~ubuntu-branches/ubuntu/quantal/libarchive/quantal

« back to all changes in this revision

Viewing changes to libarchive/archive_write_set_format_mtree.c

  • Committer: Package Import Robot
  • Author(s): Andres Mejia
  • Date: 2012-02-23 19:29:24 UTC
  • mfrom: (8.1.10 sid)
  • Revision ID: package-import@ubuntu.com-20120223192924-73n4iedok5fwgsyr
Tags: 3.0.3-5
* Detect if locales or locales-all is installed for use with test suite.
* Bump Standards-Version to 3.9.3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*-
2
 
 * Copyright (c) 2009 Michihiro NAKAJIMA
 
2
 * Copyright (c) 2009,2011 Michihiro NAKAJIMA
3
3
 * Copyright (c) 2008 Joerg Sonnenberger
4
4
 * All rights reserved.
5
5
 *
35
35
#include <string.h>
36
36
 
37
37
#include "archive.h"
 
38
#include "archive_crypto_private.h"
38
39
#include "archive_entry.h"
39
40
#include "archive_private.h"
40
41
#include "archive_write_private.h"
41
42
 
42
 
#include "archive_hash.h"
43
 
 
44
43
#define INDENTNAMELEN   15
45
44
#define MAXLINELEN      80
 
45
#define SET_KEYS        \
 
46
        (F_FLAGS | F_GID | F_GNAME | F_MODE | F_TYPE | F_UID | F_UNAME)
 
47
 
 
48
struct mtree_entry {
 
49
        struct mtree_entry *next;
 
50
 
 
51
        char *pathname;
 
52
        char *symlink;
 
53
        unsigned int nlink;
 
54
        mode_t filetype;
 
55
        mode_t mode;
 
56
        int64_t uid;
 
57
        int64_t gid;
 
58
        char *uname;
 
59
        char *gname;
 
60
        char *fflags_text;
 
61
        unsigned long fflags_set;
 
62
        unsigned long fflags_clear;
 
63
        time_t mtime;
 
64
        long mtime_nsec;
 
65
        dev_t rdevmajor;
 
66
        dev_t rdevminor;
 
67
        int64_t size;
 
68
 
 
69
        int compute_sum;
 
70
        uint32_t crc;
 
71
#ifdef ARCHIVE_HAS_MD5
 
72
        unsigned char buf_md5[16];
 
73
#endif
 
74
#ifdef ARCHIVE_HAS_RMD160
 
75
        unsigned char buf_rmd160[20];
 
76
#endif
 
77
#ifdef ARCHIVE_HAS_SHA1
 
78
        unsigned char buf_sha1[20];
 
79
#endif
 
80
#ifdef ARCHIVE_HAS_SHA256
 
81
        unsigned char buf_sha256[32];
 
82
#endif
 
83
#ifdef ARCHIVE_HAS_SHA384
 
84
        unsigned char buf_sha384[48];
 
85
#endif
 
86
#ifdef ARCHIVE_HAS_SHA512
 
87
        unsigned char buf_sha512[64];
 
88
#endif
 
89
};
 
90
 
 
91
struct attr_counter {
 
92
        struct attr_counter *prev;
 
93
        struct attr_counter *next;
 
94
        int count;
 
95
        struct mtree_entry *m_entry;
 
96
};
46
97
 
47
98
struct mtree_writer {
48
 
        struct archive_entry *entry;
 
99
        struct mtree_entry *mtree_entry;
49
100
        struct archive_string ebuf;
50
101
        struct archive_string buf;
51
102
        int first;
56
107
                struct archive_string parent;
57
108
                mode_t          type;
58
109
                int             keys;
59
 
                uid_t           uid;
60
 
                gid_t           gid;
 
110
                int64_t         uid;
 
111
                int64_t         gid;
61
112
                mode_t          mode;
62
113
                unsigned long   fflags_set;
63
114
                unsigned long   fflags_clear;
 
115
 
 
116
                struct attr_counter *uid_list;
 
117
                struct attr_counter *gid_list;
 
118
                struct attr_counter *mode_list;
 
119
                struct attr_counter *flags_list;
 
120
                struct mtree_entry *me_first;
 
121
                struct mtree_entry **me_last;
64
122
        } set;
65
 
        /* chekc sum */
 
123
        /* check sum */
66
124
        int compute_sum;
67
125
        uint32_t crc;
68
126
        uint64_t crc_len;
125
183
                         | F_NLINK | F_SIZE | F_TIME | F_TYPE | F_UID\
126
184
                         | F_UNAME)
127
185
 
 
186
static struct attr_counter * new_attr_count(struct mtree_entry *,
 
187
        struct attr_counter *);
 
188
static void free_attr_count(struct attr_counter **);
 
189
static int inc_attr_count(struct attr_counter **, struct attr_counter *,
 
190
        struct attr_counter *, struct mtree_entry *);
 
191
static int collect_set_values(struct mtree_writer *, struct mtree_entry *);
 
192
static int get_keys(struct mtree_writer *, struct mtree_entry *);
 
193
static void sum_init(struct mtree_writer *);
 
194
static void sum_update(struct mtree_writer *, const void *, size_t);
 
195
static void sum_final(struct mtree_writer *, struct mtree_entry *);
 
196
static void sum_write(struct archive_string *, struct mtree_entry *);
 
197
 
128
198
#define COMPUTE_CRC(var, ch)    (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
129
199
static const uint32_t crctab[] = {
130
200
        0x0,
227
297
                archive_strncat(s, start, str - start);
228
298
}
229
299
 
 
300
/*
 
301
 * Indent a line as mtree utility to be readable for people.
 
302
 */
