1 /*-
2  * Copyright (c) 2009 Michihiro NAKAJIMA
3  * Copyright (c) 2008 Joerg Sonnenberger
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "archive_platform.h"
28 __FBSDID("$FreeBSD$");
29 
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
32 #endif
33 #include <errno.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #ifdef HAVE_OPENSSL_MD5_H
37 #include <openssl/md5.h>
38 #else /* HAVE_OPENSSL_MD5_H */
39 #ifdef HAVE_MD5_H
40 #include <md5.h>
41 #endif
42 #endif /* HAVE_OPENSSL_MD5_H */
43 #ifdef HAVE_OPENSSL_RIPEMD_H
44 #include <openssl/ripemd.h>
45 #else /* HAVE_OPENSSL_RIPEMD_H */
46 #ifdef HAVE_RIPEMD_H
47 #include <ripemd.h>
48 #endif
49 #ifdef HAVE_RMD160_H
50 #include <rmd160.h>
51 #endif
52 #endif /* HAVE_OPENSSL_RIPEMD_H */
53 #ifdef HAVE_OPENSSL_SHA_H
54 #include <openssl/sha.h>
55 #else /* HAVE_OPENSSL_SHA_H */
56 #ifdef HAVE_SHA_H
57 #include <sha.h>
58 #endif
59 #ifdef HAVE_SHA1_H
60 #include <sha1.h>
61 #endif
62 #ifdef HAVE_SHA2_H
63 #include <sha2.h>
64 #endif
65 #ifdef HAVE_SHA256_H
66 #include <sha256.h>
67 #endif
68 #endif /* HAVE_OPENSSL_SHA_H */
69 
70 #include "archive.h"
71 #include "archive_entry.h"
72 #include "archive_private.h"
73 #include "archive_write_private.h"
74 
75 #define INDENTNAMELEN	15
76 #define MAXLINELEN	80
77 
78 struct mtree_writer {
79 	struct archive_entry *entry;
80 	struct archive_string ebuf;
81 	struct archive_string buf;
82 	int first;
83 	uint64_t entry_bytes_remaining;
84 	struct {
85 		int		output;
86 		int		processed;
87 		struct archive_string parent;
88 		mode_t		type;
89 		int		keys;
90 		uid_t		uid;
91 		gid_t		gid;
92 		mode_t		mode;
93 		unsigned long	fflags_set;
94 		unsigned long	fflags_clear;
95 	} set;
96 	/* chekc sum */
97 	int compute_sum;
98 	uint32_t crc;
99 	uint64_t crc_len;
100 #ifdef HAVE_MD5
101 	MD5_CTX md5ctx;
102 #endif
103 #if defined(HAVE_OPENSSL_RIPEMD_H) || defined(HAVE_RIPEMD_H)
104 	RIPEMD160_CTX rmd160ctx;
105 #elif defined(HAVE_RMD160_H)
106 	RMD160_CTX rmd160ctx;
107 #endif
108 #ifdef HAVE_SHA1
109 #if defined(HAVE_OPENSSL_SHA_H) || defined(HAVE_SHA_H)
110 	SHA_CTX sha1ctx;
111 #else
112 	SHA1_CTX sha1ctx;
113 #endif
114 #endif
115 #ifdef HAVE_SHA256
116 	SHA256_CTX sha256ctx;
117 #endif
118 #ifdef HAVE_SHA384
119 #if defined(HAVE_OPENSSL_SHA_H)
120 	SHA512_CTX sha384ctx;
121 #else
122 	SHA384_CTX sha384ctx;
123 #endif
124 #endif
125 #ifdef HAVE_SHA512
126 	SHA512_CTX sha512ctx;
127 #endif
128 	/* Keyword options */
129 	int keys;
130 #define	F_CKSUM		0x00000001		/* check sum */
131 #define	F_DEV		0x00000002		/* device type */
132 #define	F_DONE		0x00000004		/* directory done */
133 #define	F_FLAGS		0x00000008		/* file flags */
134 #define	F_GID		0x00000010		/* gid */
135 #define	F_GNAME		0x00000020		/* group name */
136 #define	F_IGN		0x00000040		/* ignore */
137 #define	F_MAGIC		0x00000080		/* name has magic chars */
138 #define	F_MD5		0x00000100		/* MD5 digest */
139 #define	F_MODE		0x00000200		/* mode */
140 #define	F_NLINK		0x00000400		/* number of links */
141 #define	F_NOCHANGE 	0x00000800		/* If owner/mode "wrong", do
142 						 * not change */
143 #define	F_OPT		0x00001000		/* existence optional */
144 #define	F_RMD160 	0x00002000		/* RIPEMD160 digest */
145 #define	F_SHA1		0x00004000		/* SHA-1 digest */
146 #define	F_SIZE		0x00008000		/* size */
147 #define	F_SLINK		0x00010000		/* symbolic link */
148 #define	F_TAGS		0x00020000		/* tags */
149 #define	F_TIME		0x00040000		/* modification time */
150 #define	F_TYPE		0x00080000		/* file type */
151 #define	F_UID		0x00100000		/* uid */
152 #define	F_UNAME		0x00200000		/* user name */
153 #define	F_VISIT		0x00400000		/* file visited */
154 #define	F_SHA256	0x00800000		/* SHA-256 digest */
155 #define	F_SHA384	0x01000000		/* SHA-384 digest */
156 #define	F_SHA512	0x02000000		/* SHA-512 digest */
157 
158 	/* Options */
159 	int dironly;		/* if the dironly is 1, ignore everything except
160 				 * directory type files. like mtree(8) -d option.
161 				 */
162 	int indent;		/* if the indent is 1, indent writing data. */
163 };
164 
165 #define DEFAULT_KEYS	(F_DEV | F_FLAGS | F_GID | F_GNAME | F_SLINK | F_MODE\
166 			 | F_NLINK | F_SIZE | F_TIME | F_TYPE | F_UID\
167 			 | F_UNAME)
168 
169 #define	COMPUTE_CRC(var, ch)	(var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
170 static const uint32_t crctab[] = {
171 	0x0,
172 	0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
173 	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
174 	0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
175 	0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
176 	0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
177 	0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
178 	0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
179 	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
180 	0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
181 	0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
182 	0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
183 	0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
184 	0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
185 	0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
186 	0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
187 	0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
188 	0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
189 	0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
190 	0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
191 	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
192 	0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
193 	0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
194 	0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
195 	0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
196 	0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
197 	0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
198 	0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
199 	0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
200 	0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
201 	0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
202 	0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
203 	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
204 	0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
205 	0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
206 	0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
207 	0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
208 	0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
209 	0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
210 	0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
211 	0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
212 	0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
213 	0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
214 	0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
215 	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
216 	0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
217 	0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
218 	0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
219 	0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
220 	0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
221 	0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
222 	0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
223 };
224 
225 static int
226 mtree_safe_char(char c)
227 {
228 	if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
229 		return 1;
230 	if (c >= '0' && c <= '9')
231 		return 1;
232 	if (c == 35 || c == 61 || c == 92)
233 		return 0; /* #, = and \ are always quoted */
234 
235 	if (c >= 33 && c <= 47) /* !"$%&'()*+,-./ */
236 		return 1;
237 	if (c >= 58 && c <= 64) /* :;<>?@ */
238 		return 1;
239 	if (c >= 91 && c <= 96) /* []^_` */
240 		return 1;
241 	if (c >= 123 && c <= 126) /* {|}~ */
242 		return 1;
243 	return 0;
244 }
245 
246 static void
247 mtree_quote(struct archive_string *s, const char *str)
248 {
249 	const char *start;
250 	char buf[4];
251 	unsigned char c;
252 
253 	for (start = str; *str != '\0'; ++str) {
254 		if (mtree_safe_char(*str))
255 			continue;
256 		if (start != str)
257 			archive_strncat(s, start, str - start);
258 		c = (unsigned char)*str;
259 		buf[0] = '\\';
260 		buf[1] = (c / 64) + '0';
261 		buf[2] = (c / 8 % 8) + '0';
262 		buf[3] = (c % 8) + '0';
263 		archive_strncat(s, buf, 4);
264 		start = str + 1;
265 	}
266 
267 	if (start != str)
268 		archive_strncat(s, start, str - start);
269 }
270 
271 static void
272 mtree_indent(struct mtree_writer *mtree)
273 {
274 	int i, fn;
275 	const char *r, *s, *x;
276 
277 	fn = 1;
278 	s = r = mtree->ebuf.s;
279 	x = NULL;
280 	while (*r == ' ')
281 		r++;
282 	while ((r = strchr(r, ' ')) != NULL) {
283 		if (fn) {
284 			fn = 0;
285 			archive_strncat(&mtree->buf, s, r - s);
286 			if (r -s > INDENTNAMELEN) {
287 				archive_strncat(&mtree->buf, " \\\n", 3);
288 				for (i = 0; i < (INDENTNAMELEN + 1); i++)
289 					archive_strappend_char(&mtree->buf, ' ');
290 			} else {
291 				for (i = r -s; i < (INDENTNAMELEN + 1); i++)
292 					archive_strappend_char(&mtree->buf, ' ');
293 			}
294 			s = ++r;
295 			x = NULL;
296 			continue;
297 		}
298 		if (r - s <= MAXLINELEN - 3 - INDENTNAMELEN)
299 			x = r++;
300 		else {
301 			if (x == NULL)
302 				x = r;
303 			archive_strncat(&mtree->buf, s, x - s);
304 			archive_strncat(&mtree->buf, " \\\n", 3);
305 			for (i = 0; i < (INDENTNAMELEN + 1); i++)
306 				archive_strappend_char(&mtree->buf, ' ');
307 			s = r = ++x;
308 			x = NULL;
309 		}
310 	}
311 	if (x != NULL && strlen(s) > MAXLINELEN - 3 - INDENTNAMELEN) {
312 		/* Last keyword is longer. */
313 		archive_strncat(&mtree->buf, s, x - s);
314 		archive_strncat(&mtree->buf, " \\\n", 3);
315 		for (i = 0; i < (INDENTNAMELEN + 1); i++)
316 			archive_strappend_char(&mtree->buf, ' ');
317 		s = ++x;
318 	}
319 	archive_strcat(&mtree->buf, s);
320 	archive_string_empty(&mtree->ebuf);
321 }
322 
323 #if !defined(_WIN32) || defined(__CYGWIN__)
324 static size_t
325 dir_len(struct archive_entry *entry)
326 {
327 	const char *path, *r;
328 
329 	path = archive_entry_pathname(entry);
330 	r = strrchr(path, '/');
331 	if (r == NULL)
332 		return (0);
333 	/* Include a separator size */
334 	return (r - path + 1);
335 }
336 
337 #else /* _WIN32 && !__CYGWIN__ */
338 /*
339  * Note: We should use wide-character for findng '\' character,
340  * a directory separator on Windows, because some character-set have
341  * been using the '\' character for a part of its multibyte character
342  * code.
343  */
344 static size_t
345 dir_len(struct archive_entry *entry)
346 {
347 	wchar_t wc;
348 	const char *path;
349 	const char *p, *rp;
350 	size_t al, l, size;
351 
352 	path = archive_entry_pathname(entry);
353 	al = l = -1;
354 	for (p = path; *p != '\0'; ++p) {
355 		if (*p == '\\')
356 			al = l = p - path;
357 		else if (*p == '/')
358 			al = p - path;
359 	}
360 	if (l == -1)
361 		goto alen;
362 	size = p - path;
363 	rp = p = path;
364 	while (*p != '\0') {
365 		l = mbtowc(&wc, p, size);
366 		if (l == -1)
367 			goto alen;
368 		if (l == 1 && (wc == L'/' || wc == L'\\'))
369 			rp = p;
370 		p += l;
371 		size -= l;
372 	}
373 	return (rp - path + 1);
374 alen:
375 	if (al == -1)
376 		return (0);
377 	return (al + 1);
378 }
379 #endif /* _WIN32 && !__CYGWIN__ */
380 
381 static int
382 parent_dir_changed(struct archive_string *dir, struct archive_entry *entry)
383 {
384 	const char *path;
385 	size_t l;
386 
387 	l = dir_len(entry);
388 	path = archive_entry_pathname(entry);
389 	if (archive_strlen(dir) > 0) {
390 		if (l == 0) {
391 			archive_string_empty(dir);
392 			return (1);
393 		}
394 		if (strncmp(dir->s, path, l) == 0)
395 			return (0); /* The parent directory is the same. */
396 	} else if (l == 0)
397 		return (0);	    /* The parent directory is the same. */
398 	archive_strncpy(dir, path, l);
399 	return (1);
400 }
401 
402 /*
403  * Write /set keyword. It means set global datas.
404  * [directory-only mode]
405  *   - It is only once to write /set keyword. It is using values of the
406  *     first entry.
407  * [normal mode]
408  *   - Write /set keyword. It is using values of the first entry whose
409  *     filetype is a regular file.
410  *   - When a parent directory of the entry whose filetype is the regular
411  *     file is changed, check the global datas and write it again if its
412  *     values are different from the entry's.
413  */
414 static void
415 set_global(struct mtree_writer *mtree, struct archive_entry *entry)
416 {
417 	struct archive_string setstr;
418 	struct archive_string unsetstr;
419 	const char *name;
420 	int keys, oldkeys, effkeys;
421 	mode_t set_type = 0;
422 
423 	switch (archive_entry_filetype(entry)) {
424 	case AE_IFLNK: case AE_IFSOCK: case AE_IFCHR:
425 	case AE_IFBLK: case AE_IFIFO:
426 		break;
427 	case AE_IFDIR:
428 		if (mtree->dironly)
429 			set_type = AE_IFDIR;
430 		break;
431 	case AE_IFREG:
432 	default:	/* Handle unknown file types as regular files. */
433 		if (!mtree->dironly)
434 			set_type = AE_IFREG;
435 		break;
436 	}
437 	if (set_type == 0)
438 		return;
439 	if (mtree->set.processed &&
440 	    !parent_dir_changed(&mtree->set.parent, entry))
441 		return;
442 	/* At first, save a parent directory of the entry for following
443 	 * entries. */
444 	if (!mtree->set.processed && set_type == AE_IFREG)
445 		parent_dir_changed(&mtree->set.parent, entry);
446 
447 	archive_string_init(&setstr);
448 	archive_string_init(&unsetstr);
449 	keys = mtree->keys & (F_FLAGS | F_GID | F_GNAME | F_NLINK | F_MODE
450 	    | F_TYPE | F_UID | F_UNAME);
451 	oldkeys = mtree->set.keys;
452 	effkeys = keys;
453 	if (mtree->set.processed) {
454 		/*
455 		 * Check the global datas for whether it needs updating.
456 		 */
457 		effkeys &= ~F_TYPE;
458 		if ((oldkeys & (F_UNAME | F_UID)) != 0 &&
459 		    mtree->set.uid == archive_entry_uid(entry))
460 			effkeys &= ~(F_UNAME | F_UID);
461 		if ((oldkeys & (F_GNAME | F_GID)) != 0 &&
462 		    mtree->set.gid == archive_entry_gid(entry))
463 			effkeys &= ~(F_GNAME | F_GID);
464 		if ((oldkeys & F_MODE) != 0 &&
465 		    mtree->set.mode == (archive_entry_mode(entry) & 07777))
466 			effkeys &= ~F_MODE;
467 		if ((oldkeys & F_FLAGS) != 0) {
468 			unsigned long	fflags_set;
469 			unsigned long	fflags_clear;
470 
471 			archive_entry_fflags(entry, &fflags_set, &fflags_clear);
472 			if (fflags_set == mtree->set.fflags_set &&
473 			    fflags_clear == mtree->set.fflags_clear)
474 				effkeys &= ~F_FLAGS;
475 		}
476 	}
477 	if ((keys & effkeys & F_TYPE) != 0) {
478 		mtree->set.type = set_type;
479 		if (set_type == AE_IFDIR)
480 			archive_strcat(&setstr, " type=dir");
481 		else
482 			archive_strcat(&setstr, " type=file");
483 	}
484 	if ((keys & effkeys & F_UNAME) != 0) {
485 		if ((name = archive_entry_uname(entry)) != NULL) {
486 			archive_strcat(&setstr, " uname=");
487 			mtree_quote(&setstr, name);
488 		} else if ((oldkeys & F_UNAME) != 0)
489 			archive_strcat(&unsetstr, " uname");
490 		else
491 			keys &= ~F_UNAME;
492 	}
493 	if ((keys & effkeys & F_UID) != 0) {
494 		mtree->set.uid = archive_entry_uid(entry);
495 		archive_string_sprintf(&setstr, " uid=%jd",
496 		    (intmax_t)mtree->set.uid);
497 	}
498 	if ((keys & effkeys & F_GNAME) != 0) {
499 		if ((name = archive_entry_gname(entry)) != NULL) {
500 			archive_strcat(&setstr, " gname=");
501 			mtree_quote(&setstr, name);
502 		} else if ((oldkeys & F_GNAME) != 0)
503 			archive_strcat(&unsetstr, " gname");
504 		else
505 			keys &= ~F_GNAME;
506 	}
507 	if ((keys & effkeys & F_GID) != 0) {
508 		mtree->set.gid = archive_entry_gid(entry);
509 		archive_string_sprintf(&setstr, " gid=%jd",
510 		    (intmax_t)mtree->set.gid);
511 	}
512 	if ((keys & effkeys & F_MODE) != 0) {
513 		mtree->set.mode = archive_entry_mode(entry) & 07777;
514 		archive_string_sprintf(&setstr, " mode=%o", mtree->set.mode);
515 	}
516 	if ((keys & effkeys & F_FLAGS) != 0) {
517 		if ((name = archive_entry_fflags_text(entry)) != NULL) {
518 			archive_strcat(&setstr, " flags=");
519 			mtree_quote(&setstr, name);
520 			archive_entry_fflags(entry, &mtree->set.fflags_set,
521 			    &mtree->set.fflags_clear);
522 		} else if ((oldkeys & F_FLAGS) != 0)
523 			archive_strcat(&unsetstr, " flags");
524 		else
525 			keys &= ~F_FLAGS;
526 	}
527 	if (unsetstr.length > 0)
528 		archive_string_sprintf(&mtree->buf, "/unset%s\n", unsetstr.s);
529 	archive_string_free(&unsetstr);
530 	if (setstr.length > 0)
531 		archive_string_sprintf(&mtree->buf, "/set%s\n", setstr.s);
532 	archive_string_free(&setstr);
533 	mtree->set.keys = keys;
534 	mtree->set.processed = 1;
535 	/* On directory-only mode, it is only once to write /set keyword. */
536 	if (mtree->dironly)
537 		mtree->set.output = 0;
538 }
539 
540 static int
541 get_keys(struct mtree_writer *mtree, struct archive_entry *entry)
542 {
543 	int keys;
544 
545 	keys = mtree->keys;
546 	if (mtree->set.keys == 0)
547 		return (keys);
548 	if ((mtree->set.keys & (F_GNAME | F_GID)) != 0 &&
549 	     mtree->set.gid == archive_entry_gid(entry))
550 		keys &= ~(F_GNAME | F_GID);
551 	if ((mtree->set.keys & (F_UNAME | F_UID)) != 0 &&
552 	     mtree->set.uid == archive_entry_uid(entry))
553 		keys &= ~(F_UNAME | F_UID);
554 	if (mtree->set.keys & F_FLAGS) {
555 		unsigned long set, clear;
556 
557 		archive_entry_fflags(entry, &set, &clear);
558 		if (mtree->set.fflags_set == set &&
559 		    mtree->set.fflags_clear == clear)
560 			keys &= ~F_FLAGS;
561 	}
562 	if ((mtree->set.keys & F_MODE) != 0 &&
563 	     mtree->set.mode == (archive_entry_mode(entry) & 07777))
564 		keys &= ~F_MODE;
565 
566 	switch (archive_entry_filetype(entry)) {
567 	case AE_IFLNK: case AE_IFSOCK: case AE_IFCHR:
568 	case AE_IFBLK: case AE_IFIFO:
569 		break;
570 	case AE_IFDIR:
571 		if ((mtree->set.keys & F_TYPE) != 0 &&
572 		    mtree->set.type == AE_IFDIR)
573 			keys &= ~F_TYPE;
574 		break;
575 	case AE_IFREG:
576 	default:	/* Handle unknown file types as regular files. */
577 		if ((mtree->set.keys & F_TYPE) != 0 &&
578 		    mtree->set.type == AE_IFREG)
579 			keys &= ~F_TYPE;
580 		break;
581 	}
582 
583 	return (keys);
584 }
585 
586 static int
587 archive_write_mtree_header(struct archive_write *a,
588     struct archive_entry *entry)
589 {
590 	struct mtree_writer *mtree= a->format_data;
591 	struct archive_string *str;
592 	const char *path;
593 
594 	mtree->entry = archive_entry_clone(entry);
595 	path = archive_entry_pathname(mtree->entry);
596 
597 	if (mtree->first) {
598 		mtree->first = 0;
599 		archive_strcat(&mtree->buf, "#mtree\n");
600 	}
601 	if (mtree->set.output)
602 		set_global(mtree, entry);
603 
604 	archive_string_empty(&mtree->ebuf);
605 	str = (mtree->indent)? &mtree->ebuf : &mtree->buf;
606 	if (!mtree->dironly || archive_entry_filetype(entry) == AE_IFDIR)
607 		mtree_quote(str, path);
608 
609 	mtree->entry_bytes_remaining = archive_entry_size(entry);
610 	if ((mtree->keys & F_CKSUM) != 0 &&
611 	    archive_entry_filetype(entry) == AE_IFREG) {
612 		mtree->compute_sum |= F_CKSUM;
613 		mtree->crc = 0;
614 		mtree->crc_len = 0;
615 	} else
616 		mtree->compute_sum &= ~F_CKSUM;
617 #ifdef HAVE_MD5
618 	if ((mtree->keys & F_MD5) != 0 &&
619 	    archive_entry_filetype(entry) == AE_IFREG) {
620 		mtree->compute_sum |= F_MD5;
621 		MD5_Init(&mtree->md5ctx);
622 	} else
623 		mtree->compute_sum &= ~F_MD5;
624 #endif
625 #ifdef HAVE_RMD160
626 	if ((mtree->keys & F_RMD160) != 0 &&
627 	    archive_entry_filetype(entry) == AE_IFREG) {
628 		mtree->compute_sum |= F_RMD160;
629 		RIPEMD160_Init(&mtree->rmd160ctx);
630 	} else
631 		mtree->compute_sum &= ~F_RMD160;
632 #endif
633 #ifdef HAVE_SHA1
634 	if ((mtree->keys & F_SHA1) != 0 &&
635 	    archive_entry_filetype(entry) == AE_IFREG) {
636 		mtree->compute_sum |= F_SHA1;
637 		SHA1_Init(&mtree->sha1ctx);
638 	} else
639 		mtree->compute_sum &= ~F_SHA1;
640 #endif
641 #ifdef HAVE_SHA256
642 	if ((mtree->keys & F_SHA256) != 0 &&
643 	    archive_entry_filetype(entry) == AE_IFREG) {
644 		mtree->compute_sum |= F_SHA256;
645 		SHA256_Init(&mtree->sha256ctx);
646 	} else
647 		mtree->compute_sum &= ~F_SHA256;
648 #endif
649 #ifdef HAVE_SHA384
650 	if ((mtree->keys & F_SHA384) != 0 &&
651 	    archive_entry_filetype(entry) == AE_IFREG) {
652 		mtree->compute_sum |= F_SHA384;
653 		SHA384_Init(&mtree->sha384ctx);
654 	} else
655 		mtree->compute_sum &= ~F_SHA384;
656 #endif
657 #ifdef HAVE_SHA512
658 	if ((mtree->keys & F_SHA512) != 0 &&
659 	    archive_entry_filetype(entry) == AE_IFREG) {
660 		mtree->compute_sum |= F_SHA512;
661 		SHA512_Init(&mtree->sha512ctx);
662 	} else
663 		mtree->compute_sum &= ~F_SHA512;
664 #endif
665 
666 	return (ARCHIVE_OK);
667 }
668 
669 #if defined(HAVE_MD5) || defined(HAVE_RMD160) || defined(HAVE_SHA1) || defined(HAVE_SHA256) || defined(HAVE_SHA384) || defined(HAVE_SHA512)
670 static void
671 strappend_bin(struct archive_string *s, const unsigned char *bin, int n)
672 {
673 	static const char hex[] = "0123456789abcdef";
674 	int i;
675 
676 	for (i = 0; i < n; i++) {
677 		archive_strappend_char(s, hex[bin[i] >> 4]);
678 		archive_strappend_char(s, hex[bin[i] & 0x0f]);
679 	}
680 }
681 #endif
682 
683 static int
684 archive_write_mtree_finish_entry(struct archive_write *a)
685 {
686 	struct mtree_writer *mtree = a->format_data;
687 	struct archive_entry *entry;
688 	struct archive_string *str;
689 	const char *name;
690 	int keys, ret;
691 
692 	entry = mtree->entry;
693 	if (entry == NULL) {
694 		archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
695 		    "Finished entry without being open first.");
696 		return (ARCHIVE_FATAL);
697 	}
698 	mtree->entry = NULL;
699 
700 	if (mtree->dironly && archive_entry_filetype(entry) != AE_IFDIR) {
701 		archive_entry_free(entry);
702 		return (ARCHIVE_OK);
703 	}
704 
705 	str = (mtree->indent)? &mtree->ebuf : &mtree->buf;
706 	keys = get_keys(mtree, entry);
707 	if ((keys & F_NLINK) != 0 &&
708 	    archive_entry_nlink(entry) != 1 &&
709 	    archive_entry_filetype(entry) != AE_IFDIR)
710 		archive_string_sprintf(str,
711 		    " nlink=%u", archive_entry_nlink(entry));
712 
713 	if ((keys & F_GNAME) != 0 &&
714 	    (name = archive_entry_gname(entry)) != NULL) {
715 		archive_strcat(str, " gname=");
716 		mtree_quote(str, name);
717 	}
718 	if ((keys & F_UNAME) != 0 &&
719 	    (name = archive_entry_uname(entry)) != NULL) {
720 		archive_strcat(str, " uname=");
721 		mtree_quote(str, name);
722 	}
723 	if ((keys & F_FLAGS) != 0 &&
724 	    (name = archive_entry_fflags_text(entry)) != NULL) {
725 		archive_strcat(str, " flags=");
726 		mtree_quote(str, name);
727 	}
728 	if ((keys & F_TIME) != 0)
729 		archive_string_sprintf(str, " time=%jd.%jd",
730 		    (intmax_t)archive_entry_mtime(entry),
731 		    (intmax_t)archive_entry_mtime_nsec(entry));
732 	if ((keys & F_MODE) != 0)
733 		archive_string_sprintf(str, " mode=%o",
734 		    archive_entry_mode(entry) & 07777);
735 	if ((keys & F_GID) != 0)
736 		archive_string_sprintf(str, " gid=%jd",
737 		    (intmax_t)archive_entry_gid(entry));
738 	if ((keys & F_UID) != 0)
739 		archive_string_sprintf(str, " uid=%jd",
740 		    (intmax_t)archive_entry_uid(entry));
741 
742 	switch (archive_entry_filetype(entry)) {
743 	case AE_IFLNK:
744 		if ((keys & F_TYPE) != 0)
745 			archive_strcat(str, " type=link");
746 		if ((keys & F_SLINK) != 0) {
747 			archive_strcat(str, " link=");
748 			mtree_quote(str, archive_entry_symlink(entry));
749 		}
750 		break;
751 	case AE_IFSOCK:
752 		if ((keys & F_TYPE) != 0)
753 			archive_strcat(str, " type=socket");
754 		break;
755 	case AE_IFCHR:
756 		if ((keys & F_TYPE) != 0)
757 			archive_strcat(str, " type=char");
758 		if ((keys & F_DEV) != 0) {
759 			archive_string_sprintf(str,
760 			    " device=native,%d,%d",
761 			    archive_entry_rdevmajor(entry),
762 			    archive_entry_rdevminor(entry));
763 		}
764 		break;
765 	case AE_IFBLK:
766 		if ((keys & F_TYPE) != 0)
767 			archive_strcat(str, " type=block");
768 		if ((keys & F_DEV) != 0) {
769 			archive_string_sprintf(str,
770 			    " device=native,%d,%d",
771 			    archive_entry_rdevmajor(entry),
772 			    archive_entry_rdevminor(entry));
773 		}
774 		break;
775 	case AE_IFDIR:
776 		if ((keys & F_TYPE) != 0)
777 			archive_strcat(str, " type=dir");
778 		break;
779 	case AE_IFIFO:
780 		if ((keys & F_TYPE) != 0)
781 			archive_strcat(str, " type=fifo");
782 		break;
783 	case AE_IFREG:
784 	default:	/* Handle unknown file types as regular files. */
785 		if ((keys & F_TYPE) != 0)
786 			archive_strcat(str, " type=file");
787 		if ((keys & F_SIZE) != 0)
788 			archive_string_sprintf(str, " size=%jd",
789 			    (intmax_t)archive_entry_size(entry));
790 		break;
791 	}
792 
793 	if (mtree->compute_sum & F_CKSUM) {
794 		uint64_t len;
795 		/* Include the length of the file. */
796 		for (len = mtree->crc_len; len != 0; len >>= 8)
797 			COMPUTE_CRC(mtree->crc, len & 0xff);
798 		mtree->crc = ~mtree->crc;
799 		archive_string_sprintf(str, " cksum=%ju",
800 		    (uintmax_t)mtree->crc);
801 	}
802 #ifdef HAVE_MD5
803 	if (mtree->compute_sum & F_MD5) {
804 		unsigned char buf[16];
805 
806 		MD5_Final(buf, &mtree->md5ctx);
807 		archive_strcat(str, " md5digest=");
808 		strappend_bin(str, buf, sizeof(buf));
809 	}
810 #endif
811 #ifdef HAVE_RMD160
812 	if (mtree->compute_sum & F_RMD160) {
813 		unsigned char buf[20];
814 
815 		RIPEMD160_Final(buf, &mtree->rmd160ctx);
816 		archive_strcat(str, " rmd160digest=");
817 		strappend_bin(str, buf, sizeof(buf));
818 	}
819 #endif
820 #ifdef HAVE_SHA1
821 	if (mtree->compute_sum & F_SHA1) {
822 		unsigned char buf[20];
823 
824 		SHA1_Final(buf, &mtree->sha1ctx);
825 		archive_strcat(str, " sha1digest=");
826 		strappend_bin(str, buf, sizeof(buf));
827 	}
828 #endif
829 #ifdef HAVE_SHA256
830 	if (mtree->compute_sum & F_SHA256) {
831 		unsigned char buf[32];
832 
833 		SHA256_Final(buf, &mtree->sha256ctx);
834 		archive_strcat(str, " sha256digest=");
835 		strappend_bin(str, buf, sizeof(buf));
836 	}
837 #endif
838 #ifdef HAVE_SHA384
839 	if (mtree->compute_sum & F_SHA384) {
840 		unsigned char buf[48];
841 
842 		SHA384_Final(buf, &mtree->sha384ctx);
843 		archive_strcat(str, " sha384digest=");
844 		strappend_bin(str, buf, sizeof(buf));
845 	}
846 #endif
847 #ifdef HAVE_SHA512
848 	if (mtree->compute_sum & F_SHA512) {
849 		unsigned char buf[64];
850 
851 		SHA512_Final(buf, &mtree->sha512ctx);
852 		archive_strcat(str, " sha512digest=");
853 		strappend_bin(str, buf, sizeof(buf));
854 	}
855 #endif
856 	archive_strcat(str, "\n");
857 	if (mtree->indent)
858 		mtree_indent(mtree);
859 
860 	archive_entry_free(entry);
861 
862 	if (mtree->buf.length > 32768) {
863 		ret = (a->compressor.write)(a, mtree->buf.s, mtree->buf.length);
864 		archive_string_empty(&mtree->buf);
865 	} else
866 		ret = ARCHIVE_OK;
867 
868 	return (ret == ARCHIVE_OK ? ret : ARCHIVE_FATAL);
869 }
870 
871 static int
872 archive_write_mtree_finish(struct archive_write *a)
873 {
874 	struct mtree_writer *mtree= a->format_data;
875 
876 	archive_write_set_bytes_in_last_block(&a->archive, 1);
877 
878 	return (a->compressor.write)(a, mtree->buf.s, mtree->buf.length);
879 }
880 
881 static ssize_t
882 archive_write_mtree_data(struct archive_write *a, const void *buff, size_t n)
883 {
884 	struct mtree_writer *mtree= a->format_data;
885 
886 	if (n > mtree->entry_bytes_remaining)
887 		n = mtree->entry_bytes_remaining;
888 	if (mtree->dironly)
889 		/* We don't need compute a regular file sum */
890 		return (n);
891 	if (mtree->compute_sum & F_CKSUM) {
892 		/*
893 		 * Compute a POSIX 1003.2 checksum
894 		 */
895 		const unsigned char *p;
896 		int nn;
897 
898 		for (nn = n, p = buff; nn--; ++p)
899 			COMPUTE_CRC(mtree->crc, *p);
900 		mtree->crc_len += n;
901 	}
902 #ifdef HAVE_MD5
903 	if (mtree->compute_sum & F_MD5)
904 		MD5_Update(&mtree->md5ctx, buff, n);
905 #endif
906 #ifdef HAVE_RMD160
907 	if (mtree->compute_sum & F_RMD160)
908 		RIPEMD160_Update(&mtree->rmd160ctx, buff, n);
909 #endif
910 #ifdef HAVE_SHA1
911 	if (mtree->compute_sum & F_SHA1)
912 		SHA1_Update(&mtree->sha1ctx, buff, n);
913 #endif
914 #ifdef HAVE_SHA256
915 	if (mtree->compute_sum & F_SHA256)
916 		SHA256_Update(&mtree->sha256ctx, buff, n);
917 #endif
918 #ifdef HAVE_SHA384
919 	if (mtree->compute_sum & F_SHA384)
920 		SHA384_Update(&mtree->sha384ctx, buff, n);
921 #endif
922 #ifdef HAVE_SHA512
923 	if (mtree->compute_sum & F_SHA512)
924 		SHA512_Update(&mtree->sha512ctx, buff, n);
925 #endif
926 	return (n);
927 }
928 
929 static int
930 archive_write_mtree_destroy(struct archive_write *a)
931 {
932 	struct mtree_writer *mtree= a->format_data;
933 
934 	if (mtree == NULL)
935 		return (ARCHIVE_OK);
936 
937 	archive_entry_free(mtree->entry);
938 	archive_string_free(&mtree->ebuf);
939 	archive_string_free(&mtree->buf);
940 	archive_string_free(&mtree->set.parent);
941 	free(mtree);
942 	a->format_data = NULL;
943 	return (ARCHIVE_OK);
944 }
945 
946 static int
947 archive_write_mtree_options(struct archive_write *a, const char *key,
948     const char *value)
949 {
950 	struct mtree_writer *mtree= a->format_data;
951 	int keybit = 0;
952 
953 	switch (key[0]) {
954 	case 'a':
955 		if (strcmp(key, "all") == 0)
956 			keybit = ~0;
957 		break;
958 	case 'c':
959 		if (strcmp(key, "cksum") == 0)
960 			keybit = F_CKSUM;
961 		break;
962 	case 'd':
963 		if (strcmp(key, "device") == 0)
964 			keybit = F_DEV;
965 		else if (strcmp(key, "dironly") == 0) {
966 			mtree->dironly = (value != NULL)? 1: 0;
967 			return (ARCHIVE_OK);
968 		}
969 		break;
970 	case 'f':
971 		if (strcmp(key, "flags") == 0)
972 			keybit = F_FLAGS;
973 		break;
974 	case 'g':
975 		if (strcmp(key, "gid") == 0)
976 			keybit = F_GID;
977 		else if (strcmp(key, "gname") == 0)
978 			keybit = F_GNAME;
979 		break;
980 	case 'i':
981 		if (strcmp(key, "indent") == 0) {
982 			mtree->indent = (value != NULL)? 1: 0;
983 			return (ARCHIVE_OK);
984 		}
985 		break;
986 	case 'l':
987 		if (strcmp(key, "link") == 0)
988 			keybit = F_SLINK;
989 		break;
990 	case 'm':
991 #ifdef HAVE_MD5
992 		if (strcmp(key, "md5") == 0 ||
993 		    strcmp(key, "md5digest") == 0)
994 			keybit = F_MD5;
995 #endif
996 		if (strcmp(key, "mode") == 0)
997 			keybit = F_MODE;
998 		break;
999 	case 'n':
1000 		if (strcmp(key, "nlink") == 0)
1001 			keybit = F_NLINK;
1002 		break;
1003 #ifdef HAVE_RMD160
1004 	case 'r':
1005 		if (strcmp(key, "ripemd160digest") == 0 ||
1006 		    strcmp(key, "rmd160") == 0 ||
1007 		    strcmp(key, "rmd160digest") == 0)
1008 			keybit = F_RMD160;
1009 		break;
1010 #endif
1011 	case 's':
1012 #ifdef HAVE_SHA1
1013 		if (strcmp(key, "sha1") == 0 ||
1014 		    strcmp(key, "sha1digest") == 0)
1015 			keybit = F_SHA1;
1016 #endif
1017 #ifdef HAVE_SHA256
1018 		if (strcmp(key, "sha256") == 0 ||
1019 		    strcmp(key, "sha256digest") == 0)
1020 			keybit = F_SHA256;
1021 #endif
1022 #ifdef HAVE_SHA384
1023 		if (strcmp(key, "sha384") == 0 ||
1024 		    strcmp(key, "sha384digest") == 0)
1025 			keybit = F_SHA384;
1026 #endif
1027 #ifdef HAVE_SHA384
1028 		if (strcmp(key, "sha512") == 0 ||
1029 		    strcmp(key, "sha512digest") == 0)
1030 			keybit = F_SHA512;
1031 #endif
1032 		if (strcmp(key, "size") == 0)
1033 			keybit = F_SIZE;
1034 		break;
1035 	case 't':
1036 		if (strcmp(key, "time") == 0)
1037 			keybit = F_TIME;
1038 		else if (strcmp(key, "type") == 0)
1039 			keybit = F_TYPE;
1040 		break;
1041 	case 'u':
1042 		if (strcmp(key, "uid") == 0)
1043 			keybit = F_UID;
1044 		else if (strcmp(key, "uname") == 0)
1045 			keybit = F_UNAME;
1046 		else if (strcmp(key, "use-set") == 0) {
1047 			mtree->set.output = (value != NULL)? 1: 0;
1048 			return (ARCHIVE_OK);
1049 		}
1050 		break;
1051 	}
1052 	if (keybit != 0) {
1053 		if (value != NULL)
1054 			mtree->keys |= keybit;
1055 		else
1056 			mtree->keys &= ~keybit;
1057 		return (ARCHIVE_OK);
1058 	}
1059 
1060 	return (ARCHIVE_WARN);
1061 }
1062 
1063 int
1064 archive_write_set_format_mtree(struct archive *_a)
1065 {
1066 	struct archive_write *a = (struct archive_write *)_a;
1067 	struct mtree_writer *mtree;
1068 
1069 	if (a->format_destroy != NULL)
1070 		(a->format_destroy)(a);
1071 
1072 	if ((mtree = malloc(sizeof(*mtree))) == NULL) {
1073 		archive_set_error(&a->archive, ENOMEM,
1074 		    "Can't allocate mtree data");
1075 		return (ARCHIVE_FATAL);
1076 	}
1077 
1078 	mtree->entry = NULL;
1079 	mtree->first = 1;
1080 	memset(&(mtree->set), 0, sizeof(mtree->set));
1081 	archive_string_init(&mtree->set.parent);
1082 	mtree->keys = DEFAULT_KEYS;
1083 	mtree->dironly = 0;
1084 	mtree->indent = 0;
1085 	archive_string_init(&mtree->ebuf);
1086 	archive_string_init(&mtree->buf);
1087 	a->format_data = mtree;
1088 	a->format_destroy = archive_write_mtree_destroy;
1089 
1090 	a->pad_uncompressed = 0;
1091 	a->format_name = "mtree";
1092 	a->format_options = archive_write_mtree_options;
1093 	a->format_write_header = archive_write_mtree_header;
1094 	a->format_finish = archive_write_mtree_finish;
1095 	a->format_write_data = archive_write_mtree_data;
1096 	a->format_finish_entry = archive_write_mtree_finish_entry;
1097 	a->archive.archive_format = ARCHIVE_FORMAT_MTREE;
1098 	a->archive.archive_format_name = "mtree";
1099 
1100 	return (ARCHIVE_OK);
1101 }
1102