]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libarchive/libarchive/archive_read_support_format_mtree.c
MFV r245512:
[FreeBSD/FreeBSD.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 Michihiro NAKAJIMA
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "archive_platform.h"
29 __FBSDID("$FreeBSD$");
30
31 #ifdef HAVE_SYS_STAT_H
32 #include <sys/stat.h>
33 #endif
34 #ifdef HAVE_ERRNO_H
35 #include <errno.h>
36 #endif
37 #ifdef HAVE_FCNTL_H
38 #include <fcntl.h>
39 #endif
40 #include <stddef.h>
41 /* #include <stdint.h> */ /* See archive_platform.h */
42 #ifdef HAVE_STDLIB_H
43 #include <stdlib.h>
44 #endif
45 #ifdef HAVE_STRING_H
46 #include <string.h>
47 #endif
48
49 #include "archive.h"
50 #include "archive_entry.h"
51 #include "archive_private.h"
52 #include "archive_read_private.h"
53 #include "archive_string.h"
54
55 #ifndef O_BINARY
56 #define O_BINARY 0
57 #endif
58
59 #define MTREE_HAS_DEVICE        0x0001
60 #define MTREE_HAS_FFLAGS        0x0002
61 #define MTREE_HAS_GID           0x0004
62 #define MTREE_HAS_GNAME         0x0008
63 #define MTREE_HAS_MTIME         0x0010
64 #define MTREE_HAS_NLINK         0x0020
65 #define MTREE_HAS_PERM          0x0040
66 #define MTREE_HAS_SIZE          0x0080
67 #define MTREE_HAS_TYPE          0x0100
68 #define MTREE_HAS_UID           0x0200
69 #define MTREE_HAS_UNAME         0x0400
70
71 #define MTREE_HAS_OPTIONAL      0x0800
72
73 struct mtree_option {
74         struct mtree_option *next;
75         char *value;
76 };
77
78 struct mtree_entry {
79         struct mtree_entry *next;
80         struct mtree_option *options;
81         char *name;
82         char full;
83         char used;
84 };
85
86 struct mtree {
87         struct archive_string    line;
88         size_t                   buffsize;
89         char                    *buff;
90         int64_t                  offset;
91         int                      fd;
92         int                      archive_format;
93         const char              *archive_format_name;
94         struct mtree_entry      *entries;
95         struct mtree_entry      *this_entry;
96         struct archive_string    current_dir;
97         struct archive_string    contents_name;
98
99         struct archive_entry_linkresolver *resolver;
100
101         int64_t                  cur_size;
102 };
103
104 static int      bid_keycmp(const char *, const char *, ssize_t);
105 static int      cleanup(struct archive_read *);
106 static int      mtree_bid(struct archive_read *, int);
107 static int      parse_file(struct archive_read *, struct archive_entry *,
108                     struct mtree *, struct mtree_entry *, int *);
109 static void     parse_escapes(char *, struct mtree_entry *);
110 static int      parse_line(struct archive_read *, struct archive_entry *,
111                     struct mtree *, struct mtree_entry *, int *);
112 static int      parse_keyword(struct archive_read *, struct mtree *,
113                     struct archive_entry *, struct mtree_option *, int *);
114 static int      read_data(struct archive_read *a,
115                     const void **buff, size_t *size, int64_t *offset);
116 static ssize_t  readline(struct archive_read *, struct mtree *, char **, ssize_t);
117 static int      skip(struct archive_read *a);
118 static int      read_header(struct archive_read *,
119                     struct archive_entry *);
120 static int64_t  mtree_atol10(char **);
121 static int64_t  mtree_atol8(char **);
122 static int64_t  mtree_atol(char **);
123
124 /*
125  * There's no standard for TIME_T_MAX/TIME_T_MIN.  So we compute them
126  * here.  TODO: Move this to configure time, but be careful
127  * about cross-compile environments.
128  */
129 static int64_t
130 get_time_t_max(void)
131 {
132 #if defined(TIME_T_MAX)
133         return TIME_T_MAX;
134 #else
135         static time_t t;
136         time_t a;
137         if (t == 0) {
138                 a = 1;
139                 while (a > t) {
140                         t = a;
141                         a = a * 2 + 1;
142                 }
143         }
144         return t;
145 #endif
146 }
147
148 static int64_t
149 get_time_t_min(void)
150 {
151 #if defined(TIME_T_MIN)
152         return TIME_T_MIN;
153 #else
154         /* 't' will hold the minimum value, which will be zero (if
155          * time_t is unsigned) or -2^n (if time_t is signed). */
156         static int computed;
157         static time_t t;
158         time_t a;
159         if (computed == 0) {
160                 a = (time_t)-1;
161                 while (a < t) {
162                         t = a;
163                         a = a * 2;
164                 }                       
165                 computed = 1;
166         }
167         return t;
168 #endif
169 }
170
171 static void
172 free_options(struct mtree_option *head)
173 {
174         struct mtree_option *next;
175
176         for (; head != NULL; head = next) {
177                 next = head->next;
178                 free(head->value);
179                 free(head);
180         }
181 }
182
183 int
184 archive_read_support_format_mtree(struct archive *_a)
185 {
186         struct archive_read *a = (struct archive_read *)_a;
187         struct mtree *mtree;
188         int r;
189
190         archive_check_magic(_a, ARCHIVE_READ_MAGIC,
191             ARCHIVE_STATE_NEW, "archive_read_support_format_mtree");
192
193         mtree = (struct mtree *)malloc(sizeof(*mtree));
194         if (mtree == NULL) {
195                 archive_set_error(&a->archive, ENOMEM,
196                     "Can't allocate mtree data");
197                 return (ARCHIVE_FATAL);
198         }
199         memset(mtree, 0, sizeof(*mtree));
200         mtree->fd = -1;
201
202         r = __archive_read_register_format(a, mtree, "mtree",
203             mtree_bid, NULL, read_header, read_data, skip, cleanup);
204
205         if (r != ARCHIVE_OK)
206                 free(mtree);
207         return (ARCHIVE_OK);
208 }
209
210 static int
211 cleanup(struct archive_read *a)
212 {
213         struct mtree *mtree;
214         struct mtree_entry *p, *q;
215
216         mtree = (struct mtree *)(a->format->data);
217
218         p = mtree->entries;
219         while (p != NULL) {
220                 q = p->next;
221                 free(p->name);
222                 free_options(p->options);
223                 free(p);
224                 p = q;
225         }
226         archive_string_free(&mtree->line);
227         archive_string_free(&mtree->current_dir);
228         archive_string_free(&mtree->contents_name);
229         archive_entry_linkresolver_free(mtree->resolver);
230
231         free(mtree->buff);
232         free(mtree);
233         (a->format->data) = NULL;
234         return (ARCHIVE_OK);
235 }
236
237 static ssize_t
238 get_line_size(const char *b, ssize_t avail, ssize_t *nlsize)
239 {
240         ssize_t len;
241
242         len = 0;
243         while (len < avail) {
244                 switch (*b) {
245                 case '\0':/* Non-ascii character or control character. */
246                         if (nlsize != NULL)
247                                 *nlsize = 0;
248                         return (-1);
249                 case '\r':
250                         if (avail-len > 1 && b[1] == '\n') {
251                                 if (nlsize != NULL)
252                                         *nlsize = 2;
253                                 return (len+2);
254                         }
255                         /* FALL THROUGH */
256                 case '\n':
257                         if (nlsize != NULL)
258                                 *nlsize = 1;
259                         return (len+1);
260                 default:
261                         b++;
262                         len++;
263                         break;
264                 }
265         }
266         if (nlsize != NULL)
267                 *nlsize = 0;
268         return (avail);
269 }
270
271 static ssize_t
272 next_line(struct archive_read *a,
273     const char **b, ssize_t *avail, ssize_t *ravail, ssize_t *nl)
274 {
275         ssize_t len;
276         int quit;
277         
278         quit = 0;
279         if (*avail == 0) {
280                 *nl = 0;
281                 len = 0;
282         } else
283                 len = get_line_size(*b, *avail, nl);
284         /*
285          * Read bytes more while it does not reach the end of line.
286          */
287         while (*nl == 0 && len == *avail && !quit) {
288                 ssize_t diff = *ravail - *avail;
289                 size_t nbytes_req = (*ravail+1023) & ~1023U;
290                 ssize_t tested;
291
292                 /* Increase reading bytes if it is not enough to at least
293                  * new two lines. */
294                 if (nbytes_req < (size_t)*ravail + 160)
295                         nbytes_req <<= 1;
296
297                 *b = __archive_read_ahead(a, nbytes_req, avail);
298                 if (*b == NULL) {
299                         if (*ravail >= *avail)
300                                 return (0);
301                         /* Reading bytes reaches the end of file. */
302                         *b = __archive_read_ahead(a, *avail, avail);
303                         quit = 1;
304                 }
305                 *ravail = *avail;
306                 *b += diff;
307                 *avail -= diff;
308                 tested = len;/* Skip some bytes we already determinated. */
309                 len = get_line_size(*b, *avail, nl);
310                 if (len >= 0)
311                         len += tested;
312         }
313         return (len);
314 }
315
316 /*
317  * Compare characters with a mtree keyword.
318  * Returns the length of a mtree keyword if matched.
319  * Returns 0 if not matched.
320  */
321 static int
322 bid_keycmp(const char *p, const char *key, ssize_t len)
323 {
324         int match_len = 0;
325
326         while (len > 0 && *p && *key) {
327                 if (*p == *key) {
328                         --len;
329                         ++p;
330                         ++key;
331                         ++match_len;
332                         continue;
333                 }
334                 return (0);/* Not match */
335         }
336         if (*key != '\0')
337                 return (0);/* Not match */
338
339         /* A following character should be specified characters */
340         if (p[0] == '=' || p[0] == ' ' || p[0] == '\t' ||
341             p[0] == '\n' || p[0] == '\r' ||
342            (p[0] == '\\' && (p[1] == '\n' || p[1] == '\r')))
343                 return (match_len);
344         return (0);/* Not match */
345 }
346
347 /*
348  * Test whether the characters 'p' has is mtree keyword.
349  * Returns the length of a detected keyword.
350  * Returns 0 if any keywords were not found.
351  */
352 static ssize_t
353 bid_keyword(const char *p,  ssize_t len)
354 {
355         static const char *keys_c[] = {
356                 "content", "contents", "cksum", NULL
357         };
358         static const char *keys_df[] = {
359                 "device", "flags", NULL
360         };
361         static const char *keys_g[] = {
362                 "gid", "gname", NULL
363         };
364         static const char *keys_il[] = {
365                 "ignore", "link", NULL
366         };
367         static const char *keys_m[] = {
368                 "md5", "md5digest", "mode", NULL
369         };
370         static const char *keys_no[] = {
371                 "nlink", "optional", NULL
372         };
373         static const char *keys_r[] = {
374                 "rmd160", "rmd160digest", NULL
375         };
376         static const char *keys_s[] = {
377                 "sha1", "sha1digest",
378                 "sha256", "sha256digest",
379                 "sha384", "sha384digest",
380                 "sha512", "sha512digest",
381                 "size", NULL
382         };
383         static const char *keys_t[] = {
384                 "tags", "time", "type", NULL
385         };
386         static const char *keys_u[] = {
387                 "uid", "uname", NULL
388         };
389         const char **keys;
390         int i;
391
392         switch (*p) {
393         case 'c': keys = keys_c; break;
394         case 'd': case 'f': keys = keys_df; break;
395         case 'g': keys = keys_g; break;
396         case 'i': case 'l': keys = keys_il; break;
397         case 'm': keys = keys_m; break;
398         case 'n': case 'o': keys = keys_no; break;
399         case 'r': keys = keys_r; break;
400         case 's': keys = keys_s; break;
401         case 't': keys = keys_t; break;
402         case 'u': keys = keys_u; break;
403         default: return (0);/* Unknown key */
404         }
405
406         for (i = 0; keys[i] != NULL; i++) {
407                 int l = bid_keycmp(p, keys[i], len);
408                 if (l > 0)
409                         return (l);
410         }
411         return (0);/* Unknown key */
412 }
413
414 /*
415  * Test whether there is a set of mtree keywords.
416  * Returns the number of keyword.
417  * Returns -1 if we got incorrect sequence.
418  * This function expects a set of "<space characters>keyword=value".
419  * When "unset" is specified, expects a set of "<space characters>keyword".
420  */
421 static int
422 bid_keyword_list(const char *p,  ssize_t len, int unset)
423 {
424         int l;
425         int keycnt = 0;
426
427         while (len > 0 && *p) {
428                 int blank = 0;
429
430                 /* Test whether there are blank characters in the line. */
431                 while (len >0 && (*p == ' ' || *p == '\t')) {
432                         ++p;
433                         --len;
434                         blank = 1;
435                 }
436                 if (*p == '\n' || *p == '\r')
437                         break;
438                 if (p[0] == '\\' && (p[1] == '\n' || p[1] == '\r'))
439                         break;
440                 if (!blank) /* No blank character. */
441                         return (-1);
442
443                 if (unset) {
444                         l = bid_keycmp(p, "all", len);
445                         if (l > 0)
446                                 return (1);
447                 }
448                 /* Test whether there is a correct key in the line. */
449                 l = bid_keyword(p, len);
450                 if (l == 0)
451                         return (-1);/* Unknown keyword was found. */
452                 p += l;
453                 len -= l;
454                 keycnt++;
455
456                 /* Skip value */
457                 if (*p == '=') {
458                         int value = 0;
459                         ++p;
460                         --len;
461                         while (len > 0 && *p != ' ' && *p != '\t') {
462                                 ++p;
463                                 --len;
464                                 value = 1;
465                         }
466                         /* A keyword should have a its value unless
467                          * "/unset" operation. */ 
468                         if (!unset && value == 0)
469                                 return (-1);
470                 }
471         }
472         return (keycnt);
473 }
474
475 static int
476 bid_entry(const char *p, ssize_t len)
477 {
478         int f = 0;
479         static const unsigned char safe_char[256] = {
480                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */
481                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
482                 /* !"$%&'()*+,-./  EXCLUSION:( )(#) */
483                 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
484                 /* 0123456789:;<>?  EXCLUSION:(=) */
485                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, /* 30 - 3F */
486                 /* @ABCDEFGHIJKLMNO */
487                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
488                 /* PQRSTUVWXYZ[\]^_  */
489                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
490                 /* `abcdefghijklmno */
491                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
492                 /* pqrstuvwxyz{|}~ */
493                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */
494                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
495                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
496                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
497                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
498                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
499                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
500                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
501                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
502         };
503
504         /*
505          * Skip the path-name which is quoted.
506          */
507         while (len > 0 && *p != ' ' && *p != '\t') {
508                 if (!safe_char[*(const unsigned char *)p])
509                         return (-1);
510                 ++p;
511                 --len;
512                 ++f;
513         }
514         /* If a path-name was not found, returns error. */
515         if (f == 0)
516                 return (-1);
517
518         return (bid_keyword_list(p, len, 0));
519 }
520
521 #define MAX_BID_ENTRY   3
522
523 static int
524 mtree_bid(struct archive_read *a, int best_bid)
525 {
526         const char *signature = "#mtree";
527         const char *p;
528         ssize_t avail, ravail;
529         ssize_t len, nl;
530         int detected_bytes = 0, entry_cnt = 0, multiline = 0;
531
532         (void)best_bid; /* UNUSED */
533
534         /* Now let's look at the actual header and see if it matches. */
535         p = __archive_read_ahead(a, strlen(signature), &avail);
536         if (p == NULL)
537                 return (-1);
538
539         if (memcmp(p, signature, strlen(signature)) == 0)
540                 return (8 * (int)strlen(signature));
541
542         /*
543          * There is not a mtree signature. Let's try to detect mtree format.
544          */
545         ravail = avail;
546         for (;;) {
547                 len = next_line(a, &p, &avail, &ravail, &nl);
548                 /* The terminal character of the line should be
549                  * a new line character, '\r\n' or '\n'. */
550                 if (len <= 0 || nl == 0)
551                         break;
552                 if (!multiline) {
553                         /* Leading whitespace is never significant,
554                          * ignore it. */
555                         while (len > 0 && (*p == ' ' || *p == '\t')) {
556                                 ++p;
557                                 --avail;
558                                 --len;
559                         }
560                         /* Skip comment or empty line. */ 
561                         if (p[0] == '#' || p[0] == '\n' || p[0] == '\r') {
562                                 p += len;
563                                 avail -= len;
564                                 continue;
565                         }
566                 } else {
567                         /* A continuance line; the terminal
568                          * character of previous line was '\' character. */
569                         if (bid_keyword_list(p, len, 0) <= 0)
570                                 break;
571                         if (multiline == 1)
572                                 detected_bytes += len;
573                         if (p[len-nl-1] != '\\') {
574                                 if (multiline == 1 &&
575                                     ++entry_cnt >= MAX_BID_ENTRY)
576                                         break;
577                                 multiline = 0;
578                         }
579                         p += len;
580                         avail -= len;
581                         continue;
582                 }
583                 if (p[0] != '/') {
584                         if (bid_entry(p, len) >= 0) {
585                                 detected_bytes += len;
586                                 if (p[len-nl-1] == '\\')
587                                         /* This line continues. */
588                                         multiline = 1;
589                                 else {
590                                         /* We've got plenty of correct lines
591                                          * to assume that this file is a mtree
592                                          * format. */
593                                         if (++entry_cnt >= MAX_BID_ENTRY)
594                                                 break;
595                                 }
596                         } else
597                                 break;
598                 } else if (strncmp(p, "/set", 4) == 0) {
599                         if (bid_keyword_list(p+4, len-4, 0) <= 0)
600                                 break;
601                         /* This line continues. */
602                         if (p[len-nl-1] == '\\')
603                                 multiline = 2;
604                 } else if (strncmp(p, "/unset", 6) == 0) {
605                         if (bid_keyword_list(p+6, len-6, 1) <= 0)
606                                 break;
607                         /* This line continues. */
608                         if (p[len-nl-1] == '\\')
609                                 multiline = 2;
610                 } else
611                         break;
612
613                 /* Test next line. */
614                 p += len;
615                 avail -= len;
616         }
617         if (entry_cnt >= MAX_BID_ENTRY || (entry_cnt > 0 && len == 0))
618                 return (32);
619
620         return (0);
621 }
622
623 /*
624  * The extended mtree format permits multiple lines specifying
625  * attributes for each file.  For those entries, only the last line
626  * is actually used.  Practically speaking, that means we have
627  * to read the entire mtree file into memory up front.
628  *
629  * The parsing is done in two steps.  First, it is decided if a line
630  * changes the global defaults and if it is, processed accordingly.
631  * Otherwise, the options of the line are merged with the current
632  * global options.
633  */
634 static int
635 add_option(struct archive_read *a, struct mtree_option **global,
636     const char *value, size_t len)
637 {
638         struct mtree_option *opt;
639
640         if ((opt = malloc(sizeof(*opt))) == NULL) {
641                 archive_set_error(&a->archive, errno, "Can't allocate memory");
642                 return (ARCHIVE_FATAL);
643         }
644         if ((opt->value = malloc(len + 1)) == NULL) {
645                 free(opt);
646                 archive_set_error(&a->archive, errno, "Can't allocate memory");
647                 return (ARCHIVE_FATAL);
648         }
649         memcpy(opt->value, value, len);
650         opt->value[len] = '\0';
651         opt->next = *global;
652         *global = opt;
653         return (ARCHIVE_OK);
654 }
655
656 static void
657 remove_option(struct mtree_option **global, const char *value, size_t len)
658 {
659         struct mtree_option *iter, *last;
660
661         last = NULL;
662         for (iter = *global; iter != NULL; last = iter, iter = iter->next) {
663                 if (strncmp(iter->value, value, len) == 0 &&
664                     (iter->value[len] == '\0' ||
665                      iter->value[len] == '='))
666                         break;
667         }
668         if (iter == NULL)
669                 return;
670         if (last == NULL)
671                 *global = iter->next;
672         else
673                 last->next = iter->next;
674
675         free(iter->value);
676         free(iter);
677 }
678
679 static int
680 process_global_set(struct archive_read *a,
681     struct mtree_option **global, const char *line)
682 {
683         const char *next, *eq;
684         size_t len;
685         int r;
686
687         line += 4;
688         for (;;) {
689                 next = line + strspn(line, " \t\r\n");
690                 if (*next == '\0')
691                         return (ARCHIVE_OK);
692                 line = next;
693                 next = line + strcspn(line, " \t\r\n");
694                 eq = strchr(line, '=');
695                 if (eq > next)
696                         len = next - line;
697                 else
698                         len = eq - line;
699
700                 remove_option(global, line, len);
701                 r = add_option(a, global, line, next - line);
702                 if (r != ARCHIVE_OK)
703                         return (r);
704                 line = next;
705         }
706 }
707
708 static int
709 process_global_unset(struct archive_read *a,
710     struct mtree_option **global, const char *line)
711 {
712         const char *next;
713         size_t len;
714
715         line += 6;
716         if (strchr(line, '=') != NULL) {
717                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
718                     "/unset shall not contain `='");
719                 return ARCHIVE_FATAL;
720         }
721
722         for (;;) {
723                 next = line + strspn(line, " \t\r\n");
724                 if (*next == '\0')
725                         return (ARCHIVE_OK);
726                 line = next;
727                 len = strcspn(line, " \t\r\n");
728
729                 if (len == 3 && strncmp(line, "all", 3) == 0) {
730                         free_options(*global);
731                         *global = NULL;
732                 } else {
733                         remove_option(global, line, len);
734                 }
735
736                 line += len;
737         }
738 }
739
740 static int
741 process_add_entry(struct archive_read *a, struct mtree *mtree,
742     struct mtree_option **global, const char *line,
743     struct mtree_entry **last_entry)
744 {
745         struct mtree_entry *entry;
746         struct mtree_option *iter;
747         const char *next, *eq;
748         size_t len;
749         int r;
750
751         if ((entry = malloc(sizeof(*entry))) == NULL) {
752                 archive_set_error(&a->archive, errno, "Can't allocate memory");
753                 return (ARCHIVE_FATAL);
754         }
755         entry->next = NULL;
756         entry->options = NULL;
757         entry->name = NULL;
758         entry->used = 0;
759         entry->full = 0;
760
761         /* Add this entry to list. */
762         if (*last_entry == NULL)
763                 mtree->entries = entry;
764         else
765                 (*last_entry)->next = entry;
766         *last_entry = entry;
767
768         len = strcspn(line, " \t\r\n");
769         if ((entry->name = malloc(len + 1)) == NULL) {
770                 archive_set_error(&a->archive, errno, "Can't allocate memory");
771                 return (ARCHIVE_FATAL);
772         }
773
774         memcpy(entry->name, line, len);
775         entry->name[len] = '\0';
776         parse_escapes(entry->name, entry);
777
778         line += len;
779         for (iter = *global; iter != NULL; iter = iter->next) {
780                 r = add_option(a, &entry->options, iter->value,
781                     strlen(iter->value));
782                 if (r != ARCHIVE_OK)
783                         return (r);
784         }
785
786         for (;;) {
787                 next = line + strspn(line, " \t\r\n");
788                 if (*next == '\0')
789                         return (ARCHIVE_OK);
790                 line = next;
791                 next = line + strcspn(line, " \t\r\n");
792                 eq = strchr(line, '=');
793                 if (eq == NULL || eq > next)
794                         len = next - line;
795                 else
796                         len = eq - line;
797
798                 remove_option(&entry->options, line, len);
799                 r = add_option(a, &entry->options, line, next - line);
800                 if (r != ARCHIVE_OK)
801                         return (r);
802                 line = next;
803         }
804 }
805
806 static int
807 read_mtree(struct archive_read *a, struct mtree *mtree)
808 {
809         ssize_t len;
810         uintmax_t counter;
811         char *p;
812         struct mtree_option *global;
813         struct mtree_entry *last_entry;
814         int r;
815
816         mtree->archive_format = ARCHIVE_FORMAT_MTREE;
817         mtree->archive_format_name = "mtree";
818
819         global = NULL;
820         last_entry = NULL;
821
822         for (counter = 1; ; ++counter) {
823                 len = readline(a, mtree, &p, 65536);
824                 if (len == 0) {
825                         mtree->this_entry = mtree->entries;
826                         free_options(global);
827                         return (ARCHIVE_OK);
828                 }
829                 if (len < 0) {
830                         free_options(global);
831                         return (len);
832                 }
833                 /* Leading whitespace is never significant, ignore it. */
834                 while (*p == ' ' || *p == '\t') {
835                         ++p;
836                         --len;
837                 }
838                 /* Skip content lines and blank lines. */
839                 if (*p == '#')
840                         continue;
841                 if (*p == '\r' || *p == '\n' || *p == '\0')
842                         continue;
843                 if (*p != '/') {
844                         r = process_add_entry(a, mtree, &global, p,
845                             &last_entry);
846                 } else if (strncmp(p, "/set", 4) == 0) {
847                         if (p[4] != ' ' && p[4] != '\t')
848                                 break;
849                         r = process_global_set(a, &global, p);
850                 } else if (strncmp(p, "/unset", 6) == 0) {
851                         if (p[6] != ' ' && p[6] != '\t')
852                                 break;
853                         r = process_global_unset(a, &global, p);
854                 } else
855                         break;
856
857                 if (r != ARCHIVE_OK) {
858                         free_options(global);
859                         return r;
860                 }
861         }
862
863         archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
864             "Can't parse line %ju", counter);
865         free_options(global);
866         return (ARCHIVE_FATAL);
867 }
868
869 /*
870  * Read in the entire mtree file into memory on the first request.
871  * Then use the next unused file to satisfy each header request.
872  */
873 static int
874 read_header(struct archive_read *a, struct archive_entry *entry)
875 {
876         struct mtree *mtree;
877         char *p;
878         int r, use_next;
879
880         mtree = (struct mtree *)(a->format->data);
881
882         if (mtree->fd >= 0) {
883                 close(mtree->fd);
884                 mtree->fd = -1;
885         }
886
887         if (mtree->entries == NULL) {
888                 mtree->resolver = archive_entry_linkresolver_new();
889                 if (mtree->resolver == NULL)
890                         return ARCHIVE_FATAL;
891                 archive_entry_linkresolver_set_strategy(mtree->resolver,
892                     ARCHIVE_FORMAT_MTREE);
893                 r = read_mtree(a, mtree);
894                 if (r != ARCHIVE_OK)
895                         return (r);
896         }
897
898         a->archive.archive_format = mtree->archive_format;
899         a->archive.archive_format_name = mtree->archive_format_name;
900
901         for (;;) {
902                 if (mtree->this_entry == NULL)
903                         return (ARCHIVE_EOF);
904                 if (strcmp(mtree->this_entry->name, "..") == 0) {
905                         mtree->this_entry->used = 1;
906                         if (archive_strlen(&mtree->current_dir) > 0) {
907                                 /* Roll back current path. */
908                                 p = mtree->current_dir.s
909                                     + mtree->current_dir.length - 1;
910                                 while (p >= mtree->current_dir.s && *p != '/')
911                                         --p;
912                                 if (p >= mtree->current_dir.s)
913                                         --p;
914                                 mtree->current_dir.length
915                                     = p - mtree->current_dir.s + 1;
916                         }
917                 }
918                 if (!mtree->this_entry->used) {
919                         use_next = 0;
920                         r = parse_file(a, entry, mtree, mtree->this_entry, &use_next);
921                         if (use_next == 0)
922                                 return (r);
923                 }
924                 mtree->this_entry = mtree->this_entry->next;
925         }
926 }
927
928 /*
929  * A single file can have multiple lines contribute specifications.
930  * Parse as many lines as necessary, then pull additional information
931  * from a backing file on disk as necessary.
932  */
933 static int
934 parse_file(struct archive_read *a, struct archive_entry *entry,
935     struct mtree *mtree, struct mtree_entry *mentry, int *use_next)
936 {
937         const char *path;
938         struct stat st_storage, *st;
939         struct mtree_entry *mp;
940         struct archive_entry *sparse_entry;
941         int r = ARCHIVE_OK, r1, parsed_kws;
942
943         mentry->used = 1;
944
945         /* Initialize reasonable defaults. */
946         archive_entry_set_filetype(entry, AE_IFREG);
947         archive_entry_set_size(entry, 0);
948         archive_string_empty(&mtree->contents_name);
949
950         /* Parse options from this line. */
951         parsed_kws = 0;
952         r = parse_line(a, entry, mtree, mentry, &parsed_kws);
953
954         if (mentry->full) {
955                 archive_entry_copy_pathname(entry, mentry->name);
956                 /*
957                  * "Full" entries are allowed to have multiple lines
958                  * and those lines aren't required to be adjacent.  We
959                  * don't support multiple lines for "relative" entries
960                  * nor do we make any attempt to merge data from
961                  * separate "relative" and "full" entries.  (Merging
962                  * "relative" and "full" entries would require dealing
963                  * with pathname canonicalization, which is a very
964                  * tricky subject.)
965                  */
966                 for (mp = mentry->next; mp != NULL; mp = mp->next) {
967                         if (mp->full && !mp->used
968                             && strcmp(mentry->name, mp->name) == 0) {
969                                 /* Later lines override earlier ones. */
970                                 mp->used = 1;
971                                 r1 = parse_line(a, entry, mtree, mp,
972                                     &parsed_kws);
973                                 if (r1 < r)
974                                         r = r1;
975                         }
976                 }
977         } else {
978                 /*
979                  * Relative entries require us to construct
980                  * the full path and possibly update the
981                  * current directory.
982                  */
983                 size_t n = archive_strlen(&mtree->current_dir);
984                 if (n > 0)
985                         archive_strcat(&mtree->current_dir, "/");
986                 archive_strcat(&mtree->current_dir, mentry->name);
987                 archive_entry_copy_pathname(entry, mtree->current_dir.s);
988                 if (archive_entry_filetype(entry) != AE_IFDIR)
989                         mtree->current_dir.length = n;
990         }
991
992         /*
993          * Try to open and stat the file to get the real size
994          * and other file info.  It would be nice to avoid
995          * this here so that getting a listing of an mtree
996          * wouldn't require opening every referenced contents
997          * file.  But then we wouldn't know the actual
998          * contents size, so I don't see a really viable way
999          * around this.  (Also, we may want to someday pull
1000          * other unspecified info from the contents file on
1001          * disk.)
1002          */
1003         mtree->fd = -1;
1004         if (archive_strlen(&mtree->contents_name) > 0)
1005                 path = mtree->contents_name.s;
1006         else
1007                 path = archive_entry_pathname(entry);
1008
1009         if (archive_entry_filetype(entry) == AE_IFREG ||
1010             archive_entry_filetype(entry) == AE_IFDIR) {
1011                 mtree->fd = open(path, O_RDONLY | O_BINARY);
1012                 if (mtree->fd == -1 &&
1013                     (errno != ENOENT ||
1014                      archive_strlen(&mtree->contents_name) > 0)) {
1015                         archive_set_error(&a->archive, errno,
1016                             "Can't open %s", path);
1017                         r = ARCHIVE_WARN;
1018                 }
1019         }
1020
1021         st = &st_storage;
1022         if (mtree->fd >= 0) {
1023                 if (fstat(mtree->fd, st) == -1) {
1024                         archive_set_error(&a->archive, errno,
1025                             "Could not fstat %s", path);
1026                         r = ARCHIVE_WARN;
1027                         /* If we can't stat it, don't keep it open. */
1028                         close(mtree->fd);
1029                         mtree->fd = -1;
1030                         st = NULL;
1031                 }
1032         } else if (lstat(path, st) == -1) {
1033                 st = NULL;
1034         }
1035
1036         /*
1037          * Check for a mismatch between the type in the specification and
1038          * the type of the contents object on disk.
1039          */
1040         if (st != NULL) {
1041                 if (
1042                     ((st->st_mode & S_IFMT) == S_IFREG &&
1043                      archive_entry_filetype(entry) == AE_IFREG)
1044 #ifdef S_IFLNK
1045                     || ((st->st_mode & S_IFMT) == S_IFLNK &&
1046                         archive_entry_filetype(entry) == AE_IFLNK)
1047 #endif
1048 #ifdef S_IFSOCK
1049                     || ((st->st_mode & S_IFSOCK) == S_IFSOCK &&
1050                         archive_entry_filetype(entry) == AE_IFSOCK)
1051 #endif
1052 #ifdef S_IFCHR
1053                     || ((st->st_mode & S_IFMT) == S_IFCHR &&
1054                         archive_entry_filetype(entry) == AE_IFCHR)
1055 #endif
1056 #ifdef S_IFBLK
1057                     || ((st->st_mode & S_IFMT) == S_IFBLK &&
1058                         archive_entry_filetype(entry) == AE_IFBLK)
1059 #endif
1060                     || ((st->st_mode & S_IFMT) == S_IFDIR &&
1061                         archive_entry_filetype(entry) == AE_IFDIR)
1062 #ifdef S_IFIFO
1063                     || ((st->st_mode & S_IFMT) == S_IFIFO &&
1064                         archive_entry_filetype(entry) == AE_IFIFO)
1065 #endif
1066                     ) {
1067                         /* Types match. */
1068                 } else {
1069                         /* Types don't match; bail out gracefully. */
1070                         if (mtree->fd >= 0)
1071                                 close(mtree->fd);
1072                         mtree->fd = -1;
1073                         if (parsed_kws & MTREE_HAS_OPTIONAL) {
1074                                 /* It's not an error for an optional entry
1075                                    to not match disk. */
1076                                 *use_next = 1;
1077                         } else if (r == ARCHIVE_OK) {
1078                                 archive_set_error(&a->archive,
1079                                     ARCHIVE_ERRNO_MISC,
1080                                     "mtree specification has different type for %s",
1081                                     archive_entry_pathname(entry));
1082                                 r = ARCHIVE_WARN;
1083                         }
1084                         return r;
1085                 }
1086         }
1087
1088         /*
1089          * If there is a contents file on disk, pick some of the metadata
1090          * from that file.  For most of these, we only set it from the contents
1091          * if it wasn't already parsed from the specification.
1092          */
1093         if (st != NULL) {
1094                 if ((parsed_kws & MTREE_HAS_DEVICE) == 0 &&
1095                     (archive_entry_filetype(entry) == AE_IFCHR ||
1096                      archive_entry_filetype(entry) == AE_IFBLK))
1097                         archive_entry_set_rdev(entry, st->st_rdev);
1098                 if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME)) == 0)
1099                         archive_entry_set_gid(entry, st->st_gid);
1100                 if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME)) == 0)
1101                         archive_entry_set_uid(entry, st->st_uid);
1102                 if ((parsed_kws & MTREE_HAS_MTIME) == 0) {
1103 #if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
1104                         archive_entry_set_mtime(entry, st->st_mtime,
1105                             st->st_mtimespec.tv_nsec);
1106 #elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
1107                         archive_entry_set_mtime(entry, st->st_mtime,
1108                             st->st_mtim.tv_nsec);
1109 #elif HAVE_STRUCT_STAT_ST_MTIME_N
1110                         archive_entry_set_mtime(entry, st->st_mtime,
1111                             st->st_mtime_n);
1112 #elif HAVE_STRUCT_STAT_ST_UMTIME
1113                         archive_entry_set_mtime(entry, st->st_mtime,
1114                             st->st_umtime*1000);
1115 #elif HAVE_STRUCT_STAT_ST_MTIME_USEC
1116                         archive_entry_set_mtime(entry, st->st_mtime,
1117                             st->st_mtime_usec*1000);
1118 #else
1119                         archive_entry_set_mtime(entry, st->st_mtime, 0);
1120 #endif
1121                 }
1122                 if ((parsed_kws & MTREE_HAS_NLINK) == 0)
1123                         archive_entry_set_nlink(entry, st->st_nlink);
1124                 if ((parsed_kws & MTREE_HAS_PERM) == 0)
1125                         archive_entry_set_perm(entry, st->st_mode);
1126                 if ((parsed_kws & MTREE_HAS_SIZE) == 0)
1127                         archive_entry_set_size(entry, st->st_size);
1128                 archive_entry_set_ino(entry, st->st_ino);
1129                 archive_entry_set_dev(entry, st->st_dev);
1130
1131                 archive_entry_linkify(mtree->resolver, &entry, &sparse_entry);
1132         } else if (parsed_kws & MTREE_HAS_OPTIONAL) {
1133                 /*
1134                  * Couldn't open the entry, stat it or the on-disk type
1135                  * didn't match.  If this entry is optional, just ignore it
1136                  * and read the next header entry.
1137                  */
1138                 *use_next = 1;
1139                 return ARCHIVE_OK;
1140         }
1141
1142         mtree->cur_size = archive_entry_size(entry);
1143         mtree->offset = 0;
1144
1145         return r;
1146 }
1147
1148 /*
1149  * Each line contains a sequence of keywords.
1150  */
1151 static int
1152 parse_line(struct archive_read *a, struct archive_entry *entry,
1153     struct mtree *mtree, struct mtree_entry *mp, int *parsed_kws)
1154 {
1155         struct mtree_option *iter;
1156         int r = ARCHIVE_OK, r1;
1157
1158         for (iter = mp->options; iter != NULL; iter = iter->next) {
1159                 r1 = parse_keyword(a, mtree, entry, iter, parsed_kws);
1160                 if (r1 < r)
1161                         r = r1;
1162         }
1163         if (r == ARCHIVE_OK && (*parsed_kws & MTREE_HAS_TYPE) == 0) {
1164                 archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1165                     "Missing type keyword in mtree specification");
1166                 return (ARCHIVE_WARN);
1167         }
1168         return (r);
1169 }
1170
1171 /*
1172  * Device entries have one of the following forms:
1173  * raw dev_t
1174  * format,major,minor[,subdevice]
1175  *
1176  * Just use major and minor, no translation etc is done
1177  * between formats.
1178  */
1179 static int
1180 parse_device(struct archive *a, struct archive_entry *entry, char *val)
1181 {
1182         char *comma1, *comma2;
1183
1184         comma1 = strchr(val, ',');
1185         if (comma1 == NULL) {
1186                 archive_entry_set_dev(entry, (dev_t)mtree_atol10(&val));
1187                 return (ARCHIVE_OK);
1188         }
1189         ++comma1;
1190         comma2 = strchr(comma1, ',');
1191         if (comma2 == NULL) {
1192                 archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
1193                     "Malformed device attribute");
1194                 return (ARCHIVE_WARN);
1195         }
1196         ++comma2;
1197         archive_entry_set_rdevmajor(entry, (dev_t)mtree_atol(&comma1));
1198         archive_entry_set_rdevminor(entry, (dev_t)mtree_atol(&comma2));
1199         return (ARCHIVE_OK);
1200 }
1201
1202 /*
1203  * Parse a single keyword and its value.
1204  */
1205 static int
1206 parse_keyword(struct archive_read *a, struct mtree *mtree,
1207     struct archive_entry *entry, struct mtree_option *opt, int *parsed_kws)
1208 {
1209         char *val, *key;
1210
1211         key = opt->value;
1212
1213         if (*key == '\0')
1214                 return (ARCHIVE_OK);
1215
1216         if (strcmp(key, "optional") == 0) {
1217                 *parsed_kws |= MTREE_HAS_OPTIONAL;
1218                 return (ARCHIVE_OK);
1219         }
1220         if (strcmp(key, "ignore") == 0) {
1221                 /*
1222                  * The mtree processing is not recursive, so
1223                  * recursion will only happen for explicitly listed
1224                  * entries.
1225                  */
1226                 return (ARCHIVE_OK);
1227         }
1228
1229         val = strchr(key, '=');
1230         if (val == NULL) {
1231                 archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1232                     "Malformed attribute \"%s\" (%d)", key, key[0]);
1233                 return (ARCHIVE_WARN);
1234         }
1235
1236         *val = '\0';
1237         ++val;
1238
1239         switch (key[0]) {
1240         case 'c':
1241                 if (strcmp(key, "content") == 0
1242                     || strcmp(key, "contents") == 0) {
1243                         parse_escapes(val, NULL);
1244                         archive_strcpy(&mtree->contents_name, val);
1245                         break;
1246                 }
1247                 if (strcmp(key, "cksum") == 0)
1248                         break;
1249         case 'd':
1250                 if (strcmp(key, "device") == 0) {
1251                         *parsed_kws |= MTREE_HAS_DEVICE;
1252                         return parse_device(&a->archive, entry, val);
1253                 }
1254         case 'f':
1255                 if (strcmp(key, "flags") == 0) {
1256                         *parsed_kws |= MTREE_HAS_FFLAGS;
1257                         archive_entry_copy_fflags_text(entry, val);
1258                         break;
1259                 }
1260         case 'g':
1261                 if (strcmp(key, "gid") == 0) {
1262                         *parsed_kws |= MTREE_HAS_GID;
1263                         archive_entry_set_gid(entry, mtree_atol10(&val));
1264                         break;
1265                 }
1266                 if (strcmp(key, "gname") == 0) {
1267                         *parsed_kws |= MTREE_HAS_GNAME;
1268                         archive_entry_copy_gname(entry, val);
1269                         break;
1270                 }
1271         case 'l':
1272                 if (strcmp(key, "link") == 0) {
1273                         archive_entry_copy_symlink(entry, val);
1274                         break;
1275                 }
1276         case 'm':
1277                 if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0)
1278                         break;
1279                 if (strcmp(key, "mode") == 0) {
1280                         if (val[0] >= '0' && val[0] <= '9') {
1281                                 *parsed_kws |= MTREE_HAS_PERM;
1282                                 archive_entry_set_perm(entry,
1283                                     (mode_t)mtree_atol8(&val));
1284                         } else {
1285                                 archive_set_error(&a->archive,
1286                                     ARCHIVE_ERRNO_FILE_FORMAT,
1287                                     "Symbolic mode \"%s\" unsupported", val);
1288                                 return ARCHIVE_WARN;
1289                         }
1290                         break;
1291                 }
1292         case 'n':
1293                 if (strcmp(key, "nlink") == 0) {
1294                         *parsed_kws |= MTREE_HAS_NLINK;
1295                         archive_entry_set_nlink(entry,
1296                                 (unsigned int)mtree_atol10(&val));
1297                         break;
1298                 }
1299         case 'r':
1300                 if (strcmp(key, "rmd160") == 0 ||
1301                     strcmp(key, "rmd160digest") == 0)
1302                         break;
1303         case 's':
1304                 if (strcmp(key, "sha1") == 0 || strcmp(key, "sha1digest") == 0)
1305                         break;
1306                 if (strcmp(key, "sha256") == 0 ||
1307                     strcmp(key, "sha256digest") == 0)
1308                         break;
1309                 if (strcmp(key, "sha384") == 0 ||
1310                     strcmp(key, "sha384digest") == 0)
1311                         break;
1312                 if (strcmp(key, "sha512") == 0 ||
1313                     strcmp(key, "sha512digest") == 0)
1314                         break;
1315                 if (strcmp(key, "size") == 0) {
1316                         archive_entry_set_size(entry, mtree_atol10(&val));
1317                         break;
1318                 }
1319         case 't':
1320                 if (strcmp(key, "tags") == 0) {
1321                         /*
1322                          * Comma delimited list of tags.
1323                          * Ignore the tags for now, but the interface
1324                          * should be extended to allow inclusion/exclusion.
1325                          */
1326                         break;
1327                 }
1328                 if (strcmp(key, "time") == 0) {
1329                         int64_t m;
1330                         int64_t my_time_t_max = get_time_t_max();
1331                         int64_t my_time_t_min = get_time_t_min();
1332                         long ns;
1333
1334                         *parsed_kws |= MTREE_HAS_MTIME;
1335                         m = mtree_atol10(&val);
1336                         /* Replicate an old mtree bug:
1337                          * 123456789.1 represents 123456789
1338                          * seconds and 1 nanosecond. */
1339                         if (*val == '.') {
1340                                 ++val;
1341                                 ns = (long)mtree_atol10(&val);
1342                         } else
1343                                 ns = 0;
1344                         if (m > my_time_t_max)
1345                                 m = my_time_t_max;
1346                         else if (m < my_time_t_min)
1347                                 m = my_time_t_min;
1348                         archive_entry_set_mtime(entry, (time_t)m, ns);
1349                         break;
1350                 }
1351                 if (strcmp(key, "type") == 0) {
1352                         switch (val[0]) {
1353                         case 'b':
1354                                 if (strcmp(val, "block") == 0) {
1355                                         archive_entry_set_filetype(entry, AE_IFBLK);
1356                                         break;
1357                                 }
1358                         case 'c':
1359                                 if (strcmp(val, "char") == 0) {
1360                                         archive_entry_set_filetype(entry, AE_IFCHR);
1361                                         break;
1362                                 }
1363                         case 'd':
1364                                 if (strcmp(val, "dir") == 0) {
1365                                         archive_entry_set_filetype(entry, AE_IFDIR);
1366                                         break;
1367                                 }
1368                         case 'f':
1369                                 if (strcmp(val, "fifo") == 0) {
1370                                         archive_entry_set_filetype(entry, AE_IFIFO);
1371                                         break;
1372                                 }
1373                                 if (strcmp(val, "file") == 0) {
1374                                         archive_entry_set_filetype(entry, AE_IFREG);
1375                                         break;
1376                                 }
1377                         case 'l':
1378                                 if (strcmp(val, "link") == 0) {
1379                                         archive_entry_set_filetype(entry, AE_IFLNK);
1380                                         break;
1381                                 }
1382                         default:
1383                                 archive_set_error(&a->archive,
1384                                     ARCHIVE_ERRNO_FILE_FORMAT,
1385                                     "Unrecognized file type \"%s\"; assuming \"file\"", val);
1386                                 archive_entry_set_filetype(entry, AE_IFREG);
1387                                 return (ARCHIVE_WARN);
1388                         }
1389                         *parsed_kws |= MTREE_HAS_TYPE;
1390                         break;
1391                 }
1392         case 'u':
1393                 if (strcmp(key, "uid") == 0) {
1394                         *parsed_kws |= MTREE_HAS_UID;
1395                         archive_entry_set_uid(entry, mtree_atol10(&val));
1396                         break;
1397                 }
1398                 if (strcmp(key, "uname") == 0) {
1399                         *parsed_kws |= MTREE_HAS_UNAME;
1400                         archive_entry_copy_uname(entry, val);
1401                         break;
1402                 }
1403         default:
1404                 archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1405                     "Unrecognized key %s=%s", key, val);
1406                 return (ARCHIVE_WARN);
1407         }
1408         return (ARCHIVE_OK);
1409 }
1410
1411 static int
1412 read_data(struct archive_read *a, const void **buff, size_t *size, int64_t *offset)
1413 {
1414         size_t bytes_to_read;
1415         ssize_t bytes_read;
1416         struct mtree *mtree;
1417
1418         mtree = (struct mtree *)(a->format->data);
1419         if (mtree->fd < 0) {
1420                 *buff = NULL;
1421                 *offset = 0;
1422                 *size = 0;
1423                 return (ARCHIVE_EOF);
1424         }
1425         if (mtree->buff == NULL) {
1426                 mtree->buffsize = 64 * 1024;
1427                 mtree->buff = malloc(mtree->buffsize);
1428                 if (mtree->buff == NULL) {
1429                         archive_set_error(&a->archive, ENOMEM,
1430                             "Can't allocate memory");
1431                         return (ARCHIVE_FATAL);
1432                 }
1433         }
1434
1435         *buff = mtree->buff;
1436         *offset = mtree->offset;
1437         if ((int64_t)mtree->buffsize > mtree->cur_size - mtree->offset)
1438                 bytes_to_read = (size_t)(mtree->cur_size - mtree->offset);
1439         else
1440                 bytes_to_read = mtree->buffsize;
1441         bytes_read = read(mtree->fd, mtree->buff, bytes_to_read);
1442         if (bytes_read < 0) {
1443                 archive_set_error(&a->archive, errno, "Can't read");
1444                 return (ARCHIVE_WARN);
1445         }
1446         if (bytes_read == 0) {
1447                 *size = 0;
1448                 return (ARCHIVE_EOF);
1449         }
1450         mtree->offset += bytes_read;
1451         *size = bytes_read;
1452         return (ARCHIVE_OK);
1453 }
1454
1455 /* Skip does nothing except possibly close the contents file. */
1456 static int
1457 skip(struct archive_read *a)
1458 {
1459         struct mtree *mtree;
1460
1461         mtree = (struct mtree *)(a->format->data);
1462         if (mtree->fd >= 0) {
1463                 close(mtree->fd);
1464                 mtree->fd = -1;
1465         }
1466         return (ARCHIVE_OK);
1467 }
1468
1469 /*
1470  * Since parsing backslash sequences always makes strings shorter,
1471  * we can always do this conversion in-place.
1472  */
1473 static void
1474 parse_escapes(char *src, struct mtree_entry *mentry)
1475 {
1476         char *dest = src;
1477         char c;
1478
1479         if (mentry != NULL && strcmp(src, ".") == 0)
1480                 mentry->full = 1;
1481
1482         while (*src != '\0') {
1483                 c = *src++;
1484                 if (c == '/' && mentry != NULL)
1485                         mentry->full = 1;
1486                 if (c == '\\') {
1487                         switch (src[0]) {
1488                         case '0':
1489                                 if (src[1] < '0' || src[1] > '7') {
1490                                         c = 0;
1491                                         ++src;
1492                                         break;
1493                                 }
1494                                 /* FALLTHROUGH */
1495                         case '1':
1496                         case '2':
1497                         case '3':
1498                                 if (src[1] >= '0' && src[1] <= '7' &&
1499                                     src[2] >= '0' && src[2] <= '7') {
1500                                         c = (src[0] - '0') << 6;
1501                                         c |= (src[1] - '0') << 3;
1502                                         c |= (src[2] - '0');
1503                                         src += 3;
1504                                 }
1505                                 break;
1506                         case 'a':
1507                                 c = '\a';
1508                                 ++src;
1509                                 break;
1510                         case 'b':
1511                                 c = '\b';
1512                                 ++src;
1513                                 break;
1514                         case 'f':
1515                                 c = '\f';
1516                                 ++src;
1517                                 break;
1518                         case 'n':
1519                                 c = '\n';
1520                                 ++src;
1521                                 break;
1522                         case 'r':
1523                                 c = '\r';
1524                                 ++src;
1525                                 break;
1526                         case 's':
1527                                 c = ' ';
1528                                 ++src;
1529                                 break;
1530                         case 't':
1531                                 c = '\t';
1532                                 ++src;
1533                                 break;
1534                         case 'v':
1535                                 c = '\v';
1536                                 ++src;
1537                                 break;
1538                         }
1539                 }
1540                 *dest++ = c;
1541         }
1542         *dest = '\0';
1543 }
1544
1545 /*
1546  * Note that this implementation does not (and should not!) obey
1547  * locale settings; you cannot simply substitute strtol here, since
1548  * it does obey locale.
1549  */
1550 static int64_t
1551 mtree_atol8(char **p)
1552 {
1553         int64_t l, limit, last_digit_limit;
1554         int digit, base;
1555
1556         base = 8;
1557         limit = INT64_MAX / base;
1558         last_digit_limit = INT64_MAX % base;
1559
1560         l = 0;
1561         digit = **p - '0';
1562         while (digit >= 0 && digit < base) {
1563                 if (l>limit || (l == limit && digit > last_digit_limit)) {
1564                         l = INT64_MAX; /* Truncate on overflow. */
1565                         break;
1566                 }
1567                 l = (l * base) + digit;
1568                 digit = *++(*p) - '0';
1569         }
1570         return (l);
1571 }
1572
1573 /*
1574  * Note that this implementation does not (and should not!) obey
1575  * locale settings; you cannot simply substitute strtol here, since
1576  * it does obey locale.
1577  */
1578 static int64_t
1579 mtree_atol10(char **p)
1580 {
1581         int64_t l, limit, last_digit_limit;
1582         int base, digit, sign;
1583
1584         base = 10;
1585
1586         if (**p == '-') {
1587                 sign = -1;
1588                 limit = ((uint64_t)(INT64_MAX) + 1) / base;
1589                 last_digit_limit = ((uint64_t)(INT64_MAX) + 1) % base;
1590                 ++(*p);
1591         } else {
1592                 sign = 1;
1593                 limit = INT64_MAX / base;
1594                 last_digit_limit = INT64_MAX % base;
1595         }
1596
1597         l = 0;
1598         digit = **p - '0';
1599         while (digit >= 0 && digit < base) {
1600                 if (l > limit || (l == limit && digit > last_digit_limit))
1601                         return (sign < 0) ? INT64_MIN : INT64_MAX;
1602                 l = (l * base) + digit;
1603                 digit = *++(*p) - '0';
1604         }
1605         return (sign < 0) ? -l : l;
1606 }
1607
1608 /* Parse a hex digit. */
1609 static int
1610 parsehex(char c)
1611 {
1612         if (c >= '0' && c <= '9')
1613                 return c - '0';
1614         else if (c >= 'a' && c <= 'f')
1615                 return c - 'a';
1616         else if (c >= 'A' && c <= 'F')
1617                 return c - 'A';
1618         else
1619                 return -1;
1620 }
1621
1622 /*
1623  * Note that this implementation does not (and should not!) obey
1624  * locale settings; you cannot simply substitute strtol here, since
1625  * it does obey locale.
1626  */
1627 static int64_t
1628 mtree_atol16(char **p)
1629 {
1630         int64_t l, limit, last_digit_limit;
1631         int base, digit, sign;
1632
1633         base = 16;
1634
1635         if (**p == '-') {
1636                 sign = -1;
1637                 limit = ((uint64_t)(INT64_MAX) + 1) / base;
1638                 last_digit_limit = ((uint64_t)(INT64_MAX) + 1) % base;
1639                 ++(*p);
1640         } else {
1641                 sign = 1;
1642                 limit = INT64_MAX / base;
1643                 last_digit_limit = INT64_MAX % base;
1644         }
1645
1646         l = 0;
1647         digit = parsehex(**p);
1648         while (digit >= 0 && digit < base) {
1649                 if (l > limit || (l == limit && digit > last_digit_limit))
1650                         return (sign < 0) ? INT64_MIN : INT64_MAX;
1651                 l = (l * base) + digit;
1652                 digit = parsehex(*++(*p));
1653         }
1654         return (sign < 0) ? -l : l;
1655 }
1656
1657 static int64_t
1658 mtree_atol(char **p)
1659 {
1660         if (**p != '0')
1661                 return mtree_atol10(p);
1662         if ((*p)[1] == 'x' || (*p)[1] == 'X') {
1663                 *p += 2;
1664                 return mtree_atol16(p);
1665         }
1666         return mtree_atol8(p);
1667 }
1668
1669 /*
1670  * Returns length of line (including trailing newline)
1671  * or negative on error.  'start' argument is updated to
1672  * point to first character of line.
1673  */
1674 static ssize_t
1675 readline(struct archive_read *a, struct mtree *mtree, char **start, ssize_t limit)
1676 {
1677         ssize_t bytes_read;
1678         ssize_t total_size = 0;
1679         ssize_t find_off = 0;
1680         const void *t;
1681         const char *s;
1682         void *p;
1683         char *u;
1684
1685         /* Accumulate line in a line buffer. */
1686         for (;;) {
1687                 /* Read some more. */
1688                 t = __archive_read_ahead(a, 1, &bytes_read);
1689                 if (t == NULL)
1690                         return (0);
1691                 if (bytes_read < 0)
1692                         return (ARCHIVE_FATAL);
1693                 s = t;  /* Start of line? */
1694                 p = memchr(t, '\n', bytes_read);
1695                 /* If we found '\n', trim the read. */
1696                 if (p != NULL) {
1697                         bytes_read = 1 + ((const char *)p) - s;
1698                 }
1699                 if (total_size + bytes_read + 1 > limit) {
1700                         archive_set_error(&a->archive,
1701                             ARCHIVE_ERRNO_FILE_FORMAT,
1702                             "Line too long");
1703                         return (ARCHIVE_FATAL);
1704                 }
1705                 if (archive_string_ensure(&mtree->line,
1706                         total_size + bytes_read + 1) == NULL) {
1707                         archive_set_error(&a->archive, ENOMEM,
1708                             "Can't allocate working buffer");
1709                         return (ARCHIVE_FATAL);
1710                 }
1711                 memcpy(mtree->line.s + total_size, t, bytes_read);
1712                 __archive_read_consume(a, bytes_read);
1713                 total_size += bytes_read;
1714                 /* Null terminate. */
1715                 mtree->line.s[total_size] = '\0';
1716                 /* If we found an unescaped '\n', clean up and return. */
1717                 for (u = mtree->line.s + find_off; *u; ++u) {
1718                         if (u[0] == '\n') {
1719                                 *start = mtree->line.s;
1720                                 return total_size;
1721                         }
1722                         if (u[0] == '#') {
1723                                 if (p == NULL)
1724                                         break;
1725                                 *start = mtree->line.s;
1726                                 return total_size;
1727                         }
1728                         if (u[0] != '\\')
1729                                 continue;
1730                         if (u[1] == '\\') {
1731                                 ++u;
1732                                 continue;
1733                         }
1734                         if (u[1] == '\n') {
1735                                 memmove(u, u + 1,
1736                                     total_size - (u - mtree->line.s) + 1);
1737                                 --total_size;
1738                                 ++u;
1739                                 break;
1740                         }
1741                         if (u[1] == '\0')
1742                                 break;
1743                 }
1744                 find_off = u - mtree->line.s;
1745         }
1746 }