230
303
static void
231
304
mtree_indent(struct mtree_writer *mtree)
232
305
{
281
354
 
282
355
#if !defined(_WIN32) || defined(__CYGWIN__)
283
356
static size_t
284
 
dir_len(struct archive_entry *entry)
 
357
dir_len(struct mtree_entry *me)
285
358
{
286
359
        const char *path, *r;
287
360
 
288
 
        path = archive_entry_pathname(entry);
 
361
        path = me->pathname;
289
362
        r = strrchr(path, '/');
290
363
        if (r == NULL)
291
364
                return (0);
301
374
 * code.
302
375
 */
303
376
static size_t
304
 
dir_len(struct archive_entry *entry)
 
377
dir_len(struct mtree_entry *me)
305
378
{
306
379
        wchar_t wc;
307
380
        const char *path;
308
381
        const char *p, *rp;
309
382
        size_t al, l, size;
310
383
 
311
 
        path = archive_entry_pathname(entry);
 
384
        path = me->pathname;
312
385
        al = l = -1;
313
386
        for (p = path; *p != '\0'; ++p) {
314
387
                if (*p == '\\')
337
410
}
338
411
#endif /* _WIN32 && !__CYGWIN__ */
339
412
 
 
413
/*
 
414
 * Test if a parent directory of the current entry is changed.
 
415
 */
340
416
static int
341
 
parent_dir_changed(struct archive_string *dir, struct archive_entry *entry)
 
417
parent_dir_changed(struct archive_string *dir, struct mtree_entry *me)
342
418
{
343
419
        const char *path;
344
420
        size_t l;
345
421
 
346
 
        l = dir_len(entry);
347
 
        path = archive_entry_pathname(entry);
 
422
        l = dir_len(me);
 
423
        path = me->pathname;
348
424
        if (archive_strlen(dir) > 0) {
349
425
                if (l == 0) {
350
426
                        archive_string_empty(dir);
359
435
}
360
436
 
361
437
/*
362
 
 * Write /set keyword. It means set global datas.
363
 
 * [directory-only mode]
364
 
 *   - It is only once to write /set keyword. It is using values of the
365
 
 *     first entry.
366
 
 * [normal mode]
367
 
 *   - Write /set keyword. It is using values of the first entry whose
368
 
 *     filetype is a regular file.
369
 
 *   - When a parent directory of the entry whose filetype is the regular
370
 
 *     file is changed, check the global datas and write it again if its
371
 
 *     values are different from the entry's.
 
438
 * Write /set keyword.
 
439
 * Set most used value of uid,gid,mode and fflags, which are
 
440
 * collected by collect_set_values() function.
372
441
 */
373
442
static void
374
 
set_global(struct mtree_writer *mtree, struct archive_entry *entry)
 
443
write_global(struct mtree_writer *mtree)
375
444
{
376
445
        struct archive_string setstr;
377
446
        struct archive_string unsetstr;
378
447
        const char *name;
379
448
        int keys, oldkeys, effkeys;
380
 
        mode_t set_type = 0;
381
 
 
382
 
        switch (archive_entry_filetype(entry)) {
383
 
        case AE_IFLNK: case AE_IFSOCK: case AE_IFCHR:
384
 
        case AE_IFBLK: case AE_IFIFO:
385
 
                break;
386
 
        case AE_IFDIR:
387
 
                if (mtree->dironly)
388
 
                        set_type = AE_IFDIR;
389
 
                break;
390
 
        case AE_IFREG:
391
 
        default:        /* Handle unknown file types as regular files. */
392
 
                if (!mtree->dironly)
393
 
                        set_type = AE_IFREG;
394
 
                break;
395
 
        }
396
 
        if (set_type == 0)
397
 
                return;
398
 
        if (mtree->set.processed &&
399
 
            !parent_dir_changed(&mtree->set.parent, entry))
400
 
                return;
401
 
        /* At first, save a parent directory of the entry for following
402
 
         * entries. */
403
 
        if (!mtree->set.processed && set_type == AE_IFREG)
404
 
                parent_dir_changed(&mtree->set.parent, entry);
 
449
        struct attr_counter *ac;
405
450
 
406
451
        archive_string_init(&setstr);
407
452
        archive_string_init(&unsetstr);
408
 
        keys = mtree->keys & (F_FLAGS | F_GID | F_GNAME | F_NLINK | F_MODE
409
 
            | F_TYPE | F_UID | F_UNAME);
 
453
        keys = mtree->keys & SET_KEYS;
410
454
        oldkeys = mtree->set.keys;
411
455
        effkeys = keys;
412
456
        if (mtree->set.processed) {
413
457
                /*
414
 
                 * Check the global datas for whether it needs updating.
 
458
                 * Check if the global data needs updating.
415
459
                 */
416
460
                effkeys &= ~F_TYPE;
417
 
                if ((oldkeys & (F_UNAME | F_UID)) != 0 &&
418
 
                    mtree->set.uid == archive_entry_uid(entry))
419
 
                        effkeys &= ~(F_UNAME | F_UID);
420
 
                if ((oldkeys & (F_GNAME | F_GID)) != 0 &&
421
 
                    mtree->set.gid == archive_entry_gid(entry))
422
 
                        effkeys &= ~(F_GNAME | F_GID);
423
 
                if ((oldkeys & F_MODE) != 0 &&
424
 
                    mtree->set.mode == (archive_entry_mode(entry) & 07777))
425
 
                        effkeys &= ~F_MODE;
 
461
                if (oldkeys & (F_UNAME | F_UID)) {
 
462
                        ac = mtree->set.uid_list;
 
463
                        do {
 
464
                                if (mtree->set.uid == ac->m_entry->uid) {
 
465
                                        effkeys &= ~(F_UNAME | F_UID);
 
466
                                        break;
 
467
                                }
 
468
                                if (ac->next != NULL &&
 
469
                                    ac->next->count == ac->count)
 
470
                                        continue;
 
471
                        } while (0);
 
472
                }
 
473
                if (oldkeys & (F_GNAME | F_GID)) {
 
474
                        ac = mtree->set.gid_list;
 
475
                        do {
 
476
                                if (mtree->set.gid == ac->m_entry->gid) {
 
477
                                        effkeys &= ~(F_GNAME | F_GID);
 
478
                                        break;
 
479
                                }
 
480
                                if (ac->next != NULL &&
 
481
                                    ac->next->count == ac->count)
 
482
                                        continue;
 
483
                        } while (0);
 
484
                }
 
485
                if (oldkeys & F_MODE) {
 
486
                        ac = mtree->set.mode_list;
 
487
                        do {
 
488
                                if (mtree->set.mode == ac->m_entry->mode) {
 
489
                                        effkeys &= ~F_MODE;
 
490
                                        break;
 
491
                                }
 
492
                                if (ac->next != NULL &&
 
493
                                    ac->next->count == ac->count)
 
494
                                        continue;
 
495
                        } while (0);
 
496
                }
426
497
                if ((oldkeys & F_FLAGS) != 0) {
427
 
                        unsigned long   fflags_set;
428
 
                        unsigned long   fflags_clear;
429
 
 
430
 
                        archive_entry_fflags(entry, &fflags_set, &fflags_clear);
431
 
                        if (fflags_set == mtree->set.fflags_set &&
432
 
                            fflags_clear == mtree->set.fflags_clear)
433
 
                                effkeys &= ~F_FLAGS;
 
498
                        ac = mtree->set.flags_list;
 
499
                        do {
 
500
                                if (ac->m_entry->fflags_set ==
 
501
                                        mtree->set.fflags_set &&
 
502
                                    ac->m_entry->fflags_clear ==
 
503
                                        mtree->set.fflags_clear) {
 
504
                                        effkeys &= ~F_FLAGS;
 
505
                                        break;
 
506
                                }
 
507
                                if (ac->next != NULL &&
 
508
                                    ac->next->count == ac->count)
 
509
                                        continue;
 
510
                        } while (0);
434
511
                }
435
512
        }
436
513
        if ((keys & effkeys & F_TYPE) != 0) {
437
 
                mtree->set.type = set_type;
438
 
                if (set_type == AE_IFDIR)
 
514
                if (mtree->dironly) {
439
515
                        archive_strcat(&setstr, " type=dir");
440
 
                else
 
516
                        mtree->set.type = AE_IFDIR;
 
517
                } else {
441
518
                        archive_strcat(&setstr, " type=file");
 
519
                        mtree->set.type = AE_IFREG;
 
520
                }
442
521
        }
443
522
        if ((keys & effkeys & F_UNAME) != 0) {
444
 
                if ((name = archive_entry_uname(entry)) != NULL) {
 
523
                name = mtree->set.uid_list->m_entry->uname;
 
524
                if (name != NULL) {
445
525
                        archive_strcat(&setstr, " uname=");
446
526
                        mtree_quote(&setstr, name);
447
 
                } else if ((oldkeys & F_UNAME) != 0)
448
 
                        archive_strcat(&unsetstr, " uname");
449
 
                else
 
527
                } else {
450
528
                        keys &= ~F_UNAME;
 
529
                        if ((oldkeys & F_UNAME) != 0)
 
530
                                archive_strcat(&unsetstr, " uname");
 
531
                }
451
532
        }
452
533
        if ((keys & effkeys & F_UID) != 0) {
453
 
                mtree->set.uid = archive_entry_uid(entry);
 
534
                mtree->set.uid = mtree->set.uid_list->m_entry->uid;
454
535
                archive_string_sprintf(&setstr, " uid=%jd",
455
536
                    (intmax_t)mtree->set.uid);
456
537
        }
457
538
        if ((keys & effkeys & F_GNAME) != 0) {
458
 
                if ((name = archive_entry_gname(entry)) != NULL) {
 
539
                name = mtree->set.gid_list->m_entry->gname;
 
540
                if (name != NULL) {
459
541
                        archive_strcat(&setstr, " gname=");
460
542
                        mtree_quote(&setstr, name);
461
 
                } else if ((oldkeys & F_GNAME) != 0)
462
 
                        archive_strcat(&unsetstr, " gname");
463
 
                else
 
543
                } else {
464
544
                        keys &= ~F_GNAME;
 
545
                        if ((oldkeys & F_GNAME) != 0)
 
546
                                archive_strcat(&unsetstr, " gname");
 
547
                }
465
548
        }
466
549
        if ((keys & effkeys & F_GID) != 0) {
467
 
                mtree->set.gid = archive_entry_gid(entry);
 
550
                mtree->set.gid = mtree->set.gid_list->m_entry->gid;
468
551
                archive_string_sprintf(&setstr, " gid=%jd",
469
552
                    (intmax_t)mtree->set.gid);
470
553
        }
471
554
        if ((keys & effkeys & F_MODE) != 0) {
472
 
                mtree->set.mode = archive_entry_mode(entry) & 07777;
473
 
                archive_string_sprintf(&setstr, " mode=%o", mtree->set.mode);
 
555
                mtree->set.mode = mtree->set.mode_list->m_entry->mode;
 
556
                archive_string_sprintf(&setstr, " mode=%o",
 
557
                    (unsigned int)mtree->set.mode);
474
558
        }
475
559
        if ((keys & effkeys & F_FLAGS) != 0) {
476
 
                if ((name = archive_entry_fflags_text(entry)) != NULL) {
 
560
                name = mtree->set.flags_list->m_entry->fflags_text;
 
561
                if (name != NULL) {
477
562
                        archive_strcat(&setstr, " flags=");
478
563
                        mtree_quote(&setstr, name);
479
 
                        archive_entry_fflags(entry, &mtree->set.fflags_set,
480
 
                            &mtree->set.fflags_clear);
481
 
                } else if ((oldkeys & F_FLAGS) != 0)
482
 
                        archive_strcat(&unsetstr, " flags");
483
 
                else
 
564
                        mtree->set.fflags_set =
 
565
                            mtree->set.flags_list->m_entry->fflags_set;
 
566
                        mtree->set.fflags_clear =
 
567
                            mtree->set.flags_list->m_entry->fflags_clear;
 
568
                } else {
484
569
                        keys &= ~F_FLAGS;
 
570
                        if ((oldkeys & F_FLAGS) != 0)
 
571
                                archive_strcat(&unsetstr, " flags");
 
572
                }
485
573
        }
486
574
        if (unsetstr.length > 0)
487
575
                archive_string_sprintf(&mtree->buf, "/unset%s\n", unsetstr.s);
491
579
        archive_string_free(&setstr);
492
580
        mtree->set.keys = keys;
493
581
        mtree->set.processed = 1;
494
 
        /* On directory-only mode, it is only once to write /set keyword. */
495
 
        if (mtree->dironly)
496
 
                mtree->set.output = 0;
497
 
}
498
 
 
499
 
static int
500
 
get_keys(struct mtree_writer *mtree, struct archive_entry *entry)
 
582
 
 
583
        free_attr_count(&mtree->set.uid_list);
 
584
        free_attr_count(&mtree->set.gid_list);
 
585
        free_attr_count(&mtree->set.mode_list);
 
586
        free_attr_count(&mtree->set.flags_list);
 
587
}
 
588
 
 
589
static struct attr_counter *
 
590
new_attr_count(struct mtree_entry *me, struct attr_counter *prev)
 
591
{
 
592
        struct attr_counter *ac;
 
593
 
 
594
        ac = malloc(sizeof(*ac));
 
595
        if (ac != NULL) {
 
596
                ac->prev = prev;
 
597
                ac->next = NULL;
 
598
                ac->count = 1;
 
599
                ac->m_entry = me;
 
600
        }
 
601
        return (ac);
 
602
}
 
603
 
 
604
static void
 
605
free_attr_count(struct attr_counter **top)
 
606
{
 
607
        struct attr_counter *ac, *tac;
 
608
 
 
609
        if (*top == NULL)
 
610
                return;
 
611
        ac = *top;
 
612
        while (ac != NULL) {
 
613
                tac = ac->next;
 
614
                free(ac);
 
615
                ac = tac;
 
616
        }
 
617
        *top = NULL;
 
618
}
 
619
 
 
620
static int
 
621
inc_attr_count(struct attr_counter **top, struct attr_counter *ac,
 
622
    struct attr_counter *last, struct mtree_entry *me)
 
623
{
 
624
        struct attr_counter *pac;
 
625
 
 
626
        if (ac != NULL) {
 
627
                ac->count++;
 
628
                if (*top == ac || ac->prev->count >= ac->count)
 
629
                        return (0);
 
630
                for (pac = ac->prev; pac; pac = pac->prev) {
 
631
                        if (pac->count >= ac->count)
 
632
                                break;
 
633
                }
 
634
                ac->prev->next = ac->next;
 
635
                if (ac->next != NULL)
 
636
                        ac->next->prev = ac->prev;
 
637
                if (pac != NULL) {
 
638
                        ac->prev = pac;
 
639
                        ac->next = pac->next;
 
640
                        pac->next = ac;
 
641
                        if (ac->next != NULL)
 
642
                                ac->next->prev = ac;
 
643
                } else {
 
644
                        ac->prev = NULL;
 
645
                        ac->next = *top;
 
646
                        *top = ac;
 
647
                        ac->next->prev = ac;
 
648
                }
 
649
        } else {
 
650
                ac = new_attr_count(me, last);
 
651
                if (ac == NULL)
 
652
                        return (-1);
 
653
                last->next = ac;
 
654
        }
 
655
        return (0);
 
656
}
 
657
 
 
658
static int
 
659
collect_set_values(struct mtree_writer *mtree, struct mtree_entry *me)
 
660
{
 
661
        int keys = mtree->keys;
 
662
        struct attr_counter *ac, *last;
 
663
 
 
664
        if (keys & (F_UNAME | F_UID)) {
 
665
                if (mtree->set.uid_list == NULL) {
 
666
                        mtree->set.uid_list = new_attr_count(me, NULL);
 
667
                        if (mtree->set.uid_list == NULL)
 
668
                                return (-1);
 
669
                } else {
 
670
                        last = NULL;
 
671
                        for (ac = mtree->set.uid_list; ac; ac = ac->next) {
 
672
                                if (ac->m_entry->uid == me->uid)
 
673
                                        break;
 
674
                                last = ac;
 
675
                        }
 
676
                        if (inc_attr_count(
 
677
                            &mtree->set.uid_list, ac, last, me) < 0)
 
678
                                return (-1);
 
679
                }
 
680
        }
 
681
        if (keys & (F_GNAME | F_GID)) {
 
682
                if (mtree->set.gid_list == NULL) {
 
683
                        mtree->set.gid_list = new_attr_count(me, NULL);
 
684
                        if (mtree->set.gid_list == NULL)
 
685
                                return (-1);
 
686
                } else {
 
687
                        last = NULL;
 
688
                        for (ac = mtree->set.gid_list; ac; ac = ac->next) {
 
689
                                if (ac->m_entry->gid == me->gid)
 
690
                                        break;
 
691
                                last = ac;
 
692
                        }
 
693
                        if (inc_attr_count(
 
694
                            &mtree->set.gid_list, ac, last, me) < 0)
 
695
                                return (-1);
 
696
                }
 
697
        }
 
698
        if (keys & F_MODE) {
 
699
                if (mtree->set.mode_list == NULL) {
 
700
                        mtree->set.mode_list = new_attr_count(me, NULL);
 
701
                        if (mtree->set.mode_list == NULL)
 
702
                                return (-1);
 
703
                } else {
 
704
                        last = NULL;
 
705
                        for (ac = mtree->set.mode_list; ac; ac = ac->next) {
 
706
                                if (ac->m_entry->mode == me->mode)
 
707
                                        break;
 
708
                                last = ac;
 
709
                        }
 
710
                        if (inc_attr_count(
 
711
                            &mtree->set.mode_list, ac, last, me) < 0)
 
712
                                return (-1);
 
713
                }
 
714
        }
 
715
        if (keys & F_FLAGS) {
 
716
                if (mtree->set.flags_list == NULL) {
 
717
                        mtree->set.flags_list = new_attr_count(me, NULL);
 
718
                        if (mtree->set.flags_list == NULL)
 
719
                                return (-1);
 
720
                } else {
 
721
                        last = NULL;
 
722
                        for (ac = mtree->set.flags_list; ac; ac = ac->next) {
 
723
                                if (ac->m_entry->fflags_set == me->fflags_set &&
 
724
                                    ac->m_entry->fflags_clear == me->fflags_clear)
 
725
                                        break;
 
726
                                last = ac;
 
727
                        }
 
728
                        if (inc_attr_count(
 
729
                            &mtree->set.flags_list, ac, last, me) < 0)
 
730
                                return (-1);
 
731
                }
 
732
        }
 
733
 
 
734
        /*
 
735
         * Save a entry.
 
736
         */
 
737
        me->next = NULL;
 
738
        *mtree->set.me_last = me;
 
739
        mtree->set.me_last = &me->next;
 
740
        return (0);
 
741
}
 
742
 
 
743
static int
 
744
get_keys(struct mtree_writer *mtree, struct mtree_entry *me)
501
745
{
502
746
        int keys;
503
747
 
504
748
        keys = mtree->keys;
 
749
 
 
750
        /*
 
751
         * If a keyword has been set by /set, we do not need to
 
752
         * output it.
 
753
         */
505
754
        if (mtree->set.keys == 0)
506
 
                return (keys);
 
755
                return (keys);/* /set is not used. */
 
756
 
507
757
        if ((mtree->set.keys & (F_GNAME | F_GID)) != 0 &&
508
 
             mtree->set.gid == archive_entry_gid(entry))
 
758
             mtree->set.gid == me->gid)
509
759
                keys &= ~(F_GNAME | F_GID);
510
760
        if ((mtree->set.keys & (F_UNAME | F_UID)) != 0 &&
511
 
             mtree->set.uid == archive_entry_uid(entry))
 
761
             mtree->set.uid == me->uid)
512
762
                keys &= ~(F_UNAME | F_UID);
513
763
        if (mtree->set.keys & F_FLAGS) {
514
 
                unsigned long set, clear;
515
 
 
516
 
                archive_entry_fflags(entry, &set, &clear);
517
 
                if (mtree->set.fflags_set == set &&
518
 
                    mtree->set.fflags_clear == clear)
 
764
                if (mtree->set.fflags_set == me->fflags_set &&
 
765
                    mtree->set.fflags_clear == me->fflags_clear)
519
766
                        keys &= ~F_FLAGS;
520
767
        }
521
 
        if ((mtree->set.keys & F_MODE) != 0 &&
522
 
             mtree->set.mode == (archive_entry_mode(entry) & 07777))
 
768
        if ((mtree->set.keys & F_MODE) != 0 && mtree->set.mode == me->mode)
523
769
                keys &= ~F_MODE;
524
770
 
525
 
        switch (archive_entry_filetype(entry)) {
 
771
        switch (me->filetype) {
526
772
        case AE_IFLNK: case AE_IFSOCK: case AE_IFCHR:
527
773
        case AE_IFBLK: case AE_IFIFO:
528
774
                break;
542
788
        return (keys);
543
789
}
544
790
 
 
791
static struct mtree_entry *
 
792
new_mtree_entry(struct archive_entry *entry)
 
793
{
 
794
        struct mtree_entry *me;
 
795
        const char *s;
 
796
 
 
797
        me = calloc(1, sizeof(*me));
 
798
        if (me == NULL)
 
799
                return (NULL);
 
800
        me->pathname = strdup(archive_entry_pathname(entry));
 
801
        if ((s = archive_entry_symlink(entry)) != NULL)
 
802
                me->symlink = strdup(s);
 
803
        else
 
804
                me->symlink = NULL;
 
805
        me->nlink = archive_entry_nlink(entry);
 
806
        me->filetype = archive_entry_filetype(entry);
 
807
        me->mode = archive_entry_mode(entry) & 07777;
 
808
        me->uid = archive_entry_uid(entry);
 
809
        me->gid = archive_entry_gid(entry);
 
810
        if ((s = archive_entry_uname(entry)) != NULL)
 
811
                me->uname = strdup(s);
 
812
        else
 
813
                me->uname = NULL;
 
814
        if ((s = archive_entry_gname(entry)) != NULL)
 
815
                me->gname = strdup(s);
 
816
        else
 
817
                me->gname = NULL;
 
818
        if ((s = archive_entry_fflags_text(entry)) != NULL)
 
819
                me->fflags_text = strdup(s);
 
820
        else
 
821
                me->fflags_text = NULL;
 
822
        archive_entry_fflags(entry, &me->fflags_set, &me->fflags_clear);
 
823
        me->mtime = archive_entry_mtime(entry);
 
824
        me->mtime_nsec = archive_entry_mtime_nsec(entry);
 
825
        me->rdevmajor = archive_entry_rdevmajor(entry);
 
826
        me->rdevminor = archive_entry_rdevminor(entry);
 
827
        me->size = archive_entry_size(entry);
 
828
        me->compute_sum = 0;
 
829
 
 
830
        return (me);
 
831
}
 
832
 
 
833
static void
 
834
free_mtree_entry(struct mtree_entry *me)
 
835
{
 
836
        free(me->pathname);
 
837
        free(me->symlink);
 
838
        free(me->uname);
 
839
        free(me->gname);
 
840
        free(me->fflags_text);
 
841
        free(me);
 
842
}
 
843
 
545
844
static int
546
845
archive_write_mtree_header(struct archive_write *a,
547
846
    struct archive_entry *entry)
548
847
{
549
848
        struct mtree_writer *mtree= a->format_data;
550
 
        struct archive_string *str;
551
 
        const char *path;
552
 
 
553
 
        mtree->entry = archive_entry_clone(entry);
554
 
        path = archive_entry_pathname(mtree->entry);
555
849
 
556
850
        if (mtree->first) {
557
851
                mtree->first = 0;
558
852
                archive_strcat(&mtree->buf, "#mtree\n");
 
853
                if ((mtree->keys & SET_KEYS) == 0)
 
854
                        mtree->set.output = 0;/* Disalbed. */
559
855
        }
560
 
        if (mtree->set.output)
561
 
                set_global(mtree, entry);
562
 
 
563
 
        archive_string_empty(&mtree->ebuf);
564
 
        str = (mtree->indent)? &mtree->ebuf : &mtree->buf;
565
 
        if (!mtree->dironly || archive_entry_filetype(entry) == AE_IFDIR)
566
 
                mtree_quote(str, path);
567
856
 
568
857
        mtree->entry_bytes_remaining = archive_entry_size(entry);
569
 
        if ((mtree->keys & F_CKSUM) != 0 &&
570
 
            archive_entry_filetype(entry) == AE_IFREG) {
571
 
                mtree->compute_sum |= F_CKSUM;
572
 
                mtree->crc = 0;
573
 
                mtree->crc_len = 0;
574
 
        } else
575
 
                mtree->compute_sum &= ~F_CKSUM;
576
 
#ifdef ARCHIVE_HAS_MD5
577
 
        if ((mtree->keys & F_MD5) != 0 &&
578
 
            archive_entry_filetype(entry) == AE_IFREG) {
579
 
                mtree->compute_sum |= F_MD5;
580
 
                archive_md5_init(&mtree->md5ctx);
581
 
        } else
582
 
                mtree->compute_sum &= ~F_MD5;
583
 
#endif
584
 
#ifdef ARCHIVE_HAS_RMD160
585
 
        if ((mtree->keys & F_RMD160) != 0 &&
586
 
            archive_entry_filetype(entry) == AE_IFREG) {
587
 
                mtree->compute_sum |= F_RMD160;
588
 
                archive_rmd160_init(&mtree->rmd160ctx);
589
 
        } else
590
 
                mtree->compute_sum &= ~F_RMD160;
591
 
#endif
592
 
#ifdef ARCHIVE_HAS_SHA1
593
 
        if ((mtree->keys & F_SHA1) != 0 &&
594
 
            archive_entry_filetype(entry) == AE_IFREG) {
595
 
                mtree->compute_sum |= F_SHA1;
596
 
                archive_sha1_init(&mtree->sha1ctx);
597
 
        } else
598
 
                mtree->compute_sum &= ~F_SHA1;
599
 
#endif
600
 
#ifdef ARCHIVE_HAS_SHA256
601
 
        if ((mtree->keys & F_SHA256) != 0 &&
602
 
            archive_entry_filetype(entry) == AE_IFREG) {
603
 
                mtree->compute_sum |= F_SHA256;
604
 
                archive_sha256_init(&mtree->sha256ctx);
605
 
        } else
606
 
                mtree->compute_sum &= ~F_SHA256;
607
 
#endif
608
 
#ifdef ARCHIVE_HAS_SHA384
609
 
        if ((mtree->keys & F_SHA384) != 0 &&
610
 
            archive_entry_filetype(entry) == AE_IFREG) {
611
 
                mtree->compute_sum |= F_SHA384;
612
 
                archive_sha384_init(&mtree->sha384ctx);
613
 
        } else
614
 
                mtree->compute_sum &= ~F_SHA384;
615
 
#endif
616
 
#ifdef ARCHIVE_HAS_SHA512
617
 
        if ((mtree->keys & F_SHA512) != 0 &&
618
 
            archive_entry_filetype(entry) == AE_IFREG) {
619
 
                mtree->compute_sum |= F_SHA512;
620
 
                archive_sha512_init(&mtree->sha512ctx);
621
 
        } else
622
 
                mtree->compute_sum &= ~F_SHA512;
623
 
#endif
 
858
        if (mtree->dironly && archive_entry_filetype(entry) != AE_IFDIR)
 
859
                return (ARCHIVE_OK);
 
860
 
 
861
        mtree->mtree_entry = new_mtree_entry(entry);
 
862
        if (mtree->mtree_entry == NULL) {
 
863
                archive_set_error(&a->archive, ENOMEM,
 
864
                    "Can't allocate mtree entry");
 
865
                return (ARCHIVE_FATAL);
 
866
        }
 
867
 
 
868
        mtree->compute_sum = 0;
 
869
 
 
870
        /* If current file is not a regular file, we do not have to
 
871
         * compute the sum of its content. */ 
 
872
        if (archive_entry_filetype(entry) != AE_IFREG)
 
873
                return (ARCHIVE_OK);
 
874
                
 
875
        /* Initialize a bunch of sum check context. */
 
876
        sum_init(mtree);
624
877
 
625
878
        return (ARCHIVE_OK);
626
879
}
627
880
 
628
 
#if defined(ARCHIVE_HAS_MD5) || defined(ARCHIVE_HAS_RMD160) || \
629
 
    defined(ARCHIVE_HAS_SHA1) || defined(ARCHIVE_HAS_SHA256) || \
630
 
    defined(ARCHIVE_HAS_SHA384) || defined(ARCHIVE_HAS_SHA512)
631
 
static void
632
 
strappend_bin(struct archive_string *s, const unsigned char *bin, int n)
633
 
{
634
 
        static const char hex[] = "0123456789abcdef";
635
 
        int i;
636
 
 
637
 
        for (i = 0; i < n; i++) {
638
 
                archive_strappend_char(s, hex[bin[i] >> 4]);
639
 
                archive_strappend_char(s, hex[bin[i] & 0x0f]);
640
 
        }
641
 
}
642
 
#endif
643
 
 
644
881
static int
645
 
archive_write_mtree_finish_entry(struct archive_write *a)
 
882
write_entry(struct archive_write *a, struct mtree_entry *me)
646
883
{
647
884
        struct mtree_writer *mtree = a->format_data;
648
 
        struct archive_entry *entry;
649
885
        struct archive_string *str;
650
 
        const char *name;
651
886
        int keys, ret;
652
887
 
653
 
        entry = mtree->entry;
654
 
        if (entry == NULL) {
655
 
                archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
656
 
                    "Finished entry without being open first.");
657
 
                return (ARCHIVE_FATAL);
658
 
        }
659
 
        mtree->entry = NULL;
660
 
 
661
 
        if (mtree->dironly && archive_entry_filetype(entry) != AE_IFDIR) {
662
 
                archive_entry_free(entry);
663
 
                return (ARCHIVE_OK);
664
 
        }
665
 
 
 
888
        archive_string_empty(&mtree->ebuf);
666
889
        str = (mtree->indent)? &mtree->ebuf : &mtree->buf;
667
 
        keys = get_keys(mtree, entry);
 
890
        mtree_quote(str, me->pathname);
 
891
        keys = get_keys(mtree, me);
668
892
        if ((keys & F_NLINK) != 0 &&
669
 
            archive_entry_nlink(entry) != 1 &&
670
 
            archive_entry_filetype(entry) != AE_IFDIR)
671
 
                archive_string_sprintf(str,
672
 
                    " nlink=%u", archive_entry_nlink(entry));
 
893
            me->nlink != 1 && me->filetype != AE_IFDIR)
 
894
                archive_string_sprintf(str, " nlink=%u", me->nlink);
673
895
 
674
 
        if ((keys & F_GNAME) != 0 &&
675
 
            (name = archive_entry_gname(entry)) != NULL) {
 
896
        if ((keys & F_GNAME) != 0 && me->gname != NULL) {
676
897
                archive_strcat(str, " gname=");
677
 
                mtree_quote(str, name);
 
898
                mtree_quote(str, me->gname);
678
899
        }
679
 
        if ((keys & F_UNAME) != 0 &&
680
 
            (name = archive_entry_uname(entry)) != NULL) {
 
900
        if ((keys & F_UNAME) != 0 && me->uname != NULL) {
681
901
                archive_strcat(str, " uname=");
682
 
                mtree_quote(str, name);
 
902
                mtree_quote(str, me->uname);
683
903
        }
684
 
        if ((keys & F_FLAGS) != 0 &&
685
 
            (name = archive_entry_fflags_text(entry)) != NULL) {
686
 
                archive_strcat(str, " flags=");
687
 
                mtree_quote(str, name);
 
904
        if ((keys & F_FLAGS) != 0) {
 
905
                if (me->fflags_text != NULL) {
 
906
                        archive_strcat(str, " flags=");
 
907
                        mtree_quote(str, me->fflags_text);
 
908
                } else if (mtree->set.processed &&
 
909
                    (mtree->set.keys & F_FLAGS) != 0)
 
910
                        /* Overwrite the global parameter. */
 
911
                        archive_strcat(str, " flags=none");
688
912
        }
689
913
        if ((keys & F_TIME) != 0)
690
914
                archive_string_sprintf(str, " time=%jd.%jd",
691
 
                    (intmax_t)archive_entry_mtime(entry),
692
 
                    (intmax_t)archive_entry_mtime_nsec(entry));
 
915
                    (intmax_t)me->mtime, (intmax_t)me->mtime_nsec);
693
916
        if ((keys & F_MODE) != 0)
694
 
                archive_string_sprintf(str, " mode=%o",
695
 
                    archive_entry_mode(entry) & 07777);
 
917
                archive_string_sprintf(str, " mode=%o", (unsigned int)me->mode);
696
918
        if ((keys & F_GID) != 0)
697
 
                archive_string_sprintf(str, " gid=%jd",
698
 
                    (intmax_t)archive_entry_gid(entry));
 
919
                archive_string_sprintf(str, " gid=%jd", (intmax_t)me->gid);
699
920
        if ((keys & F_UID) != 0)
700
 
                archive_string_sprintf(str, " uid=%jd",
701
 
                    (intmax_t)archive_entry_uid(entry));
 
921
                archive_string_sprintf(str, " uid=%jd", (intmax_t)me->uid);
702
922
 
703
 
        switch (archive_entry_filetype(entry)) {
 
923
        switch (me->filetype) {
704
924
        case AE_IFLNK:
705
925
                if ((keys & F_TYPE) != 0)
706
926
                        archive_strcat(str, " type=link");
707
927
                if ((keys & F_SLINK) != 0) {
708
928
                        archive_strcat(str, " link=");
709
 
                        mtree_quote(str, archive_entry_symlink(entry));
 
929
                        mtree_quote(str, me->symlink);
710
930
                }
711
931
                break;
712
932
        case AE_IFSOCK:
718
938
                        archive_strcat(str, " type=char");
719
939
                if ((keys & F_DEV) != 0) {
720
940
                        archive_string_sprintf(str,
721
 
                            " device=native,%d,%d",
722
 
                            archive_entry_rdevmajor(entry),
723
 
                            archive_entry_rdevminor(entry));
 
941
                            " device=native,%ju,%ju",
 
942
                            (uintmax_t)me->rdevmajor,
 
943
                            (uintmax_t)me->rdevminor);
724
944
                }
725
945
                break;
726
946
        case AE_IFBLK:
728
948
                        archive_strcat(str, " type=block");
729
949
                if ((keys & F_DEV) != 0) {
730
950
                        archive_string_sprintf(str,
731
 
                            " device=native,%d,%d",
732
 
                            archive_entry_rdevmajor(entry),
733
 
                            archive_entry_rdevminor(entry));
 
951
                            " device=native,%ju,%ju",
 
952
                            (uintmax_t)me->rdevmajor,
 
953
                            (uintmax_t)me->rdevminor);
734
954
                }
735
955
                break;
736
956
        case AE_IFDIR:
747
967
                        archive_strcat(str, " type=file");
748
968
                if ((keys & F_SIZE) != 0)
749
969
                        archive_string_sprintf(str, " size=%jd",
750
 
                            (intmax_t)archive_entry_size(entry));
 
970
                            (intmax_t)me->size);
751
971
                break;
752
972
        }
753
973
 
754
 
        if (mtree->compute_sum & F_CKSUM) {
755
 
                uint64_t len;
756
 
                /* Include the length of the file. */
757
 
                for (len = mtree->crc_len; len != 0; len >>= 8)
758
 
                        COMPUTE_CRC(mtree->crc, len & 0xff);
759
 
                mtree->crc = ~mtree->crc;
760
 
                archive_string_sprintf(str, " cksum=%ju",
761
 
                    (uintmax_t)mtree->crc);
762
 
        }
763
 
#ifdef ARCHIVE_HAS_MD5
764
 
        if (mtree->compute_sum & F_MD5) {
765
 
                unsigned char buf[16];
766
 
 
767
 
                archive_md5_final(&mtree->md5ctx, buf);
768
 
                archive_strcat(str, " md5digest=");
769
 
                strappend_bin(str, buf, sizeof(buf));
770
 
        }
771
 
#endif
772
 
#ifdef ARCHIVE_HAS_RMD160
773
 
        if (mtree->compute_sum & F_RMD160) {
774
 
                unsigned char buf[20];
775
 
 
776
 
                archive_rmd160_final(&mtree->rmd160ctx, buf);
777
 
                archive_strcat(str, " rmd160digest=");
778
 
                strappend_bin(str, buf, sizeof(buf));
779
 
        }
780
 
#endif
781
 
#ifdef ARCHIVE_HAS_SHA1
782
 
        if (mtree->compute_sum & F_SHA1) {
783
 
                unsigned char buf[20];
784
 
 
785
 
                archive_sha1_final(&mtree->sha1ctx, buf);
786
 
                archive_strcat(str, " sha1digest=");
787
 
                strappend_bin(str, buf, sizeof(buf));
788
 
        }
789
 
#endif
790
 
#ifdef ARCHIVE_HAS_SHA256
791
 
        if (mtree->compute_sum & F_SHA256) {
792
 
                unsigned char buf[32];
793
 
 
794
 
                archive_sha256_final(&mtree->sha256ctx, buf);
795
 
                archive_strcat(str, " sha256digest=");
796
 
                strappend_bin(str, buf, sizeof(buf));
797
 
        }
798
 
#endif
799
 
#ifdef ARCHIVE_HAS_SHA384
800
 
        if (mtree->compute_sum & F_SHA384) {
801
 
                unsigned char buf[48];
802
 
 
803
 
                archive_sha384_final(&mtree->sha384ctx, buf);
804
 
                archive_strcat(str, " sha384digest=");
805
 
                strappend_bin(str, buf, sizeof(buf));
806
 
        }
807
 
#endif
808
 
#ifdef ARCHIVE_HAS_SHA512
809
 
        if (mtree->compute_sum & F_SHA512) {
810
 
                unsigned char buf[64];
811
 
 
812
 
                archive_sha512_final(&mtree->sha512ctx, buf);
813
 
                archive_strcat(str, " sha512digest=");
814
 
                strappend_bin(str, buf, sizeof(buf));
815
 
        }
816
 
#endif
 
974
        /* Write a bunch of sum. */
 
975
        if (me->filetype == AE_IFREG)
 
976
                sum_write(str, me);
 
977
 
817
978
        archive_strcat(str, "\n");
818
979
        if (mtree->indent)
819
980
                mtree_indent(mtree);
820
981
 
821
 
        archive_entry_free(entry);
822
 
 
823
982
        if (mtree->buf.length > 32768) {
824
 
                ret = (a->compressor.write)(a, mtree->buf.s, mtree->buf.length);
 
983
                ret = __archive_write_output(a, mtree->buf.s, mtree->buf.length);
825
984
                archive_string_empty(&mtree->buf);
826
985
        } else
827
986
                ret = ARCHIVE_OK;
828
 
 
 
987
        return (ret);
 
988
}
 
989
 
 
990
/*
 
991
 * Write mtree entries saved at collect_set_values() function.
 
992
 */
 
993
static int
 
994
write_mtree_entries(struct archive_write *a)
 
995
{
 
996
        struct mtree_writer *mtree = a->format_data;
 
997
        struct mtree_entry *me, *tme;
 
998
        int ret;
 
999
 
 
1000
        for (me = mtree->set.me_first; me; me = me->next) {
 
1001
                ret = write_entry(a, me);
 
1002
                if (ret != ARCHIVE_OK)
 
1003
                        return (ARCHIVE_FATAL);
 
1004
        }
 
1005
 
 
1006
        me = mtree->set.me_first;
 
1007
        while (me != NULL) {
 
1008
                tme = me->next;
 
1009
                free_mtree_entry(me);
 
1010
                me = tme;
 
1011
        }
 
1012
        mtree->set.me_first = NULL;
 
1013
        mtree->set.me_last = &mtree->set.me_first;
 
1014
        return (ARCHIVE_OK);
 
1015
}
 
1016
 
 
1017
static int
 
1018
archive_write_mtree_finish_entry(struct archive_write *a)
 
1019
{
 
1020
        struct mtree_writer *mtree = a->format_data;
 
1021
        struct mtree_entry *me;
 
1022
        int ret;
 
1023
 
 
1024
        if ((me = mtree->mtree_entry) == NULL)
 
1025
                return (ARCHIVE_OK);
 
1026
        mtree->mtree_entry = NULL;
 
1027
 
 
1028
        if (me->filetype == AE_IFREG)
 
1029
                sum_final(mtree, me);
 
1030
 
 
1031
        if (mtree->set.output) {
 
1032
                if (!mtree->dironly) {
 
1033
                        if (archive_strlen(&mtree->set.parent) == 0)
 
1034
                                parent_dir_changed(&mtree->set.parent, me);
 
1035
                        if (parent_dir_changed(&mtree->set.parent, me)) {
 
1036
                                /* Write /set keyword */
 
1037
                                write_global(mtree);
 
1038
                                /* Write entries saved by
 
1039
                                 * collect_set_values() function. */
 
1040
                                ret = write_mtree_entries(a);
 
1041
                                if (ret != ARCHIVE_OK)
 
1042
                                        return (ARCHIVE_FATAL);
 
1043
                        }
 
1044
                }
 
1045
                /* Tabulate uid,gid,mode and fflags of a entry
 
1046
                 * in order to be used for /set. and, at this time
 
1047
                 * we do not write a entry.  */
 
1048
                collect_set_values(mtree, me);
 
1049
                return (ARCHIVE_OK);
 
1050
        } else {
 
1051
                /* Write the current entry and free it. */
 
1052
                ret = write_entry(a, me);
 
1053
                free_mtree_entry(me);
 
1054
        }
829
1055
        return (ret == ARCHIVE_OK ? ret : ARCHIVE_FATAL);
830
1056
}
831
1057
 
832
1058
static int
833
 
archive_write_mtree_finish(struct archive_write *a)
 
1059
archive_write_mtree_close(struct archive_write *a)
834
1060
{
835
1061
        struct mtree_writer *mtree= a->format_data;
 
1062
        int ret;
 
1063
 
 
1064
        if (mtree->set.output && mtree->set.me_first != NULL) {
 
1065
                write_global(mtree);
 
1066
                ret = write_mtree_entries(a);
 
1067
                if (ret != ARCHIVE_OK)
 
1068
                        return (ARCHIVE_FATAL);
 
1069
        }
836
1070
 
837
1071
        archive_write_set_bytes_in_last_block(&a->archive, 1);
838
1072
 
839
 
        return (a->compressor.write)(a, mtree->buf.s, mtree->buf.length);
 
1073
        return __archive_write_output(a, mtree->buf.s, mtree->buf.length);
840
1074
}
841
1075
 
842
1076
static ssize_t
846
1080
 
847
1081
        if (n > mtree->entry_bytes_remaining)
848
1082
                n = mtree->entry_bytes_remaining;
849
 
        if (mtree->dironly)
850
 
                /* We don't need compute a regular file sum */
 
1083
        mtree->entry_bytes_remaining -= n;
 
1084
 
 
1085
        /* We don't need to compute a regular file sum */
 
1086
        if (mtree->mtree_entry == NULL)
851
1087
                return (n);
852
 
        if (mtree->compute_sum & F_CKSUM) {
853
 
                /*
854
 
                 * Compute a POSIX 1003.2 checksum
855
 
                 */
856
 
                const unsigned char *p;
857
 
                size_t nn;
858
 
 
859
 
                for (nn = n, p = buff; nn--; ++p)
860
 
                        COMPUTE_CRC(mtree->crc, *p);
861
 
                mtree->crc_len += n;
862
 
        }
863
 
#ifdef ARCHIVE_HAS_MD5
864
 
        if (mtree->compute_sum & F_MD5)
865
 
                archive_md5_update(&mtree->md5ctx, buff, n);
866
 
#endif
867
 
#ifdef ARCHIVE_HAS_RMD160
868
 
        if (mtree->compute_sum & F_RMD160)
869
 
                archive_rmd160_update(&mtree->rmd160ctx, buff, n);
870
 
#endif
871
 
#ifdef ARCHIVE_HAS_SHA1
872
 
        if (mtree->compute_sum & F_SHA1)
873
 
                archive_sha1_update(&mtree->sha1ctx, buff, n);
874
 
#endif
875
 
#ifdef ARCHIVE_HAS_SHA256
876
 
        if (mtree->compute_sum & F_SHA256)
877
 
                archive_sha256_update(&mtree->sha256ctx, buff, n);
878
 
#endif
879
 
#ifdef ARCHIVE_HAS_SHA384
880
 
        if (mtree->compute_sum & F_SHA384)
881
 
                archive_sha384_update(&mtree->sha384ctx, buff, n);
882
 
#endif
883
 
#ifdef ARCHIVE_HAS_SHA512
884
 
        if (mtree->compute_sum & F_SHA512)
885
 
                archive_sha512_update(&mtree->sha512ctx, buff, n);
886
 
#endif
 
1088
 
 
1089
        if (mtree->mtree_entry->filetype == AE_IFREG)
 
1090
                sum_update(mtree, buff, n);
 
1091
 
887
1092
        return (n);
888
1093
}
889
1094
 
890
1095
static int
891
 
archive_write_mtree_destroy(struct archive_write *a)
 
1096
archive_write_mtree_free(struct archive_write *a)
892
1097
{
893
1098
        struct mtree_writer *mtree= a->format_data;
 
1099
        struct mtree_entry *me, *tme;
894
1100
 
895
1101
        if (mtree == NULL)
896
1102
                return (ARCHIVE_OK);
897
1103
 
898
 
        archive_entry_free(mtree->entry);
 
1104
        /* Make sure we dot not leave any entries. */
 
1105
        me = mtree->set.me_first;
 
1106
        while (me != NULL) {
 
1107
                tme = me->next;
 
1108
                free_mtree_entry(me);
 
1109
                me = tme;
 
1110
        }
899
1111
        archive_string_free(&mtree->ebuf);
900
1112
        archive_string_free(&mtree->buf);
901
1113
        archive_string_free(&mtree->set.parent);
 
1114
        free_attr_count(&mtree->set.uid_list);
 
1115
        free_attr_count(&mtree->set.gid_list);
 
1116
        free_attr_count(&mtree->set.mode_list);
 
1117
        free_attr_count(&mtree->set.flags_list);
902
1118
        free(mtree);
903
1119
        a->format_data = NULL;
904
1120
        return (ARCHIVE_OK);
1006
1222
                return (ARCHIVE_OK);
1007
1223
        }
1008
1224
 
1009
 
        return (ARCHIVE_WARN);
 
1225
        return (ARCHIVE_FAILED);
1010
1226
}
1011
1227
 
