2 * Copyright (c) 2008 Joerg Sonnenberger
3 * Copyright (c) 2009-2012 Michihiro NAKAJIMA
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
27 #include "archive_platform.h"
28 __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_mtree.c 201171 2009-12-29 06:39:07Z kientzle $");
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
38 #include "archive_crypto_private.h"
39 #include "archive_entry.h"
40 #include "archive_private.h"
41 #include "archive_write_private.h"
43 #define INDENTNAMELEN 15
46 (F_FLAGS | F_GID | F_GNAME | F_MODE | F_TYPE | F_UID | F_UNAME)
49 struct mtree_entry *next;
61 unsigned long fflags_set;
62 unsigned long fflags_clear;
71 #ifdef ARCHIVE_HAS_MD5
72 unsigned char buf_md5[16];
74 #ifdef ARCHIVE_HAS_RMD160
75 unsigned char buf_rmd160[20];
77 #ifdef ARCHIVE_HAS_SHA1
78 unsigned char buf_sha1[20];
80 #ifdef ARCHIVE_HAS_SHA256
81 unsigned char buf_sha256[32];
83 #ifdef ARCHIVE_HAS_SHA384
84 unsigned char buf_sha384[48];
86 #ifdef ARCHIVE_HAS_SHA512
87 unsigned char buf_sha512[64];
92 struct attr_counter *prev;
93 struct attr_counter *next;
95 struct mtree_entry *m_entry;
99 struct mtree_entry *mtree_entry;
100 struct archive_string ebuf;
101 struct archive_string buf;
103 uint64_t entry_bytes_remaining;
107 struct archive_string parent;
113 unsigned long fflags_set;
114 unsigned long fflags_clear;
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;
127 #ifdef ARCHIVE_HAS_MD5
128 archive_md5_ctx md5ctx;
130 #ifdef ARCHIVE_HAS_RMD160
131 archive_rmd160_ctx rmd160ctx;
133 #ifdef ARCHIVE_HAS_SHA1
134 archive_sha1_ctx sha1ctx;
136 #ifdef ARCHIVE_HAS_SHA256
137 archive_sha256_ctx sha256ctx;
139 #ifdef ARCHIVE_HAS_SHA384
140 archive_sha384_ctx sha384ctx;
142 #ifdef ARCHIVE_HAS_SHA512
143 archive_sha512_ctx sha512ctx;
145 /* Keyword options */
147 #define F_CKSUM 0x00000001 /* check sum */
148 #define F_DEV 0x00000002 /* device type */
149 #define F_DONE 0x00000004 /* directory done */
150 #define F_FLAGS 0x00000008 /* file flags */
151 #define F_GID 0x00000010 /* gid */
152 #define F_GNAME 0x00000020 /* group name */
153 #define F_IGN 0x00000040 /* ignore */
154 #define F_MAGIC 0x00000080 /* name has magic chars */
155 #define F_MD5 0x00000100 /* MD5 digest */
156 #define F_MODE 0x00000200 /* mode */
157 #define F_NLINK 0x00000400 /* number of links */
158 #define F_NOCHANGE 0x00000800 /* If owner/mode "wrong", do
160 #define F_OPT 0x00001000 /* existence optional */
161 #define F_RMD160 0x00002000 /* RIPEMD160 digest */
162 #define F_SHA1 0x00004000 /* SHA-1 digest */
163 #define F_SIZE 0x00008000 /* size */
164 #define F_SLINK 0x00010000 /* symbolic link */
165 #define F_TAGS 0x00020000 /* tags */
166 #define F_TIME 0x00040000 /* modification time */
167 #define F_TYPE 0x00080000 /* file type */
168 #define F_UID 0x00100000 /* uid */
169 #define F_UNAME 0x00200000 /* user name */
170 #define F_VISIT 0x00400000 /* file visited */
171 #define F_SHA256 0x00800000 /* SHA-256 digest */
172 #define F_SHA384 0x01000000 /* SHA-384 digest */
173 #define F_SHA512 0x02000000 /* SHA-512 digest */
176 int dironly; /* if the dironly is 1, ignore everything except
177 * directory type files. like mtree(8) -d option.
179 int indent; /* if the indent is 1, indent writing data. */
182 #define DEFAULT_KEYS (F_DEV | F_FLAGS | F_GID | F_GNAME | F_SLINK | F_MODE\
183 | F_NLINK | F_SIZE | F_TIME | F_TYPE | F_UID\
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 *);
198 #define COMPUTE_CRC(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
199 static const uint32_t crctab[] = {
201 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
202 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
203 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
204 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
205 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
206 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
207 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
208 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
209 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
210 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
211 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
212 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
213 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
214 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
215 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
216 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
217 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
218 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
219 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
220 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
221 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
222 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
223 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
224 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
225 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
226 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
227 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
228 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
229 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
230 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
231 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
232 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
233 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
234 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
235 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
236 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
237 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
238 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
239 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
240 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
241 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
242 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
243 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
244 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
245 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
246 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
247 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
248 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
249 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
250 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
251 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
255 mtree_safe_char(char c)
257 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
259 if (c >= '0' && c <= '9')
261 if (c == 35 || c == 61 || c == 92)
262 return 0; /* #, = and \ are always quoted */
264 if (c >= 33 && c <= 47) /* !"$%&'()*+,-./ */
266 if (c >= 58 && c <= 64) /* :;<>?@ */
268 if (c >= 91 && c <= 96) /* []^_` */
270 if (c >= 123 && c <= 126) /* {|}~ */
276 mtree_quote(struct archive_string *s, const char *str)
282 for (start = str; *str != '\0'; ++str) {
283 if (mtree_safe_char(*str))
286 archive_strncat(s, start, str - start);
287 c = (unsigned char)*str;
289 buf[1] = (c / 64) + '0';
290 buf[2] = (c / 8 % 8) + '0';
291 buf[3] = (c % 8) + '0';
292 archive_strncat(s, buf, 4);
297 archive_strncat(s, start, str - start);
301 * Indent a line as mtree utility to be readable for people.
304 mtree_indent(struct mtree_writer *mtree)
307 const char *r, *s, *x;
310 s = r = mtree->ebuf.s;
314 while ((r = strchr(r, ' ')) != NULL) {
317 archive_strncat(&mtree->buf, s, r - s);
318 if (r -s > INDENTNAMELEN) {
319 archive_strncat(&mtree->buf, " \\\n", 3);
320 for (i = 0; i < (INDENTNAMELEN + 1); i++)
321 archive_strappend_char(&mtree->buf, ' ');
323 for (i = r -s; i < (INDENTNAMELEN + 1); i++)
324 archive_strappend_char(&mtree->buf, ' ');
330 if (r - s <= MAXLINELEN - 3 - INDENTNAMELEN)
335 archive_strncat(&mtree->buf, s, x - s);
336 archive_strncat(&mtree->buf, " \\\n", 3);
337 for (i = 0; i < (INDENTNAMELEN + 1); i++)
338 archive_strappend_char(&mtree->buf, ' ');
343 if (x != NULL && strlen(s) > MAXLINELEN - 3 - INDENTNAMELEN) {
344 /* Last keyword is longer. */
345 archive_strncat(&mtree->buf, s, x - s);
346 archive_strncat(&mtree->buf, " \\\n", 3);
347 for (i = 0; i < (INDENTNAMELEN + 1); i++)
348 archive_strappend_char(&mtree->buf, ' ');
351 archive_strcat(&mtree->buf, s);
352 archive_string_empty(&mtree->ebuf);
355 #if !defined(_WIN32) || defined(__CYGWIN__)
357 dir_len(struct mtree_entry *me)
359 const char *path, *r;
362 r = strrchr(path, '/');
365 /* Include a separator size */
366 return (r - path + 1);
369 #else /* _WIN32 && !__CYGWIN__ */
371 * Note: We should use wide-character for findng '\' character,
372 * a directory separator on Windows, because some character-set have
373 * been using the '\' character for a part of its multibyte character
377 dir_len(struct mtree_entry *me)
386 for (p = path; *p != '\0'; ++p) {
397 l = mbtowc(&wc, p, size);
400 if (l == 1 && (wc == L'/' || wc == L'\\'))
405 return (rp - path + 1);
407 if (al == (size_t)-1)
411 #endif /* _WIN32 && !__CYGWIN__ */
414 * Test if a parent directory of the current entry is changed.
417 parent_dir_changed(struct archive_string *dir, struct mtree_entry *me)
424 if (archive_strlen(dir) > 0) {
426 archive_string_empty(dir);
429 if (strncmp(dir->s, path, l) == 0)
430 return (0); /* The parent directory is the same. */
432 return (0); /* The parent directory is the same. */
433 archive_strncpy(dir, path, l);
438 * Write /set keyword.
439 * Set most used value of uid,gid,mode and fflags, which are
440 * collected by collect_set_values() function.
443 write_global(struct mtree_writer *mtree)
445 struct archive_string setstr;
446 struct archive_string unsetstr;
448 int keys, oldkeys, effkeys;
449 struct attr_counter *ac;
451 archive_string_init(&setstr);
452 archive_string_init(&unsetstr);
453 keys = mtree->keys & SET_KEYS;
454 oldkeys = mtree->set.keys;
456 if (mtree->set.processed) {
458 * Check if the global data needs updating.
461 if (oldkeys & (F_UNAME | F_UID)) {
462 ac = mtree->set.uid_list;
464 if (mtree->set.uid == ac->m_entry->uid) {
465 effkeys &= ~(F_UNAME | F_UID);
468 if (ac->next != NULL &&
469 ac->next->count == ac->count)
473 if (oldkeys & (F_GNAME | F_GID)) {
474 ac = mtree->set.gid_list;
476 if (mtree->set.gid == ac->m_entry->gid) {
477 effkeys &= ~(F_GNAME | F_GID);
480 if (ac->next != NULL &&
481 ac->next->count == ac->count)
485 if (oldkeys & F_MODE) {
486 ac = mtree->set.mode_list;
488 if (mtree->set.mode == ac->m_entry->mode) {
492 if (ac->next != NULL &&
493 ac->next->count == ac->count)
497 if ((oldkeys & F_FLAGS) != 0) {
498 ac = mtree->set.flags_list;
500 if (ac->m_entry->fflags_set ==
501 mtree->set.fflags_set &&
502 ac->m_entry->fflags_clear ==
503 mtree->set.fflags_clear) {
507 if (ac->next != NULL &&
508 ac->next->count == ac->count)
513 if ((keys & effkeys & F_TYPE) != 0) {
514 if (mtree->dironly) {
515 archive_strcat(&setstr, " type=dir");
516 mtree->set.type = AE_IFDIR;
518 archive_strcat(&setstr, " type=file");
519 mtree->set.type = AE_IFREG;
522 if ((keys & effkeys & F_UNAME) != 0) {
523 name = mtree->set.uid_list->m_entry->uname;
525 archive_strcat(&setstr, " uname=");
526 mtree_quote(&setstr, name);
529 if ((oldkeys & F_UNAME) != 0)
530 archive_strcat(&unsetstr, " uname");
533 if ((keys & effkeys & F_UID) != 0) {
534 mtree->set.uid = mtree->set.uid_list->m_entry->uid;
535 archive_string_sprintf(&setstr, " uid=%jd",
536 (intmax_t)mtree->set.uid);
538 if ((keys & effkeys & F_GNAME) != 0) {
539 name = mtree->set.gid_list->m_entry->gname;
541 archive_strcat(&setstr, " gname=");
542 mtree_quote(&setstr, name);
545 if ((oldkeys & F_GNAME) != 0)
546 archive_strcat(&unsetstr, " gname");
549 if ((keys & effkeys & F_GID) != 0) {
550 mtree->set.gid = mtree->set.gid_list->m_entry->gid;
551 archive_string_sprintf(&setstr, " gid=%jd",
552 (intmax_t)mtree->set.gid);
554 if ((keys & effkeys & F_MODE) != 0) {
555 mtree->set.mode = mtree->set.mode_list->m_entry->mode;
556 archive_string_sprintf(&setstr, " mode=%o",
557 (unsigned int)mtree->set.mode);
559 if ((keys & effkeys & F_FLAGS) != 0) {
560 name = mtree->set.flags_list->m_entry->fflags_text;
562 archive_strcat(&setstr, " flags=");
563 mtree_quote(&setstr, name);
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;
570 if ((oldkeys & F_FLAGS) != 0)
571 archive_strcat(&unsetstr, " flags");
574 if (unsetstr.length > 0)
575 archive_string_sprintf(&mtree->buf, "/unset%s\n", unsetstr.s);
576 archive_string_free(&unsetstr);
577 if (setstr.length > 0)
578 archive_string_sprintf(&mtree->buf, "/set%s\n", setstr.s);
579 archive_string_free(&setstr);
580 mtree->set.keys = keys;
581 mtree->set.processed = 1;
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);
589 static struct attr_counter *
590 new_attr_count(struct mtree_entry *me, struct attr_counter *prev)
592 struct attr_counter *ac;
594 ac = malloc(sizeof(*ac));
605 free_attr_count(struct attr_counter **top)
607 struct attr_counter *ac, *tac;
621 inc_attr_count(struct attr_counter **top, struct attr_counter *ac,
622 struct attr_counter *last, struct mtree_entry *me)
624 struct attr_counter *pac;
628 if (*top == ac || ac->prev->count >= ac->count)
630 for (pac = ac->prev; pac; pac = pac->prev) {
631 if (pac->count >= ac->count)
634 ac->prev->next = ac->next;
635 if (ac->next != NULL)
636 ac->next->prev = ac->prev;
639 ac->next = pac->next;
641 if (ac->next != NULL)
650 ac = new_attr_count(me, last);
659 collect_set_values(struct mtree_writer *mtree, struct mtree_entry *me)
661 int keys = mtree->keys;
662 struct attr_counter *ac, *last;
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)
671 for (ac = mtree->set.uid_list; ac; ac = ac->next) {
672 if (ac->m_entry->uid == me->uid)
677 &mtree->set.uid_list, ac, last, me) < 0)
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)
688 for (ac = mtree->set.gid_list; ac; ac = ac->next) {
689 if (ac->m_entry->gid == me->gid)
694 &mtree->set.gid_list, ac, last, me) < 0)
699 if (mtree->set.mode_list == NULL) {
700 mtree->set.mode_list = new_attr_count(me, NULL);
701 if (mtree->set.mode_list == NULL)
705 for (ac = mtree->set.mode_list; ac; ac = ac->next) {
706 if (ac->m_entry->mode == me->mode)
711 &mtree->set.mode_list, ac, last, me) < 0)
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)
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)
729 &mtree->set.flags_list, ac, last, me) < 0)
738 *mtree->set.me_last = me;
739 mtree->set.me_last = &me->next;
744 get_keys(struct mtree_writer *mtree, struct mtree_entry *me)
751 * If a keyword has been set by /set, we do not need to
754 if (mtree->set.keys == 0)
755 return (keys);/* /set is not used. */
757 if ((mtree->set.keys & (F_GNAME | F_GID)) != 0 &&
758 mtree->set.gid == me->gid)
759 keys &= ~(F_GNAME | F_GID);
760 if ((mtree->set.keys & (F_UNAME | F_UID)) != 0 &&
761 mtree->set.uid == me->uid)
762 keys &= ~(F_UNAME | F_UID);
763 if (mtree->set.keys & F_FLAGS) {
764 if (mtree->set.fflags_set == me->fflags_set &&
765 mtree->set.fflags_clear == me->fflags_clear)
768 if ((mtree->set.keys & F_MODE) != 0 && mtree->set.mode == me->mode)
771 switch (me->filetype) {
772 case AE_IFLNK: case AE_IFSOCK: case AE_IFCHR:
773 case AE_IFBLK: case AE_IFIFO:
776 if ((mtree->set.keys & F_TYPE) != 0 &&
777 mtree->set.type == AE_IFDIR)
781 default: /* Handle unknown file types as regular files. */
782 if ((mtree->set.keys & F_TYPE) != 0 &&
783 mtree->set.type == AE_IFREG)
791 static struct mtree_entry *
792 new_mtree_entry(struct archive_entry *entry)
794 struct mtree_entry *me;
797 me = calloc(1, sizeof(*me));
800 me->pathname = strdup(archive_entry_pathname(entry));
801 if ((s = archive_entry_symlink(entry)) != NULL)
802 me->symlink = strdup(s);
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);
814 if ((s = archive_entry_gname(entry)) != NULL)
815 me->gname = strdup(s);
818 if ((s = archive_entry_fflags_text(entry)) != NULL)
819 me->fflags_text = strdup(s);
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);
834 free_mtree_entry(struct mtree_entry *me)
840 free(me->fflags_text);
845 archive_write_mtree_header(struct archive_write *a,
846 struct archive_entry *entry)
848 struct mtree_writer *mtree= a->format_data;
852 archive_strcat(&mtree->buf, "#mtree\n");
853 if ((mtree->keys & SET_KEYS) == 0)
854 mtree->set.output = 0;/* Disalbed. */
857 mtree->entry_bytes_remaining = archive_entry_size(entry);
858 if (mtree->dironly && archive_entry_filetype(entry) != AE_IFDIR)
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);
868 mtree->compute_sum = 0;
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)
875 /* Initialize a bunch of sum check context. */
882 write_entry(struct archive_write *a, struct mtree_entry *me)
884 struct mtree_writer *mtree = a->format_data;
885 struct archive_string *str;
888 archive_string_empty(&mtree->ebuf);
889 str = (mtree->indent)? &mtree->ebuf : &mtree->buf;
890 mtree_quote(str, me->pathname);
891 keys = get_keys(mtree, me);
892 if ((keys & F_NLINK) != 0 &&
893 me->nlink != 1 && me->filetype != AE_IFDIR)
894 archive_string_sprintf(str, " nlink=%u", me->nlink);
896 if ((keys & F_GNAME) != 0 && me->gname != NULL) {
897 archive_strcat(str, " gname=");
898 mtree_quote(str, me->gname);
900 if ((keys & F_UNAME) != 0 && me->uname != NULL) {
901 archive_strcat(str, " uname=");
902 mtree_quote(str, me->uname);
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");
913 if ((keys & F_TIME) != 0)
914 archive_string_sprintf(str, " time=%jd.%jd",
915 (intmax_t)me->mtime, (intmax_t)me->mtime_nsec);
916 if ((keys & F_MODE) != 0)
917 archive_string_sprintf(str, " mode=%o", (unsigned int)me->mode);
918 if ((keys & F_GID) != 0)
919 archive_string_sprintf(str, " gid=%jd", (intmax_t)me->gid);
920 if ((keys & F_UID) != 0)
921 archive_string_sprintf(str, " uid=%jd", (intmax_t)me->uid);
923 switch (me->filetype) {
925 if ((keys & F_TYPE) != 0)
926 archive_strcat(str, " type=link");
927 if ((keys & F_SLINK) != 0) {
928 archive_strcat(str, " link=");
929 mtree_quote(str, me->symlink);
933 if ((keys & F_TYPE) != 0)
934 archive_strcat(str, " type=socket");
937 if ((keys & F_TYPE) != 0)
938 archive_strcat(str, " type=char");
939 if ((keys & F_DEV) != 0) {
940 archive_string_sprintf(str,
941 " device=native,%ju,%ju",
942 (uintmax_t)me->rdevmajor,
943 (uintmax_t)me->rdevminor);
947 if ((keys & F_TYPE) != 0)
948 archive_strcat(str, " type=block");
949 if ((keys & F_DEV) != 0) {
950 archive_string_sprintf(str,
951 " device=native,%ju,%ju",
952 (uintmax_t)me->rdevmajor,
953 (uintmax_t)me->rdevminor);
957 if ((keys & F_TYPE) != 0)
958 archive_strcat(str, " type=dir");
961 if ((keys & F_TYPE) != 0)
962 archive_strcat(str, " type=fifo");
965 default: /* Handle unknown file types as regular files. */
966 if ((keys & F_TYPE) != 0)
967 archive_strcat(str, " type=file");
968 if ((keys & F_SIZE) != 0)
969 archive_string_sprintf(str, " size=%jd",
974 /* Write a bunch of sum. */
975 if (me->filetype == AE_IFREG)
978 archive_strcat(str, "\n");
982 if (mtree->buf.length > 32768) {
983 ret = __archive_write_output(a, mtree->buf.s, mtree->buf.length);
984 archive_string_empty(&mtree->buf);
991 * Write mtree entries saved at collect_set_values() function.
994 write_mtree_entries(struct archive_write *a)
996 struct mtree_writer *mtree = a->format_data;
997 struct mtree_entry *me, *tme;
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);
1006 me = mtree->set.me_first;
1007 while (me != NULL) {
1009 free_mtree_entry(me);
1012 mtree->set.me_first = NULL;
1013 mtree->set.me_last = &mtree->set.me_first;
1014 return (ARCHIVE_OK);
1018 archive_write_mtree_finish_entry(struct archive_write *a)
1020 struct mtree_writer *mtree = a->format_data;
1021 struct mtree_entry *me;
1024 if ((me = mtree->mtree_entry) == NULL)
1025 return (ARCHIVE_OK);
1026 mtree->mtree_entry = NULL;
1028 if (me->filetype == AE_IFREG)
1029 sum_final(mtree, me);
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);
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);
1051 /* Write the current entry and free it. */
1052 ret = write_entry(a, me);
1053 free_mtree_entry(me);
1055 return (ret == ARCHIVE_OK ? ret : ARCHIVE_FATAL);
1059 archive_write_mtree_close(struct archive_write *a)
1061 struct mtree_writer *mtree= a->format_data;
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);
1071 archive_write_set_bytes_in_last_block(&a->archive, 1);
1073 return __archive_write_output(a, mtree->buf.s, mtree->buf.length);
1077 archive_write_mtree_data(struct archive_write *a, const void *buff, size_t n)
1079 struct mtree_writer *mtree= a->format_data;
1081 if (n > mtree->entry_bytes_remaining)
1082 n = (size_t)mtree->entry_bytes_remaining;
1083 mtree->entry_bytes_remaining -= n;
1085 /* We don't need to compute a regular file sum */
1086 if (mtree->mtree_entry == NULL)
1089 if (mtree->mtree_entry->filetype == AE_IFREG)
1090 sum_update(mtree, buff, n);
1096 archive_write_mtree_free(struct archive_write *a)
1098 struct mtree_writer *mtree= a->format_data;
1099 struct mtree_entry *me, *tme;
1102 return (ARCHIVE_OK);
1104 /* Make sure we dot not leave any entries. */
1105 me = mtree->set.me_first;
1106 while (me != NULL) {
1108 free_mtree_entry(me);
1111 archive_string_free(&mtree->ebuf);
1112 archive_string_free(&mtree->buf);
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);
1119 a->format_data = NULL;
1120 return (ARCHIVE_OK);
1124 archive_write_mtree_options(struct archive_write *a, const char *key,
1127 struct mtree_writer *mtree= a->format_data;
1132 if (strcmp(key, "all") == 0)
1136 if (strcmp(key, "cksum") == 0)
1140 if (strcmp(key, "device") == 0)
1142 else if (strcmp(key, "dironly") == 0) {
1143 mtree->dironly = (value != NULL)? 1: 0;
1144 return (ARCHIVE_OK);
1148 if (strcmp(key, "flags") == 0)
1152 if (strcmp(key, "gid") == 0)
1154 else if (strcmp(key, "gname") == 0)
1158 if (strcmp(key, "indent") == 0) {
1159 mtree->indent = (value != NULL)? 1: 0;
1160 return (ARCHIVE_OK);
1164 if (strcmp(key, "link") == 0)
1168 if (strcmp(key, "md5") == 0 ||
1169 strcmp(key, "md5digest") == 0)
1171 if (strcmp(key, "mode") == 0)
1175 if (strcmp(key, "nlink") == 0)
1179 if (strcmp(key, "ripemd160digest") == 0 ||
1180 strcmp(key, "rmd160") == 0 ||
1181 strcmp(key, "rmd160digest") == 0)
1185 if (strcmp(key, "sha1") == 0 ||
1186 strcmp(key, "sha1digest") == 0)
1188 if (strcmp(key, "sha256") == 0 ||
1189 strcmp(key, "sha256digest") == 0)
1191 if (strcmp(key, "sha384") == 0 ||
1192 strcmp(key, "sha384digest") == 0)
1194 if (strcmp(key, "sha512") == 0 ||
1195 strcmp(key, "sha512digest") == 0)
1197 if (strcmp(key, "size") == 0)
1201 if (strcmp(key, "time") == 0)
1203 else if (strcmp(key, "type") == 0)
1207 if (strcmp(key, "uid") == 0)
1209 else if (strcmp(key, "uname") == 0)
1211 else if (strcmp(key, "use-set") == 0) {
1212 mtree->set.output = (value != NULL)? 1: 0;
1213 return (ARCHIVE_OK);
1219 mtree->keys |= keybit;
1221 mtree->keys &= ~keybit;
1222 return (ARCHIVE_OK);
1225 /* Note: The "warn" return is just to inform the options
1226 * supervisor that we didn't handle it. It will generate
1227 * a suitable error if no one used this option. */
1228 return (ARCHIVE_WARN);
1232 archive_write_set_format_mtree(struct archive *_a)
1234 struct archive_write *a = (struct archive_write *)_a;
1235 struct mtree_writer *mtree;
1237 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
1238 ARCHIVE_STATE_NEW, "archive_write_set_format_mtree");
1240 if (a->format_free != NULL)
1241 (a->format_free)(a);
1243 if ((mtree = calloc(1, sizeof(*mtree))) == NULL) {
1244 archive_set_error(&a->archive, ENOMEM,
1245 "Can't allocate mtree data");
1246 return (ARCHIVE_FATAL);
1249 mtree->mtree_entry = NULL;
1251 memset(&(mtree->set), 0, sizeof(mtree->set));
1252 archive_string_init(&mtree->set.parent);
1253 mtree->keys = DEFAULT_KEYS;
1256 archive_string_init(&mtree->ebuf);
1257 archive_string_init(&mtree->buf);
1258 mtree->set.me_first = NULL;
1259 mtree->set.me_last = &mtree->set.me_first;
1260 a->format_data = mtree;
1261 a->format_free = archive_write_mtree_free;
1262 a->format_name = "mtree";
1263 a->format_options = archive_write_mtree_options;
1264 a->format_write_header = archive_write_mtree_header;
1265 a->format_close = archive_write_mtree_close;
1266 a->format_write_data = archive_write_mtree_data;
1267 a->format_finish_entry = archive_write_mtree_finish_entry;
1268 a->archive.archive_format = ARCHIVE_FORMAT_MTREE;
1269 a->archive.archive_format_name = "mtree";
1271 return (ARCHIVE_OK);
1275 sum_init(struct mtree_writer *mtree)
1277 if (mtree->keys & F_CKSUM) {
1278 mtree->compute_sum |= F_CKSUM;
1282 #ifdef ARCHIVE_HAS_MD5
1283 if (mtree->keys & F_MD5) {
1284 if (archive_md5_init(&mtree->md5ctx) == ARCHIVE_OK)
1285 mtree->compute_sum |= F_MD5;
1287 mtree->keys &= ~F_MD5;/* Not supported. */
1290 #ifdef ARCHIVE_HAS_RMD160
1291 if (mtree->keys & F_RMD160) {
1292 if (archive_rmd160_init(&mtree->rmd160ctx) == ARCHIVE_OK)
1293 mtree->compute_sum |= F_RMD160;
1295 mtree->keys &= ~F_RMD160;/* Not supported. */
1298 #ifdef ARCHIVE_HAS_SHA1
1299 if (mtree->keys & F_SHA1) {
1300 if (archive_sha1_init(&mtree->sha1ctx) == ARCHIVE_OK)
1301 mtree->compute_sum |= F_SHA1;
1303 mtree->keys &= ~F_SHA1;/* Not supported. */
1306 #ifdef ARCHIVE_HAS_SHA256
1307 if (mtree->keys & F_SHA256) {
1308 if (archive_sha256_init(&mtree->sha256ctx) == ARCHIVE_OK)
1309 mtree->compute_sum |= F_SHA256;
1311 mtree->keys &= ~F_SHA256;/* Not supported. */
1314 #ifdef ARCHIVE_HAS_SHA384
1315 if (mtree->keys & F_SHA384) {
1316 if (archive_sha384_init(&mtree->sha384ctx) == ARCHIVE_OK)
1317 mtree->compute_sum |= F_SHA384;
1319 mtree->keys &= ~F_SHA384;/* Not supported. */
1322 #ifdef ARCHIVE_HAS_SHA512
1323 if (mtree->keys & F_SHA512) {
1324 if (archive_sha512_init(&mtree->sha512ctx) == ARCHIVE_OK)
1325 mtree->compute_sum |= F_SHA512;
1327 mtree->keys &= ~F_SHA512;/* Not supported. */
1333 sum_update(struct mtree_writer *mtree, const void *buff, size_t n)
1335 if (mtree->compute_sum & F_CKSUM) {
1337 * Compute a POSIX 1003.2 checksum
1339 const unsigned char *p;
1342 for (nn = n, p = buff; nn--; ++p)
1343 COMPUTE_CRC(mtree->crc, *p);
1344 mtree->crc_len += n;
1346 #ifdef ARCHIVE_HAS_MD5
1347 if (mtree->compute_sum & F_MD5)
1348 archive_md5_update(&mtree->md5ctx, buff, n);
1350 #ifdef ARCHIVE_HAS_RMD160
1351 if (mtree->compute_sum & F_RMD160)
1352 archive_rmd160_update(&mtree->rmd160ctx, buff, n);
1354 #ifdef ARCHIVE_HAS_SHA1
1355 if (mtree->compute_sum & F_SHA1)
1356 archive_sha1_update(&mtree->sha1ctx, buff, n);
1358 #ifdef ARCHIVE_HAS_SHA256
1359 if (mtree->compute_sum & F_SHA256)
1360 archive_sha256_update(&mtree->sha256ctx, buff, n);
1362 #ifdef ARCHIVE_HAS_SHA384
1363 if (mtree->compute_sum & F_SHA384)
1364 archive_sha384_update(&mtree->sha384ctx, buff, n);
1366 #ifdef ARCHIVE_HAS_SHA512
1367 if (mtree->compute_sum & F_SHA512)
1368 archive_sha512_update(&mtree->sha512ctx, buff, n);
1373 sum_final(struct mtree_writer *mtree, struct mtree_entry *me)
1376 if (mtree->compute_sum & F_CKSUM) {
1378 /* Include the length of the file. */
1379 for (len = mtree->crc_len; len != 0; len >>= 8)
1380 COMPUTE_CRC(mtree->crc, len & 0xff);
1381 me->crc = ~mtree->crc;
1383 #ifdef ARCHIVE_HAS_MD5
1384 if (mtree->compute_sum & F_MD5)
1385 archive_md5_final(&mtree->md5ctx, me->buf_md5);
1387 #ifdef ARCHIVE_HAS_RMD160
1388 if (mtree->compute_sum & F_RMD160)
1389 archive_rmd160_final(&mtree->rmd160ctx, me->buf_rmd160);
1391 #ifdef ARCHIVE_HAS_SHA1
1392 if (mtree->compute_sum & F_SHA1)
1393 archive_sha1_final(&mtree->sha1ctx, me->buf_sha1);
1395 #ifdef ARCHIVE_HAS_SHA256
1396 if (mtree->compute_sum & F_SHA256)
1397 archive_sha256_final(&mtree->sha256ctx, me->buf_sha256);
1399 #ifdef ARCHIVE_HAS_SHA384
1400 if (mtree->compute_sum & F_SHA384)
1401 archive_sha384_final(&mtree->sha384ctx, me->buf_sha384);
1403 #ifdef ARCHIVE_HAS_SHA512
1404 if (mtree->compute_sum & F_SHA512)
1405 archive_sha512_final(&mtree->sha512ctx, me->buf_sha512);
1407 /* Save what types of sum are computed. */
1408 me->compute_sum = mtree->compute_sum;
1411 #if defined(ARCHIVE_HAS_MD5) || defined(ARCHIVE_HAS_RMD160) || \
1412 defined(ARCHIVE_HAS_SHA1) || defined(ARCHIVE_HAS_SHA256) || \
1413 defined(ARCHIVE_HAS_SHA384) || defined(ARCHIVE_HAS_SHA512)
1415 strappend_bin(struct archive_string *s, const unsigned char *bin, int n)
1417 static const char hex[] = "0123456789abcdef";
1420 for (i = 0; i < n; i++) {
1421 archive_strappend_char(s, hex[bin[i] >> 4]);
1422 archive_strappend_char(s, hex[bin[i] & 0x0f]);
1428 sum_write(struct archive_string *str, struct mtree_entry *me)
1431 if (me->compute_sum & F_CKSUM) {
1432 archive_string_sprintf(str, " cksum=%ju",
1433 (uintmax_t)me->crc);
1435 #ifdef ARCHIVE_HAS_MD5
1436 if (me->compute_sum & F_MD5) {
1437 archive_strcat(str, " md5digest=");
1438 strappend_bin(str, me->buf_md5, sizeof(me->buf_md5));
1441 #ifdef ARCHIVE_HAS_RMD160
1442 if (me->compute_sum & F_RMD160) {
1443 archive_strcat(str, " rmd160digest=");
1444 strappend_bin(str, me->buf_rmd160, sizeof(me->buf_rmd160));
1447 #ifdef ARCHIVE_HAS_SHA1
1448 if (me->compute_sum & F_SHA1) {
1449 archive_strcat(str, " sha1digest=");
1450 strappend_bin(str, me->buf_sha1, sizeof(me->buf_sha1));
1453 #ifdef ARCHIVE_HAS_SHA256
1454 if (me->compute_sum & F_SHA256) {
1455 archive_strcat(str, " sha256digest=");
1456 strappend_bin(str, me->buf_sha256, sizeof(me->buf_sha256));
1459 #ifdef ARCHIVE_HAS_SHA384
1460 if (me->compute_sum & F_SHA384) {
1461 archive_strcat(str, " sha384digest=");
1462 strappend_bin(str, me->buf_sha384, sizeof(me->buf_sha384));
1465 #ifdef ARCHIVE_HAS_SHA512
1466 if (me->compute_sum & F_SHA512) {
1467 archive_strcat(str, " sha512digest=");
1468 strappend_bin(str, me->buf_sha512, sizeof(me->buf_sha512));