]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libarchive/archive_read_support_format_mtree.c
This commit was generated by cvs2svn to compensate for changes in r179404,
[FreeBSD/FreeBSD.git] / lib / libarchive / archive_read_support_format_mtree.c
1 /*-
2  * Copyright (c) 2003-2007 Tim Kientzle
3  * Copyright (c) 2008 Joerg Sonnenberger
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "archive_platform.h"
28 __FBSDID("$FreeBSD$");
29
30 #ifdef HAVE_SYS_STAT_H
31 #include <sys/stat.h>
32 #endif
33 #ifdef HAVE_ERRNO_H
34 #include <errno.h>
35 #endif
36 #ifdef HAVE_FCNTL_H
37 #include <fcntl.h>
38 #endif
39 #include <stddef.h>
40 /* #include <stdint.h> */ /* See archive_platform.h */
41 #ifdef HAVE_STDLIB_H
42 #include <stdlib.h>
43 #endif
44 #ifdef HAVE_STRING_H
45 #include <string.h>
46 #endif
47
48 #include "archive.h"
49 #include "archive_entry.h"
50 #include "archive_private.h"
51 #include "archive_read_private.h"
52 #include "archive_string.h"
53
54 #ifndef O_BINARY
55 #define O_BINARY 0
56 #endif
57
58 #define MTREE_HAS_DEVICE        0x0001
59 #define MTREE_HAS_FFLAGS        0x0002
60 #define MTREE_HAS_GID           0x0004
61 #define MTREE_HAS_GNAME         0x0008
62 #define MTREE_HAS_MTIME         0x0010
63 #define MTREE_HAS_NLINK         0x0020
64 #define MTREE_HAS_PERM          0x0040
65 #define MTREE_HAS_SIZE          0x0080
66 #define MTREE_HAS_TYPE          0x0100
67 #define MTREE_HAS_UID           0x0200
68 #define MTREE_HAS_UNAME         0x0400
69
70 #define MTREE_HAS_OPTIONAL      0x0800
71
72 struct mtree_option {
73         struct mtree_option *next;
74         char *value;
75 };
76
77 struct mtree_entry {
78         struct mtree_entry *next;
79         struct mtree_option *options;
80         char *name;
81         char full;
82         char used;
83 };
84
85 struct mtree {
86         struct archive_string    line;
87         size_t                   buffsize;
88         char                    *buff;
89         off_t                    offset;
90         int                      fd;
91         int                      filetype;
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         off_t                    cur_size, cur_offset;
102 };
103
104 static int      cleanup(struct archive_read *);
105 static int      mtree_bid(struct archive_read *);
106 static int      parse_file(struct archive_read *, struct archive_entry *,
107                     struct mtree *, struct mtree_entry *, int *);
108 static void     parse_escapes(char *, struct mtree_entry *);
109 static int      parse_line(struct archive_read *, struct archive_entry *,
110                     struct mtree *, struct mtree_entry *, int *);
111 static int      parse_keyword(struct archive_read *, struct mtree *,
112                     struct archive_entry *, struct mtree_option *, int *);
113 static int      read_data(struct archive_read *a,
114                     const void **buff, size_t *size, off_t *offset);
115 static ssize_t  readline(struct archive_read *, struct mtree *, char **, ssize_t);
116 static int      skip(struct archive_read *a);
117 static int      read_header(struct archive_read *,
118                     struct archive_entry *);
119 static int64_t  mtree_atol10(char **);
120 static int64_t  mtree_atol8(char **);
121 static int64_t  mtree_atol(char **);
122
123 static void
124 free_options(struct mtree_option *head)
125 {
126         struct mtree_option *next;
127
128         for (; head != NULL; head = next) {
129                 next = head->next;
130                 free(head->value);
131                 free(head);
132         }
133 }
134
135 int
136 archive_read_support_format_mtree(struct archive *_a)
137 {
138         struct archive_read *a = (struct archive_read *)_a;
139         struct mtree *mtree;
140         int r;
141
142         mtree = (struct mtree *)malloc(sizeof(*mtree));
143         if (mtree == NULL) {
144                 archive_set_error(&a->archive, ENOMEM,
145                     "Can't allocate mtree data");
146                 return (ARCHIVE_FATAL);
147         }
148         memset(mtree, 0, sizeof(*mtree));
149         mtree->fd = -1;
150
151         r = __archive_read_register_format(a, mtree,
152             mtree_bid, read_header, read_data, skip, cleanup);
153
154         if (r != ARCHIVE_OK)
155                 free(mtree);
156         return (ARCHIVE_OK);
157 }
158
159 static int
160 cleanup(struct archive_read *a)
161 {
162         struct mtree *mtree;
163         struct mtree_entry *p, *q;
164
165         mtree = (struct mtree *)(a->format->data);
166
167         p = mtree->entries;
168         while (p != NULL) {
169                 q = p->next;
170                 free(p->name);
171                 free_options(p->options);
172                 free(p);
173                 p = q;
174         }
175         archive_string_free(&mtree->line);
176         archive_string_free(&mtree->current_dir);
177         archive_string_free(&mtree->contents_name);
178         archive_entry_linkresolver_free(mtree->resolver);
179
180         free(mtree->buff);
181         free(mtree);
182         (a->format->data) = NULL;
183         return (ARCHIVE_OK);
184 }
185
186
187 static int
188 mtree_bid(struct archive_read *a)
189 {
190         struct mtree *mtree;
191         ssize_t bytes_read;
192         const void *h;
193         const char *signature = "#mtree";
194         const char *p;
195         int bid;
196
197         mtree = (struct mtree *)(a->format->data);
198
199         /* Now let's look at the actual header and see if it matches. */
200         bytes_read = (a->decompressor->read_ahead)(a, &h, strlen(signature));
201
202         if (bytes_read <= 0)
203                 return (bytes_read);
204
205         p = h;
206         bid = 0;
207         while (bytes_read > 0 && *signature != '\0') {
208                 if (*p != *signature)
209                         return (bid = 0);
210                 bid += 8;
211                 p++;
212                 signature++;
213                 bytes_read--;
214         }
215         return (bid);
216 }
217
218 /*
219  * The extended mtree format permits multiple lines specifying
220  * attributes for each file.  For those entries, only the last line
221  * is actually used.  Practically speaking, that means we have
222  * to read the entire mtree file into memory up front.
223  *
224  * The parsing is done in two steps.  First, it is decided if a line
225  * changes the global defaults and if it is, processed accordingly.
226  * Otherwise, the options of the line are merged with the current
227  * global options.
228  */
229 static int
230 add_option(struct archive_read *a, struct mtree_option **global,
231     const char *value, size_t len)
232 {
233         struct mtree_option *option;
234
235         if ((option = malloc(sizeof(*option))) == NULL) {
236                 archive_set_error(&a->archive, errno, "Can't allocate memory");
237                 return (ARCHIVE_FATAL);
238         }
239         if ((option->value = malloc(len + 1)) == NULL) {
240                 free(option);
241                 archive_set_error(&a->archive, errno, "Can't allocate memory");
242                 return (ARCHIVE_FATAL);
243         }
244         memcpy(option->value, value, len);
245         option->value[len] = '\0';
246         option->next = *global;
247         *global = option;
248         return (ARCHIVE_OK);
249 }
250
251 static void
252 remove_option(struct mtree_option **global, const char *value, size_t len)
253 {
254         struct mtree_option *iter, *last;
255
256         last = NULL;
257         for (iter = *global; iter != NULL; last = iter, iter = iter->next) {
258                 if (strncmp(iter->value, value, len) == 0 &&
259                     (iter->value[len] == '\0' ||
260                      iter->value[len] == '='))
261                         break;
262         }
263         if (iter == NULL)
264                 return;
265         if (last == NULL)
266                 *global = iter->next;
267         else
268                 last->next = iter->next;
269
270         free(iter->value);
271         free(iter);
272 }
273
274 static int
275 process_global_set(struct archive_read *a,
276     struct mtree_option **global, const char *line)
277 {
278         const char *next, *eq;
279         size_t len;
280         int r;
281
282         line += 4;
283         for (;;) {
284                 next = line + strspn(line, " \t\r\n");
285                 if (*next == '\0')
286                         return (ARCHIVE_OK);
287                 line = next;
288                 next = line + strcspn(line, " \t\r\n");
289                 eq = strchr(line, '=');
290                 if (eq > next)
291                         len = next - line;
292                 else
293                         len = eq - line;
294
295                 remove_option(global, line, len);
296                 r = add_option(a, global, line, next - line);
297                 if (r != ARCHIVE_OK)
298                         return (r);
299                 line = next;
300         }
301 }
302
303 static int
304 process_global_unset(struct archive_read *a,
305     struct mtree_option **global, const char *line)
306 {
307         const char *next;
308         size_t len;
309
310         line += 6;
311         if ((next = strchr(line, '=')) != NULL) {
312                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
313                     "/unset shall not contain `='");
314                 return ARCHIVE_FATAL;
315         }
316
317         for (;;) {
318                 next = line + strspn(line, " \t\r\n");
319                 if (*next == '\0')
320                         return (ARCHIVE_OK);
321                 line = next;
322                 len = strcspn(line, " \t\r\n");
323
324                 if (len == 3 && strncmp(line, "all", 3) == 0) {
325                         free_options(*global);
326                         *global = NULL;
327                 } else {
328                         remove_option(global, line, len);
329                 }
330
331                 line += len;
332         }
333 }
334
335 static int
336 process_add_entry(struct archive_read *a, struct mtree *mtree,
337     struct mtree_option **global, const char *line,
338     struct mtree_entry **last_entry)
339 {
340         struct mtree_entry *entry;
341         struct mtree_option *iter;
342         const char *next, *eq;
343         size_t len;
344         int r;
345
346         if ((entry = malloc(sizeof(*entry))) == NULL) {
347                 archive_set_error(&a->archive, errno, "Can't allocate memory");
348                 return (ARCHIVE_FATAL);
349         }
350         entry->next = NULL;
351         entry->options = NULL;
352         entry->name = NULL;
353         entry->used = 0;
354         entry->full = 0;
355
356         /* Add this entry to list. */
357         if (*last_entry == NULL)
358                 mtree->entries = entry;
359         else
360                 (*last_entry)->next = entry;
361         *last_entry = entry;
362
363         len = strcspn(line, " \t\r\n");
364         if ((entry->name = malloc(len + 1)) == NULL) {
365                 archive_set_error(&a->archive, errno, "Can't allocate memory");
366                 return (ARCHIVE_FATAL);
367         }
368
369         memcpy(entry->name, line, len);
370         entry->name[len] = '\0';
371         parse_escapes(entry->name, entry);
372
373         line += len;
374         for (iter = *global; iter != NULL; iter = iter->next) {
375                 r = add_option(a, &entry->options, iter->value,
376                     strlen(iter->value));
377                 if (r != ARCHIVE_OK)
378                         return (r);
379         }
380
381         for (;;) {
382                 next = line + strspn(line, " \t\r\n");
383                 if (*next == '\0')
384                         return (ARCHIVE_OK);
385                 line = next;
386                 next = line + strcspn(line, " \t\r\n");
387                 eq = strchr(line, '=');
388                 if (eq > next)
389                         len = next - line;
390                 else
391                         len = eq - line;
392
393                 remove_option(&entry->options, line, len);
394                 r = add_option(a, &entry->options, line, next - line);
395                 if (r != ARCHIVE_OK)
396                         return (r);
397                 line = next;
398         }
399 }
400
401 static int
402 read_mtree(struct archive_read *a, struct mtree *mtree)
403 {
404         ssize_t len;
405         uintmax_t counter;
406         char *p;
407         struct mtree_option *global;
408         struct mtree_entry *last_entry;
409         int r;
410
411         mtree->archive_format = ARCHIVE_FORMAT_MTREE_V1;
412         mtree->archive_format_name = "mtree";
413
414         global = NULL;
415         last_entry = NULL;
416         r = ARCHIVE_OK;
417
418         for (counter = 1; ; ++counter) {
419                 len = readline(a, mtree, &p, 256);
420                 if (len == 0) {
421                         mtree->this_entry = mtree->entries;
422                         return (ARCHIVE_OK);
423                 }
424                 if (len < 0)
425                         return (len);
426                 /* Leading whitespace is never significant, ignore it. */
427                 while (*p == ' ' || *p == '\t') {
428                         ++p;
429                         --len;
430                 }
431                 /* Skip content lines and blank lines. */
432                 if (*p == '#')
433                         continue;
434                 if (*p == '\r' || *p == '\n' || *p == '\0')
435                         continue;
436                 if (*p != '/') {
437                         r = process_add_entry(a, mtree, &global, p,
438                             &last_entry);
439                 } else if (strncmp(p, "/set", 4) == 0) {
440                         if (p[4] != ' ' && p[4] != '\t')
441                                 break;
442                         r = process_global_set(a, &global, p);
443                 } else if (strncmp(p, "/unset", 6) == 0) {
444                         if (p[6] != ' ' && p[6] != '\t')
445                                 break;
446                         r = process_global_unset(a, &global, p);
447                 } else
448                         break;
449
450                 if (r != ARCHIVE_OK)
451                         return r;
452         }
453
454         archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
455             "Can't parse line %ju", counter);
456         return ARCHIVE_FATAL;
457 }
458
459 /*
460  * Read in the entire mtree file into memory on the first request.
461  * Then use the next unused file to satisfy each header request.
462  */
463 static int
464 read_header(struct archive_read *a, struct archive_entry *entry)
465 {
466         struct mtree *mtree;
467         char *p;
468         int r, use_next;
469
470         mtree = (struct mtree *)(a->format->data);
471
472         if (mtree->fd >= 0) {
473                 close(mtree->fd);
474                 mtree->fd = -1;
475         }
476
477         if (mtree->entries == NULL) {
478                 mtree->resolver = archive_entry_linkresolver_new();
479                 if (mtree->resolver == NULL)
480                         return ARCHIVE_FATAL;
481                 archive_entry_linkresolver_set_strategy(mtree->resolver,
482                     ARCHIVE_FORMAT_MTREE);
483                 r = read_mtree(a, mtree);
484                 if (r != ARCHIVE_OK)
485                         return (r);
486         }
487
488         a->archive.archive_format = mtree->archive_format;
489         a->archive.archive_format_name = mtree->archive_format_name;
490
491         for (;;) {
492                 if (mtree->this_entry == NULL)
493                         return (ARCHIVE_EOF);
494                 if (strcmp(mtree->this_entry->name, "..") == 0) {
495                         mtree->this_entry->used = 1;
496                         if (archive_strlen(&mtree->current_dir) > 0) {
497                                 /* Roll back current path. */
498                                 p = mtree->current_dir.s
499                                     + mtree->current_dir.length - 1;
500                                 while (p >= mtree->current_dir.s && *p != '/')
501                                         --p;
502                                 if (p >= mtree->current_dir.s)
503                                         --p;
504                                 mtree->current_dir.length
505                                     = p - mtree->current_dir.s + 1;
506                         }
507                 }
508                 if (!mtree->this_entry->used) {
509                         use_next = 0;
510                         r = parse_file(a, entry, mtree, mtree->this_entry, &use_next);
511                         if (use_next == 0)
512                                 return (r);
513                 }
514                 mtree->this_entry = mtree->this_entry->next;
515         }
516 }
517
518 /*
519  * A single file can have multiple lines contribute specifications.
520  * Parse as many lines as necessary, then pull additional information
521  * from a backing file on disk as necessary.
522  */
523 static int
524 parse_file(struct archive_read *a, struct archive_entry *entry,
525     struct mtree *mtree, struct mtree_entry *mentry, int *use_next)
526 {
527         const char *path;
528         struct stat st_storage, *st;
529         struct mtree_entry *mp;
530         struct archive_entry *sparse_entry;
531         int r = ARCHIVE_OK, r1, parsed_kws, mismatched_type;
532
533         mentry->used = 1;
534
535         /* Initialize reasonable defaults. */
536         mtree->filetype = AE_IFREG;
537         archive_entry_set_size(entry, 0);
538
539         /* Parse options from this line. */
540         parsed_kws = 0;
541         r = parse_line(a, entry, mtree, mentry, &parsed_kws);
542
543         if (mentry->full) {
544                 archive_entry_copy_pathname(entry, mentry->name);
545                 /*
546                  * "Full" entries are allowed to have multiple lines
547                  * and those lines aren't required to be adjacent.  We
548                  * don't support multiple lines for "relative" entries
549                  * nor do we make any attempt to merge data from
550                  * separate "relative" and "full" entries.  (Merging
551                  * "relative" and "full" entries would require dealing
552                  * with pathname canonicalization, which is a very
553                  * tricky subject.)
554                  */
555                 for (mp = mentry->next; mp != NULL; mp = mp->next) {
556                         if (mp->full && !mp->used
557                             && strcmp(mentry->name, mp->name) == 0) {
558                                 /* Later lines override earlier ones. */
559                                 mp->used = 1;
560                                 r1 = parse_line(a, entry, mtree, mp,
561                                     &parsed_kws);
562                                 if (r1 < r)
563                                         r = r1;
564                         }
565                 }
566         } else {
567                 /*
568                  * Relative entries require us to construct
569                  * the full path and possibly update the
570                  * current directory.
571                  */
572                 size_t n = archive_strlen(&mtree->current_dir);
573                 if (n > 0)
574                         archive_strcat(&mtree->current_dir, "/");
575                 archive_strcat(&mtree->current_dir, mentry->name);
576                 archive_entry_copy_pathname(entry, mtree->current_dir.s);
577                 if (archive_entry_filetype(entry) != AE_IFDIR)
578                         mtree->current_dir.length = n;
579         }
580
581         /*
582          * Try to open and stat the file to get the real size
583          * and other file info.  It would be nice to avoid
584          * this here so that getting a listing of an mtree
585          * wouldn't require opening every referenced contents
586          * file.  But then we wouldn't know the actual
587          * contents size, so I don't see a really viable way
588          * around this.  (Also, we may want to someday pull
589          * other unspecified info from the contents file on
590          * disk.)
591          */
592         mtree->fd = -1;
593         if (archive_strlen(&mtree->contents_name) > 0)
594                 path = mtree->contents_name.s;
595         else
596                 path = archive_entry_pathname(entry);
597
598         if (archive_entry_filetype(entry) == AE_IFREG ||
599             archive_entry_filetype(entry) == AE_IFDIR) {
600                 mtree->fd = open(path,
601                     O_RDONLY | O_BINARY);
602                 if (mtree->fd == -1 &&
603                     (errno != ENOENT ||
604                      archive_strlen(&mtree->contents_name) > 0)) {
605                         archive_set_error(&a->archive, errno,
606                             "Can't open %s", path);
607                         r = ARCHIVE_WARN;
608                 }
609         }
610
611         st = &st_storage;
612         if (mtree->fd >= 0) {
613                 if (fstat(mtree->fd, st) == -1) {
614                         archive_set_error(&a->archive, errno,
615                             "Could not fstat %s", path);
616                         r = ARCHIVE_WARN;
617                         /* If we can't stat it, don't keep it open. */
618                         close(mtree->fd);
619                         mtree->fd = -1;
620                         st = NULL;
621                 }
622         } else if (lstat(path, st) == -1) {
623                 st = NULL;
624         }
625
626         /*
627          * If there is a contents file on disk, use that size;
628          * otherwise leave it as-is (it might have been set from
629          * the mtree size= keyword).
630          */
631         if (st != NULL) {
632                 mismatched_type = 0;
633                 if ((st->st_mode & S_IFMT) == S_IFREG &&
634                     archive_entry_filetype(entry) != AE_IFREG)
635                         mismatched_type = 1;
636                 if ((st->st_mode & S_IFMT) == S_IFLNK &&
637                     archive_entry_filetype(entry) != AE_IFLNK)
638                         mismatched_type = 1;
639                 if ((st->st_mode & S_IFSOCK) == S_IFSOCK &&
640                     archive_entry_filetype(entry) != AE_IFSOCK)
641                         mismatched_type = 1;
642                 if ((st->st_mode & S_IFMT) == S_IFCHR &&
643                     archive_entry_filetype(entry) != AE_IFCHR)
644                         mismatched_type = 1;
645                 if ((st->st_mode & S_IFMT) == S_IFBLK &&
646                     archive_entry_filetype(entry) != AE_IFBLK)
647                         mismatched_type = 1;
648                 if ((st->st_mode & S_IFMT) == S_IFDIR &&
649                     archive_entry_filetype(entry) != AE_IFDIR)
650                         mismatched_type = 1;
651                 if ((st->st_mode & S_IFMT) == S_IFIFO &&
652                     archive_entry_filetype(entry) != AE_IFIFO)
653                         mismatched_type = 1;
654
655                 if (mismatched_type) {
656                         if ((parsed_kws & MTREE_HAS_OPTIONAL) == 0) {
657                                 archive_set_error(&a->archive,
658                                     ARCHIVE_ERRNO_MISC,
659                                     "mtree specification has different type for %s",
660                                     archive_entry_pathname(entry));
661                                 r = ARCHIVE_WARN;
662                         } else {
663                                 *use_next = 1;
664                         }
665                         /* Don't hold a non-regular file open. */
666                         close(mtree->fd);
667                         mtree->fd = -1;
668                         st = NULL;
669                         return r;
670                 }
671         }
672
673         if (st != NULL) {
674                 if ((parsed_kws & MTREE_HAS_DEVICE) == 0 &&
675                     (archive_entry_filetype(entry) == AE_IFCHR ||
676                      archive_entry_filetype(entry) == AE_IFBLK))
677                         archive_entry_set_rdev(entry, st->st_rdev);
678                 if ((parsed_kws & (MTREE_HAS_GID | MTREE_HAS_GNAME)) == 0)
679                         archive_entry_set_gid(entry, st->st_gid);
680                 if ((parsed_kws & (MTREE_HAS_UID | MTREE_HAS_UNAME)) == 0)
681                         archive_entry_set_uid(entry, st->st_uid);
682                 if ((parsed_kws & MTREE_HAS_MTIME) == 0) {
683 #if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
684                         archive_entry_set_mtime(entry, st->st_mtime,
685                             st->st_mtimespec.tv_nsec);
686 #elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
687                         archive_entry_set_mtime(entry, st->st_mtime,
688                             st->st_mtim.tv_nsec);
689 #else
690                         archive_entry_set_mtime(entry, st->st_mtime, 0);
691 #endif
692                 }
693                 if ((parsed_kws & MTREE_HAS_NLINK) == 0)
694                         archive_entry_set_nlink(entry, st->st_nlink);
695                 if ((parsed_kws & MTREE_HAS_PERM) == 0)
696                         archive_entry_set_perm(entry, st->st_mode);
697                 if ((parsed_kws & MTREE_HAS_SIZE) == 0)
698                         archive_entry_set_size(entry, st->st_size);
699                 archive_entry_set_ino(entry, st->st_ino);
700                 archive_entry_set_dev(entry, st->st_dev);
701
702                 archive_entry_linkify(mtree->resolver, &entry, &sparse_entry);
703         } else if (parsed_kws & MTREE_HAS_OPTIONAL) {
704                 /*
705                  * Couldn't open the entry, stat it or the on-disk type
706                  * didn't match.  If this entry is optional, just ignore it
707                  * and read the next header entry.
708                  */
709                 *use_next = 1;
710                 return ARCHIVE_OK;
711         }
712
713         mtree->cur_size = archive_entry_size(entry);
714         mtree->offset = 0;
715
716         return r;
717 }
718
719 /*
720  * Each line contains a sequence of keywords.
721  */
722 static int
723 parse_line(struct archive_read *a, struct archive_entry *entry,
724     struct mtree *mtree, struct mtree_entry *mp, int *parsed_kws)
725 {
726         struct mtree_option *iter;
727         int r = ARCHIVE_OK, r1;
728
729         for (iter = mp->options; iter != NULL; iter = iter->next) {
730                 r1 = parse_keyword(a, mtree, entry, iter, parsed_kws);
731                 if (r1 < r)
732                         r = r1;
733         }
734         if ((*parsed_kws & MTREE_HAS_TYPE) == 0) {
735                 archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
736                     "Missing type keyword in mtree specification");
737                 return (ARCHIVE_WARN);
738         }
739         return (r);
740 }
741
742 /*
743  * Device entries have one of the following forms:
744  * raw dev_t
745  * format,major,minor[,subdevice]
746  *
747  * Just use major and minor, no translation etc is done
748  * between formats.
749  */
750 static int
751 parse_device(struct archive *a, struct archive_entry *entry, char *val)
752 {
753         char *comma1, *comma2;
754
755         comma1 = strchr(val, ',');
756         if (comma1 == NULL) {
757                 archive_entry_set_dev(entry, mtree_atol10(&val));
758                 return (ARCHIVE_OK);
759         }
760         ++comma1;
761         comma2 = strchr(comma1, ',');
762         if (comma1 == NULL) {
763                 archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
764                     "Malformed device attribute");
765                 return (ARCHIVE_WARN);
766         }
767         ++comma2;
768         archive_entry_set_rdevmajor(entry, mtree_atol(&comma1));
769         archive_entry_set_rdevminor(entry, mtree_atol(&comma2));
770         return (ARCHIVE_OK);
771 }
772
773 /*
774  * Parse a single keyword and its value.
775  */
776 static int
777 parse_keyword(struct archive_read *a, struct mtree *mtree,
778     struct archive_entry *entry, struct mtree_option *option, int *parsed_kws)
779 {
780         char *val, *key;
781
782         key = option->value;
783
784         if (*key == '\0')
785                 return (ARCHIVE_OK);
786
787         if (strcmp(key, "optional") == 0) {
788                 *parsed_kws |= MTREE_HAS_OPTIONAL;
789                 return (ARCHIVE_OK);
790         }
791         if (strcmp(key, "ignore") == 0) {
792                 /*
793                  * The mtree processing is not recursive, so
794                  * recursion will only happen for explicitly listed
795                  * entries.
796                  */
797                 return (ARCHIVE_OK);
798         }
799
800         val = strchr(key, '=');
801         if (val == NULL) {
802                 archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
803                     "Malformed attribute \"%s\" (%d)", key, key[0]);
804                 return (ARCHIVE_WARN);
805         }
806
807         *val = '\0';
808         ++val;
809
810         switch (key[0]) {
811         case 'c':
812                 if (strcmp(key, "content") == 0
813                     || strcmp(key, "contents") == 0) {
814                         parse_escapes(val, NULL);
815                         archive_strcpy(&mtree->contents_name, val);
816                         break;
817                 }
818                 if (strcmp(key, "cksum") == 0)
819                         break;
820         case 'd':
821                 if (strcmp(key, "device") == 0) {
822                         *parsed_kws |= MTREE_HAS_DEVICE;
823                         return parse_device(&a->archive, entry, val);
824                 }
825         case 'f':
826                 if (strcmp(key, "flags") == 0) {
827                         *parsed_kws |= MTREE_HAS_FFLAGS;
828                         archive_entry_copy_fflags_text(entry, val);
829                         break;
830                 }
831         case 'g':
832                 if (strcmp(key, "gid") == 0) {
833                         *parsed_kws |= MTREE_HAS_GID;
834                         archive_entry_set_gid(entry, mtree_atol10(&val));
835                         break;
836                 }
837                 if (strcmp(key, "gname") == 0) {
838                         *parsed_kws |= MTREE_HAS_GNAME;
839                         archive_entry_copy_gname(entry, val);
840                         break;
841                 }
842         case 'l':
843                 if (strcmp(key, "link") == 0) {
844                         archive_entry_copy_symlink(entry, val);
845                         break;
846                 }
847         case 'm':
848                 if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0)
849                         break;
850                 if (strcmp(key, "mode") == 0) {
851                         if (val[0] >= '0' && val[0] <= '9') {
852                                 *parsed_kws |= MTREE_HAS_PERM;
853                                 archive_entry_set_perm(entry,
854                                     mtree_atol8(&val));
855                         } else {
856                                 archive_set_error(&a->archive,
857                                     ARCHIVE_ERRNO_FILE_FORMAT,
858                                     "Symbolic mode \"%s\" unsupported", val);
859                                 return ARCHIVE_WARN;
860                         }
861                         break;
862                 }
863         case 'n':
864                 if (strcmp(key, "nlink") == 0) {
865                         *parsed_kws |= MTREE_HAS_NLINK;
866                         archive_entry_set_nlink(entry, mtree_atol10(&val));
867                         break;
868                 }
869         case 'r':
870                 if (strcmp(key, "rmd160") == 0 ||
871                     strcmp(key, "rmd160digest") == 0)
872                         break;
873         case 's':
874                 if (strcmp(key, "sha1") == 0 || strcmp(key, "sha1digest") == 0)
875                         break;
876                 if (strcmp(key, "sha256") == 0 ||
877                     strcmp(key, "sha256digest") == 0)
878                         break;
879                 if (strcmp(key, "sha384") == 0 ||
880                     strcmp(key, "sha384digest") == 0)
881                         break;
882                 if (strcmp(key, "sha512") == 0 ||
883                     strcmp(key, "sha512digest") == 0)
884                         break;
885                 if (strcmp(key, "size") == 0) {
886                         archive_entry_set_size(entry, mtree_atol10(&val));
887                         break;
888                 }
889         case 't':
890                 if (strcmp(key, "tags") == 0) {
891                         /*
892                          * Comma delimited list of tags.
893                          * Ignore the tags for now, but the interface
894                          * should be extended to allow inclusion/exclusion.
895                          */
896                         break;
897                 }
898                 if (strcmp(key, "time") == 0) {
899                         *parsed_kws |= MTREE_HAS_MTIME;
900                         archive_entry_set_mtime(entry, mtree_atol10(&val), 0);
901                         break;
902                 }
903                 if (strcmp(key, "type") == 0) {
904                         *parsed_kws |= MTREE_HAS_TYPE;
905                         switch (val[0]) {
906                         case 'b':
907                                 if (strcmp(val, "block") == 0) {
908                                         mtree->filetype = AE_IFBLK;
909                                         break;
910                                 }
911                         case 'c':
912                                 if (strcmp(val, "char") == 0) {
913                                         mtree->filetype = AE_IFCHR;
914                                         break;
915                                 }
916                         case 'd':
917                                 if (strcmp(val, "dir") == 0) {
918                                         mtree->filetype = AE_IFDIR;
919                                         break;
920                                 }
921                         case 'f':
922                                 if (strcmp(val, "fifo") == 0) {
923                                         mtree->filetype = AE_IFIFO;
924                                         break;
925                                 }
926                                 if (strcmp(val, "file") == 0) {
927                                         mtree->filetype = AE_IFREG;
928                                         break;
929                                 }
930                         case 'l':
931                                 if (strcmp(val, "link") == 0) {
932                                         mtree->filetype = AE_IFLNK;
933                                         break;
934                                 }
935                         default:
936                                 archive_set_error(&a->archive,
937                                     ARCHIVE_ERRNO_FILE_FORMAT,
938                                     "Unrecognized file type \"%s\"", val);
939                                 return (ARCHIVE_WARN);
940                         }
941                         archive_entry_set_filetype(entry, mtree->filetype);
942                         break;
943                 }
944         case 'u':
945                 if (strcmp(key, "uid") == 0) {
946                         *parsed_kws |= MTREE_HAS_UID;
947                         archive_entry_set_uid(entry, mtree_atol10(&val));
948                         break;
949                 }
950                 if (strcmp(key, "uname") == 0) {
951                         *parsed_kws |= MTREE_HAS_UNAME;
952                         archive_entry_copy_uname(entry, val);
953                         break;
954                 }
955         default:
956                 archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
957                     "Unrecognized key %s=%s", key, val);
958                 return (ARCHIVE_WARN);
959         }
960         return (ARCHIVE_OK);
961 }
962
963 static int
964 read_data(struct archive_read *a, const void **buff, size_t *size, off_t *offset)
965 {
966         size_t bytes_to_read;
967         ssize_t bytes_read;
968         struct mtree *mtree;
969
970         mtree = (struct mtree *)(a->format->data);
971         if (mtree->fd < 0) {
972                 *buff = NULL;
973                 *offset = 0;
974                 *size = 0;
975                 return (ARCHIVE_EOF);
976         }
977         if (mtree->buff == NULL) {
978                 mtree->buffsize = 64 * 1024;
979                 mtree->buff = malloc(mtree->buffsize);
980                 if (mtree->buff == NULL) {
981                         archive_set_error(&a->archive, ENOMEM,
982                             "Can't allocate memory");
983                 }
984                 return (ARCHIVE_FATAL);
985         }
986
987         *buff = mtree->buff;
988         *offset = mtree->offset;
989         if ((off_t)mtree->buffsize > mtree->cur_size - mtree->offset)
990                 bytes_to_read = mtree->cur_size - mtree->offset;
991         else
992                 bytes_to_read = mtree->buffsize;
993         bytes_read = read(mtree->fd, mtree->buff, bytes_to_read);
994         if (bytes_read < 0) {
995                 archive_set_error(&a->archive, errno, "Can't read");
996                 return (ARCHIVE_WARN);
997         }
998         if (bytes_read == 0) {
999                 *size = 0;
1000                 return (ARCHIVE_EOF);
1001         }
1002         mtree->offset += bytes_read;
1003         *size = bytes_read;
1004         return (ARCHIVE_OK);
1005 }
1006
1007 /* Skip does nothing except possibly close the contents file. */
1008 static int
1009 skip(struct archive_read *a)
1010 {
1011         struct mtree *mtree;
1012
1013         mtree = (struct mtree *)(a->format->data);
1014         if (mtree->fd >= 0) {
1015                 close(mtree->fd);
1016                 mtree->fd = -1;
1017         }
1018         return (ARCHIVE_OK);
1019 }
1020
1021 /*
1022  * Since parsing octal escapes always makes strings shorter,
1023  * we can always do this conversion in-place.
1024  */
1025 static void
1026 parse_escapes(char *src, struct mtree_entry *mentry)
1027 {
1028         char *dest = src;
1029         char c;
1030
1031         /*
1032          * The current directory is somewhat special, it should be archived
1033          * only once as it will confuse extraction otherwise.
1034          */
1035         if (strcmp(src, ".") == 0)
1036                 mentry->full = 1;
1037
1038         while (*src != '\0') {
1039                 c = *src++;
1040                 if (c == '/' && mentry != NULL)
1041                         mentry->full = 1;
1042                 if (c == '\\') {
1043                         if (src[0] >= '0' && src[0] <= '3'
1044                             && src[1] >= '0' && src[1] <= '7'
1045                             && src[2] >= '0' && src[2] <= '7') {
1046                                 c = (src[0] - '0') << 6;
1047                                 c |= (src[1] - '0') << 3;
1048                                 c |= (src[2] - '0');
1049                                 src += 3;
1050                         }
1051                 }
1052                 *dest++ = c;
1053         }
1054         *dest = '\0';
1055 }
1056
1057 /*
1058  * Note that this implementation does not (and should not!) obey
1059  * locale settings; you cannot simply substitute strtol here, since
1060  * it does obey locale.
1061  */
1062 static int64_t
1063 mtree_atol8(char **p)
1064 {
1065         int64_t l, limit, last_digit_limit;
1066         int digit, base;
1067
1068         base = 8;
1069         limit = INT64_MAX / base;
1070         last_digit_limit = INT64_MAX % base;
1071
1072         l = 0;
1073         digit = **p - '0';
1074         while (digit >= 0 && digit < base) {
1075                 if (l>limit || (l == limit && digit > last_digit_limit)) {
1076                         l = INT64_MAX; /* Truncate on overflow. */
1077                         break;
1078                 }
1079                 l = (l * base) + digit;
1080                 digit = *++(*p) - '0';
1081         }
1082         return (l);
1083 }
1084
1085 /*
1086  * Note that this implementation does not (and should not!) obey
1087  * locale settings; you cannot simply substitute strtol here, since
1088  * it does obey locale.
1089  */
1090 static int64_t
1091 mtree_atol10(char **p)
1092 {
1093         int64_t l, limit, last_digit_limit;
1094         int base, digit, sign;
1095
1096         base = 10;
1097         limit = INT64_MAX / base;
1098         last_digit_limit = INT64_MAX % base;
1099
1100         if (**p == '-') {
1101                 sign = -1;
1102                 ++(*p);
1103         } else
1104                 sign = 1;
1105
1106         l = 0;
1107         digit = **p - '0';
1108         while (digit >= 0 && digit < base) {
1109                 if (l > limit || (l == limit && digit > last_digit_limit)) {
1110                         l = UINT64_MAX; /* Truncate on overflow. */
1111                         break;
1112                 }
1113                 l = (l * base) + digit;
1114                 digit = *++(*p) - '0';
1115         }
1116         return (sign < 0) ? -l : l;
1117 }
1118
1119 /*
1120  * Note that this implementation does not (and should not!) obey
1121  * locale settings; you cannot simply substitute strtol here, since
1122  * it does obey locale.
1123  */
1124 static int64_t
1125 mtree_atol16(char **p)
1126 {
1127         int64_t l, limit, last_digit_limit;
1128         int base, digit, sign;
1129
1130         base = 16;
1131         limit = INT64_MAX / base;
1132         last_digit_limit = INT64_MAX % base;
1133
1134         if (**p == '-') {
1135                 sign = -1;
1136                 ++(*p);
1137         } else
1138                 sign = 1;
1139
1140         l = 0;
1141         if (**p >= '0' && **p <= '9')
1142                 digit = **p - '0';
1143         else if (**p >= 'a' && **p <= 'f')
1144                 digit = **p - 'a' + 10;
1145         else if (**p >= 'A' && **p <= 'F')
1146                 digit = **p - 'A' + 10;
1147         else
1148                 digit = -1;
1149         while (digit >= 0 && digit < base) {
1150                 if (l > limit || (l == limit && digit > last_digit_limit)) {
1151                         l = UINT64_MAX; /* Truncate on overflow. */
1152                         break;
1153                 }
1154                 l = (l * base) + digit;
1155                 if (**p >= '0' && **p <= '9')
1156                         digit = **p - '0';
1157                 else if (**p >= 'a' && **p <= 'f')
1158                         digit = **p - 'a' + 10;
1159                 else if (**p >= 'A' && **p <= 'F')
1160                         digit = **p - 'A' + 10;
1161                 else
1162                         digit = -1;
1163         }
1164         return (sign < 0) ? -l : l;
1165 }
1166
1167 static int64_t
1168 mtree_atol(char **p)
1169 {
1170         if (**p != '0')
1171                 return mtree_atol10(p);
1172         if ((*p)[1] == 'x' || (*p)[1] == 'X') {
1173                 *p += 2;
1174                 return mtree_atol16(p);
1175         }
1176         return mtree_atol8(p);
1177 }
1178
1179 /*
1180  * Returns length of line (including trailing newline)
1181  * or negative on error.  'start' argument is updated to
1182  * point to first character of line.
1183  */
1184 static ssize_t
1185 readline(struct archive_read *a, struct mtree *mtree, char **start, ssize_t limit)
1186 {
1187         ssize_t bytes_read;
1188         ssize_t total_size = 0;
1189         const void *t;
1190         const char *s;
1191         void *p;
1192
1193         /* Accumulate line in a line buffer. */
1194         for (;;) {
1195                 /* Read some more. */
1196                 bytes_read = (a->decompressor->read_ahead)(a, &t, 1);
1197                 if (bytes_read == 0)
1198                         return (0);
1199                 if (bytes_read < 0)
1200                         return (ARCHIVE_FATAL);
1201                 s = t;  /* Start of line? */
1202                 p = memchr(t, '\n', bytes_read);
1203                 /* If we found '\n', trim the read. */
1204                 if (p != NULL) {
1205                         bytes_read = 1 + ((const char *)p) - s;
1206                 }
1207                 if (total_size + bytes_read + 1 > limit) {
1208                         archive_set_error(&a->archive,
1209                             ARCHIVE_ERRNO_FILE_FORMAT,
1210                             "Line too long");
1211                         return (ARCHIVE_FATAL);
1212                 }
1213                 if (archive_string_ensure(&mtree->line,
1214                         total_size + bytes_read + 1) == NULL) {
1215                         archive_set_error(&a->archive, ENOMEM,
1216                             "Can't allocate working buffer");
1217                         return (ARCHIVE_FATAL);
1218                 }
1219                 memcpy(mtree->line.s + total_size, t, bytes_read);
1220                 (a->decompressor->consume)(a, bytes_read);
1221                 total_size += bytes_read;
1222                 /* Null terminate. */
1223                 mtree->line.s[total_size] = '\0';
1224                 /* If we found '\n', clean up and return. */
1225                 if (p != NULL) {
1226                         *start = mtree->line.s;
1227                         return (total_size);
1228                 }
1229         }
1230 }