1012
1228
int
1015
1231
        struct archive_write *a = (struct archive_write *)_a;
1016
1232
        struct mtree_writer *mtree;
1017
1233
 
1018
 
        if (a->format_destroy != NULL)
1019
 
                (a->format_destroy)(a);
1020
 
 
1021
 
        if ((mtree = malloc(sizeof(*mtree))) == NULL) {
 
1234
        archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
 
1235
            ARCHIVE_STATE_NEW, "archive_write_set_format_mtree");
 
1236
 
 
1237
        if (a->format_free != NULL)
 
1238
                (a->format_free)(a);
 
1239
 
 
1240
        if ((mtree = calloc(1, sizeof(*mtree))) == NULL) {
1022
1241
                archive_set_error(&a->archive, ENOMEM,
1023
1242
                    "Can't allocate mtree data");
1024
1243
                return (ARCHIVE_FATAL);
1025
1244
        }
1026
1245
 
1027
 
        mtree->entry = NULL;
 
1246
        mtree->mtree_entry = NULL;
1028
1247
        mtree->first = 1;
1029
1248
        memset(&(mtree->set), 0, sizeof(mtree->set));
1030
1249
        archive_string_init(&mtree->set.parent);
1033
1252
        mtree->indent = 0;
1034
1253
        archive_string_init(&mtree->ebuf);
1035
1254
        archive_string_init(&mtree->buf);
 
1255
        mtree->set.me_first = NULL;
 
1256
        mtree->set.me_last = &mtree->set.me_first;
1036
1257
        a->format_data = mtree;
1037
 
        a->format_destroy = archive_write_mtree_destroy;
1038
 
 
1039
 
        a->pad_uncompressed = 0;
 
1258
        a->format_free = archive_write_mtree_free;
1040
1259
        a->format_name = "mtree";
1041
1260
        a->format_options = archive_write_mtree_options;
1042
1261
        a->format_write_header = archive_write_mtree_header;
1043
 
        a->format_finish = archive_write_mtree_finish;
 
1262
        a->format_close = archive_write_mtree_close;
1044
1263
        a->format_write_data = archive_write_mtree_data;
1045
1264
        a->format_finish_entry = archive_write_mtree_finish_entry;
1046
1265
        a->archive.archive_format = ARCHIVE_FORMAT_MTREE;
1048
1267
 
1049
1268
        return (ARCHIVE_OK);
1050
1269
}
 
1270
 
 
1271
static void
 
1272
sum_init(struct mtree_writer *mtree)
 
1273
{
 
1274
        if (mtree->keys & F_CKSUM) {
 
1275
                mtree->compute_sum |= F_CKSUM;
 
1276
                mtree->crc = 0;
 
1277
                mtree->crc_len = 0;
 
1278
        }
 
1279
#ifdef ARCHIVE_HAS_MD5
 
1280
        if (mtree->keys & F_MD5) {
 
1281
                if (archive_md5_init(&mtree->md5ctx) == ARCHIVE_OK)
 
1282
                        mtree->compute_sum |= F_MD5;
 
1283
                else
 
1284
                        mtree->keys &= ~F_MD5;/* Not supported. */
 
1285
        }
 
1286
#endif
 
1287
#ifdef ARCHIVE_HAS_RMD160
 
1288
        if (mtree->keys & F_RMD160) {
 
1289
                if (archive_rmd160_init(&mtree->rmd160ctx) == ARCHIVE_OK)
 
1290
                        mtree->compute_sum |= F_RMD160;
 
1291
                else
 
1292
                        mtree->keys &= ~F_RMD160;/* Not supported. */
 
1293
        }
 
1294
#endif
 
1295
#ifdef ARCHIVE_HAS_SHA1
 
1296
        if (mtree->keys & F_SHA1) {
 
1297
                if (archive_sha1_init(&mtree->sha1ctx) == ARCHIVE_OK)
 
1298
                        mtree->compute_sum |= F_SHA1;
 
1299
                else
 
1300
                        mtree->keys &= ~F_SHA1;/* Not supported. */
 
1301
        }
 
1302
#endif
 
1303
#ifdef ARCHIVE_HAS_SHA256
 
1304
        if (mtree->keys & F_SHA256) {
 
1305
                if (archive_sha256_init(&mtree->sha256ctx) == ARCHIVE_OK)
 
1306
                        mtree->compute_sum |= F_SHA256;
 
1307
                else
 
1308
                        mtree->keys &= ~F_SHA256;/* Not supported. */
 
1309
        }
 
1310
#endif
 
1311
#ifdef ARCHIVE_HAS_SHA384
 
1312
        if (mtree->keys & F_SHA384) {
 
1313
                if (archive_sha384_init(&mtree->sha384ctx) == ARCHIVE_OK)
 
1314
                        mtree->compute_sum |= F_SHA384;
 
1315
                else
 
1316
                        mtree->keys &= ~F_SHA384;/* Not supported. */
 
1317
        }
 
1318
#endif
 
1319
#ifdef ARCHIVE_HAS_SHA512
 
1320
        if (mtree->keys & F_SHA512) {
 
1321
                if (archive_sha512_init(&mtree->sha512ctx) == ARCHIVE_OK)
 
1322
                        mtree->compute_sum |= F_SHA512;
 
1323
                else
 
1324
                        mtree->keys &= ~F_SHA512;/* Not supported. */
 
1325
        }
 
1326
#endif
 
1327
}
 
1328
 
 
1329
static void
 
1330
sum_update(struct mtree_writer *mtree, const void *buff, size_t n)
 
1331
{
 
1332
        if (mtree->compute_sum & F_CKSUM) {
 
1333
                /*
 
1334
                 * Compute a POSIX 1003.2 checksum
 
1335
                 */
 
1336
                const unsigned char *p;
 
1337
                size_t nn;
 
1338
 
 
1339
                for (nn = n, p = buff; nn--; ++p)
 
1340
                        COMPUTE_CRC(mtree->crc, *p);
 
1341
                mtree->crc_len += n;
 
1342
        }
 
1343
#ifdef ARCHIVE_HAS_MD5
 
1344
        if (mtree->compute_sum & F_MD5)
 
1345
                archive_md5_update(&mtree->md5ctx, buff, n);
 
1346
#endif
 
1347
#ifdef ARCHIVE_HAS_RMD160
 
1348
        if (mtree->compute_sum & F_RMD160)
 
1349
                archive_rmd160_update(&mtree->rmd160ctx, buff, n);
 
1350
#endif
 
1351
#ifdef ARCHIVE_HAS_SHA1
 
1352
        if (mtree->compute_sum & F_SHA1)
 
1353
                archive_sha1_update(&mtree->sha1ctx, buff, n);
 
1354
#endif
 
1355
#ifdef ARCHIVE_HAS_SHA256
 
1356
        if (mtree->compute_sum & F_SHA256)
 
1357
                archive_sha256_update(&mtree->sha256ctx, buff, n);
 
1358
#endif
 
1359
#ifdef ARCHIVE_HAS_SHA384
 
1360
        if (mtree->compute_sum & F_SHA384)
 
1361
                archive_sha384_update(&mtree->sha384ctx, buff, n);
 
1362
#endif
 
1363
#ifdef ARCHIVE_HAS_SHA512
 
1364
        if (mtree->compute_sum & F_SHA512)
 
1365
                archive_sha512_update(&mtree->sha512ctx, buff, n);
 
1366
#endif
 
1367
}
 
1368
 
 
1369
static void
 
1370
sum_final(struct mtree_writer *mtree, struct mtree_entry *me)
 
1371
{
 
1372
 
 
1373
        if (mtree->compute_sum & F_CKSUM) {
 
1374
                uint64_t len;
 
1375
                /* Include the length of the file. */
 
1376
                for (len = mtree->crc_len; len != 0; len >>= 8)
 
1377
                        COMPUTE_CRC(mtree->crc, len & 0xff);
 
1378
                me->crc = ~mtree->crc;
 
1379
        }
 
1380
#ifdef ARCHIVE_HAS_MD5
 
1381
        if (mtree->compute_sum & F_MD5)
 
1382
                archive_md5_final(&mtree->md5ctx, me->buf_md5);
 
1383
#endif
 
1384
#ifdef ARCHIVE_HAS_RMD160
 
1385
        if (mtree->compute_sum & F_RMD160)
 
1386
                archive_rmd160_final(&mtree->rmd160ctx, me->buf_rmd160);
 
1387
#endif
 
1388
#ifdef ARCHIVE_HAS_SHA1
 
1389
        if (mtree->compute_sum & F_SHA1)
 
1390
                archive_sha1_final(&mtree->sha1ctx, me->buf_sha1);
 
1391
#endif
 
1392
#ifdef ARCHIVE_HAS_SHA256
 
1393
        if (mtree->compute_sum & F_SHA256)
 
1394
                archive_sha256_final(&mtree->sha256ctx, me->buf_sha256);
 
1395
#endif
 
1396
#ifdef ARCHIVE_HAS_SHA384
 
1397
        if (mtree->compute_sum & F_SHA384)
 
1398
                archive_sha384_final(&mtree->sha384ctx, me->buf_sha384);
 
1399
#endif
 
1400
#ifdef ARCHIVE_HAS_SHA512
 
1401
        if (mtree->compute_sum & F_SHA512)
 
1402
                archive_sha512_final(&mtree->sha512ctx, me->buf_sha512);
 
1403
#endif
 
1404
        /* Save what types of sum are computed. */
 
1405
        me->compute_sum = mtree->compute_sum;
 
1406
}
 
1407
 
 
1408
#if defined(ARCHIVE_HAS_MD5) || defined(ARCHIVE_HAS_RMD160) || \
 
1409
    defined(ARCHIVE_HAS_SHA1) || defined(ARCHIVE_HAS_SHA256) || \
 
1410
    defined(ARCHIVE_HAS_SHA384) || defined(ARCHIVE_HAS_SHA512)
 
1411
static void
 
1412
strappend_bin(struct archive_string *s, const unsigned char *bin, int n)
 
1413
{
 
1414
        static const char hex[] = "0123456789abcdef";
 
1415
        int i;
 
1416
 
 
1417
        for (i = 0; i < n; i++) {
 
1418
                archive_strappend_char(s, hex[bin[i] >> 4]);
 
1419
                archive_strappend_char(s, hex[bin[i] & 0x0f]);
 
1420
        }
 
1421
}
 
1422
#endif
 
1423
 
 
1424
static void
 
1425
sum_write(struct archive_string *str, struct mtree_entry *me)
 
1426
{
 
1427
 
 
1428
        if (me->compute_sum & F_CKSUM) {
 
1429
                archive_string_sprintf(str, " cksum=%ju",
 
1430
                    (uintmax_t)me->crc);
 
1431
        }
 
1432
#ifdef ARCHIVE_HAS_MD5
 
1433
        if (me->compute_sum & F_MD5) {
 
1434
                archive_strcat(str, " md5digest=");
 
1435
                strappend_bin(str, me->buf_md5, sizeof(me->buf_md5));
 
1436
        }
 
1437
#endif
 
1438
#ifdef ARCHIVE_HAS_RMD160
 
1439
        if (me->compute_sum & F_RMD160) {
 
1440
                archive_strcat(str, " rmd160digest=");
 
1441
                strappend_bin(str, me->buf_rmd160, sizeof(me->buf_rmd160));
 
1442
        }
 
1443
#endif
 
1444
#ifdef ARCHIVE_HAS_SHA1
 
1445
        if (me->compute_sum & F_SHA1) {
 
1446
                archive_strcat(str, " sha1digest=");
 
1447
                strappend_bin(str, me->buf_sha1, sizeof(me->buf_sha1));
 
1448
        }
 
1449
#endif
 
1450
#ifdef ARCHIVE_HAS_SHA256
 
1451
        if (me->compute_sum & F_SHA256) {
 
1452
                archive_strcat(str, " sha256digest=");
 
1453
                strappend_bin(str, me->buf_sha256, sizeof(me->buf_sha256));
 
1454
        }
 
1455
#endif
 
1456
#ifdef ARCHIVE_HAS_SHA384
 
1457
        if (me->compute_sum & F_SHA384) {
 
1458
                archive_strcat(str, " sha384digest=");
 
1459
                strappend_bin(str, me->buf_sha384, sizeof(me->buf_sha384));
 
1460
        }
 
1461
#endif
 
1462
#ifdef ARCHIVE_HAS_SHA512
 
1463
        if (me->compute_sum & F_SHA512) {
 
1464
                archive_strcat(str, " sha512digest=");
 
1465
                strappend_bin(str, me->buf_sha512, sizeof(me->buf_sha512));
 
1466
        }
 
1467
#endif
 
1468
}