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: head/lib/libarchive/archive_write_set_format_mtree.c 201171 2009-12-29 06:39:07Z kientzle $");
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 
37 #include "archive.h"
38 #include "archive_entry.h"
39 #include "archive_private.h"
40 #include "archive_write_private.h"
41 
42 #include "archive_hash.h"
43 
44 #define INDENTNAMELEN	15
45 #define MAXLINELEN	80
46 
47 struct mtree_writer {
48 	struct archive_entry *entry;
49 	struct archive_string ebuf;
50 	struct archive_string buf;
51 	int first;
52 	uint64_t entry_bytes_remaining;
53 	struct {
54 		int		output;
55 		int		processed;
56 		struct archive_string parent;
57 		mode_t		type;
58 		int		keys;
59 		uid_t		uid;
60 		gid_t		gid;
61 		mode_t		mode;
62 		unsigned long	fflags_set;
63 		unsigned long	fflags_clear;
64 	} set;
65 	/* chekc sum */
66 	int compute_sum;
67 	uint32_t crc;
68 	uint64_t crc_len;
69 #ifdef ARCHIVE_HAS_MD5
70 	archive_md5_ctx md5ctx;
71 #endif
72 #ifdef ARCHIVE_HAS_RMD160
73 	archive_rmd160_ctx rmd160ctx;
74 #endif
75 #ifdef ARCHIVE_HAS_SHA1
76 	archive_sha1_ctx sha1ctx;
77 #endif
78 #ifdef ARCHIVE_HAS_SHA256
79 	archive_sha256_ctx sha256ctx;
80 #endif
81 #ifdef ARCHIVE_HAS_SHA384
82 	archive_sha384_ctx sha384ctx;
83 #endif
84 #ifdef ARCHIVE_HAS_SHA512
85 	archive_sha512_ctx sha512ctx;
86 #endif
87 	/* Keyword options */
88 	int keys;
89 #define	F_CKSUM		0x00000001		/* check sum */
90 #define	F_DEV		0x00000002		/* device type */
91 #define	F_DONE		0x00000004		/* directory done */
92 #define	F_FLAGS		0x00000008		/* file flags */
93 #define	F_GID		0x00000010		/* gid */
94 #define	F_GNAME		0x00000020		/* group name */
95 #define	F_IGN		0x00000040		/* ignore */
96 #define	F_MAGIC		0x00000080		/* name has magic chars */
97 #define	F_MD5		0x00000100		/* MD5 digest */
98 #define	F_MODE		0x00000200		/* mode */
99 #define	F_NLINK		0x00000400		/* number of links */
100 #define	F_NOCHANGE 	0x00000800		/* If owner/mode "wrong", do
101 						 * not change */
102 #define	F_OPT		0x00001000		/* existence optional */
103 #define	F_RMD160 	0x00002000		/* RIPEMD160 digest */
104 #define	F_SHA1		0x00004000		/* SHA-1 digest */
105 #define	F_SIZE		0x00008000		/* size */
106 #define	F_SLINK		0x00010000		/* symbolic link */
107 #define	F_TAGS		0x00020000		/* tags */
108 #define	F_TIME		0x00040000		/* modification time */
109 #define	F_TYPE		0x00080000		/* file type */
110 #define	F_UID		0x00100000		/* uid */
111 #define	F_UNAME		0x00200000		/* user name */
112 #define	F_VISIT		0x00400000		/* file visited */
113 #define	F_SHA256	0x00800000		/* SHA-256 digest */
114 #define	F_SHA384	0x01000000		/* SHA-384 digest */
115 #define	F_SHA512	0x02000000		/* SHA-512 digest */
116 
117 	/* Options */
118 	int dironly;		/* if the dironly is 1, ignore everything except
119 				 * directory type files. like mtree(8) -d option.
120 				 */
121 	int indent;		/* if the indent is 1, indent writing data. */
122 };
123 
124 #define DEFAULT_KEYS	(F_DEV | F_FLAGS | F_GID | F_GNAME | F_SLINK | F_MODE\
125 			 | F_NLINK | F_SIZE | F_TIME | F_TYPE | F_UID\
126 			 | F_UNAME)
127 
128 #define	COMPUTE_CRC(var, ch)	(var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
129 static const uint32_t crctab[] = {
130 	0x0,
131 	0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
132 	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
133 	0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
134 	0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
135 	0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
136 	0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
137 	0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
138 	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
139 	0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
140 	0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
141 	0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
142 	0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
143 	0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
144 	0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
145 	0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
146 	0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
147 	0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
148 	0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
149 	0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
150 	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
151 	0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
152 	0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
153 	0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
154 	0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
155 	0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
156 	0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
157 	0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
158 	0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
159 	0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
160 	0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
161 	0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
162 	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
163 	0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
164 	0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
165 	0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
166 	0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
167 	0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
168 	0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
169 	0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
170 	0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
171 	0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
172 	0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
173 	0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
174 	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
175 	0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
176 	0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
177 	0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
178 	0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
179 	0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
180 	0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
181 	0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
182 };
183 
184 static int
185 mtree_safe_char(char c)
186 {
187 	if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
188 		return 1;
189 	if (c >= '0' && c <= '9')
190 		return 1;
191 	if (c == 35 || c == 61 || c == 92)
192 		return 0; /* #, = and \ are always quoted */
193 
194 	if (c >= 33 && c <= 47) /* !"$%&'()*+,-./ */
195 		return 1;
196 	if (c >= 58 && c <= 64) /* :;<>?@ */
197 		return 1;
198 	if (c >= 91 && c <= 96) /* []^_` */
199 		return 1;
200 	if (c >= 123 && c <= 126) /* {|}~ */
201 		return 1;
202 	return 0;
203 }
204 
205 static void
206 mtree_quote(struct archive_string *s, const char *str)
207 {
208 	const char *start;
209 	char buf[4];
210 	unsigned char c;
211 
212 	for (start = str; *str != '\0'; ++str) {
213 		if (mtree_safe_char(*str))
214 			continue;
215 		if (start != str)
216 			archive_strncat(s, start, str - start);
217 		c = (unsigned char)*str;
218 		buf[0] = '\\';
219 		buf[1] = (c / 64) + '0';
220 		buf[2] = (c / 8 % 8) + '0';
221 		buf[3] = (c % 8) + '0';
222 		archive_strncat(s, buf, 4);
223 		start = str + 1;
224 	}
225 
226 	if (start != str)
227 		archive_strncat(s, start, str - start);
228 }
229 
230 static void
231 mtree_indent(struct mtree_writer *mtree)
232 {
233 	int i, fn;
234 	const char *r, *s, *x;
235 
236 	fn = 1;
237 	s = r = mtree->ebuf.s;
238 	x = NULL;
239 	while (*r == ' ')
240 		r++;
241 	while ((r = strchr(r, ' ')) != NULL) {
242 		if (fn) {
243 			fn = 0;
244 			archive_strncat(&mtree->buf, s, r - s);
245 			if (r -s > INDENTNAMELEN) {
246 				archive_strncat(&mtree->buf, " \\\n", 3);
247 				for (i = 0; i < (INDENTNAMELEN + 1); i++)
248 					archive_strappend_char(&mtree->buf, ' ');
249 			} else {
250 				for (i = r -s; i < (INDENTNAMELEN + 1); i++)
251 					archive_strappend_char(&mtree->buf, ' ');
252 			}
253 			s = ++r;
254 			x = NULL;
255 			continue;
256 		}
257 		if (r - s <= MAXLINELEN - 3 - INDENTNAMELEN)
258 			x = r++;
259 		else {
260 			if (x == NULL)
261 				x = r;
262 			archive_strncat(&mtree->buf, s, x - s);
263 			archive_strncat(&mtree->buf, " \\\n", 3);
264 			for (i = 0; i < (INDENTNAMELEN + 1); i++)
265 				archive_strappend_char(&mtree->buf, ' ');
266 			s = r = ++x;
267 			x = NULL;
268 		}
269 	}
270 	if (x != NULL && strlen(s) > MAXLINELEN - 3 - INDENTNAMELEN) {
271 		/* Last keyword is longer. */
272 		archive_strncat(&mtree->buf, s, x - s);
273 		archive_strncat(&mtree->buf, " \\\n", 3);
274 		for (i = 0; i < (INDENTNAMELEN + 1); i++)
275 			archive_strappend_char(&mtree->buf, ' ');
276 		s = ++x;
277 	}
278 	archive_strcat(&mtree->buf, s);
279 	archive_string_empty(&mtree->ebuf);
280 }
281 
282 #if !defined(_WIN32) || defined(__CYGWIN__)
283 static size_t
284 dir_len(struct archive_entry *entry)
285 {
286 	const char *path, *r;
287 
288 	path = archive_entry_pathname(entry);
289 	r = strrchr(path, '/');
290 	if (r == NULL)
291 		return (0);
292 	/* Include a separator size */
293 	return (r - path + 1);
294 }
295 
296 #else /* _WIN32 && !__CYGWIN__ */
297 /*
298  * Note: We should use wide-character for findng '\' character,
299  * a directory separator on Windows, because some character-set have
300  * been using the '\' character for a part of its multibyte character
301  * code.
302  */
303 static size_t
304 dir_len(struct archive_entry *entry)
305 {
306 	wchar_t wc;
307 	const char *path;
308 	const char *p, *rp;
309 	size_t al, l, size;
310 
311 	path = archive_entry_pathname(entry);
312 	al = l = -1;
313 	for (p = path; *p != '\0'; ++p) {
314 		if (*p == '\\')
315 			al = l = p - path;
316 		else if (*p == '/')
317 			al = p - path;
318 	}
319 	if (l == -1)
320 		goto alen;
321 	size = p - path;
322 	rp = p = path;
323 	while (*p != '\0') {
324 		l = mbtowc(&wc, p, size);
325 		if (l == -1)
326 			goto alen;
327 		if (l == 1 && (wc == L'/' || wc == L'\\'))
328 			rp = p;
329 		p += l;
330 		size -= l;
331 	}
332 	return (rp - path + 1);
333 alen:
334 	if (al == -1)
335 		return (0);
336 	return (al + 1);
337 }
338 #endif /* _WIN32 && !__CYGWIN__ */
339 
340 static int
341 parent_dir_changed(struct archive_string *dir, struct archive_entry *entry)
342 {
343 	const char *path;
344 	size_t l;
345 
346 	l = dir_len(entry);
347 	path = archive_entry_pathname(entry);
348 	if (archive_strlen(dir) > 0) {
349 		if (l == 0) {
350 			archive_string_empty(dir);
351 			return (1);
352 		}
353 		if (strncmp(dir->s, path, l) == 0)
354 			return (0); /* The parent directory is the same. */
355 	} else if (l == 0)
356 		return (0);	    /* The parent directory is the same. */
357 	archive_strncpy(dir, path, l);
358 	return (1);
359 }
360 
361 /*
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.
372  */
373 static void
374 set_global(struct mtree_writer *mtree, struct archive_entry *entry)
375 {
376 	struct archive_string setstr;
377 	struct archive_string unsetstr;
378 	const char *name;
379 	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);
405 
406 	archive_string_init(&setstr);
407 	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);
410 	oldkeys = mtree->set.keys;
411 	effkeys = keys;
412 	if (mtree->set.processed) {
413 		/*
414 		 * Check the global datas for whether it needs updating.
415 		 */
416 		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;
426 		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;
434 		}
435 	}
436 	if ((keys & effkeys & F_TYPE) != 0) {
437 		mtree->set.type = set_type;
438 		if (set_type == AE_IFDIR)
439 			archive_strcat(&setstr, " type=dir");
440 		else
441 			archive_strcat(&setstr, " type=file");
442 	}
443 	if ((keys & effkeys & F_UNAME) != 0) {
444 		if ((name = archive_entry_uname(entry)) != NULL) {
445 			archive_strcat(&setstr, " uname=");
446 			mtree_quote(&setstr, name);
447 		} else if ((oldkeys & F_UNAME) != 0)
448 			archive_strcat(&unsetstr, " uname");
449 		else
450 			keys &= ~F_UNAME;
451 	}
452 	if ((keys & effkeys & F_UID) != 0) {
453 		mtree->set.uid = archive_entry_uid(entry);
454 		archive_string_sprintf(&setstr, " uid=%jd",
455 		    (intmax_t)mtree->set.uid);
456 	}
457 	if ((keys & effkeys & F_GNAME) != 0) {
458 		if ((name = archive_entry_gname(entry)) != NULL) {
459 			archive_strcat(&setstr, " gname=");
460 			mtree_quote(&setstr, name);
461 		} else if ((oldkeys & F_GNAME) != 0)
462 			archive_strcat(&unsetstr, " gname");
463 		else
464 			keys &= ~F_GNAME;
465 	}
466 	if ((keys & effkeys & F_GID) != 0) {
467 		mtree->set.gid = archive_entry_gid(entry);
468 		archive_string_sprintf(&setstr, " gid=%jd",
469 		    (intmax_t)mtree->set.gid);
470 	}
471 	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);
474 	}
475 	if ((keys & effkeys & F_FLAGS) != 0) {
476 		if ((name = archive_entry_fflags_text(entry)) != NULL) {
477 			archive_strcat(&setstr, " flags=");
478 			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
484 			keys &= ~F_FLAGS;
485 	}
486 	if (unsetstr.length > 0)
487 		archive_string_sprintf(&mtree->buf, "/unset%s\n", unsetstr.s);
488 	archive_string_free(&unsetstr);
489 	if (setstr.length > 0)
490 		archive_string_sprintf(&mtree->buf, "/set%s\n", setstr.s);
491 	archive_string_free(&setstr);
492 	mtree->set.keys = keys;
493 	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)
501 {
502 	int keys;
503 
504 	keys = mtree->keys;
505 	if (mtree->set.keys == 0)
506 		return (keys);
507 	if ((mtree->set.keys & (F_GNAME | F_GID)) != 0 &&
508 	     mtree->set.gid == archive_entry_gid(entry))
509 		keys &= ~(F_GNAME | F_GID);
510 	if ((mtree->set.keys & (F_UNAME | F_UID)) != 0 &&
511 	     mtree->set.uid == archive_entry_uid(entry))
512 		keys &= ~(F_UNAME | F_UID);
513 	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)
519 			keys &= ~F_FLAGS;
520 	}
521 	if ((mtree->set.keys & F_MODE) != 0 &&
522 	     mtree->set.mode == (archive_entry_mode(entry) & 07777))
523 		keys &= ~F_MODE;
524 
525 	switch (archive_entry_filetype(entry)) {
526 	case AE_IFLNK: case AE_IFSOCK: case AE_IFCHR:
527 	case AE_IFBLK: case AE_IFIFO:
528 		break;
529 	case AE_IFDIR:
530 		if ((mtree->set.keys & F_TYPE) != 0 &&
531 		    mtree->set.type == AE_IFDIR)
532 			keys &= ~F_TYPE;
533 		break;
534 	case AE_IFREG:
535 	default:	/* Handle unknown file types as regular files. */
536 		if ((mtree->set.keys & F_TYPE) != 0 &&
537 		    mtree->set.type == AE_IFREG)
538 			keys &= ~F_TYPE;
539 		break;
540 	}
541 
542 	return (keys);
543 }
544 
545 static int
546 archive_write_mtree_header(struct archive_write *a,
547     struct archive_entry *entry)
548 {
549 	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 
556 	if (mtree->first) {
557 		mtree->first = 0;
558 		archive_strcat(&mtree->buf, "#mtree\n");
559 	}
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 
568 	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
624 
625 	return (ARCHIVE_OK);
626 }
627 
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 static int
645 archive_write_mtree_finish_entry(struct archive_write *a)
646 {
647 	struct mtree_writer *mtree = a->format_data;
648 	struct archive_entry *entry;
649 	struct archive_string *str;
650 	const char *name;
651 	int keys, ret;
652 
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 
666 	str = (mtree->indent)? &mtree->ebuf : &mtree->buf;
667 	keys = get_keys(mtree, entry);
668 	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));
673 
674 	if ((keys & F_GNAME) != 0 &&
675 	    (name = archive_entry_gname(entry)) != NULL) {
676 		archive_strcat(str, " gname=");
677 		mtree_quote(str, name);
678 	}
679 	if ((keys & F_UNAME) != 0 &&
680 	    (name = archive_entry_uname(entry)) != NULL) {
681 		archive_strcat(str, " uname=");
682 		mtree_quote(str, name);
683 	}
684 	if ((keys & F_FLAGS) != 0 &&
685 	    (name = archive_entry_fflags_text(entry)) != NULL) {
686 		archive_strcat(str, " flags=");
687 		mtree_quote(str, name);
688 	}
689 	if ((keys & F_TIME) != 0)
690 		archive_string_sprintf(str, " time=%jd.%jd",
691 		    (intmax_t)archive_entry_mtime(entry),
692 		    (intmax_t)archive_entry_mtime_nsec(entry));
693 	if ((keys & F_MODE) != 0)
694 		archive_string_sprintf(str, " mode=%o",
695 		    archive_entry_mode(entry) & 07777);
696 	if ((keys & F_GID) != 0)
697 		archive_string_sprintf(str, " gid=%jd",
698 		    (intmax_t)archive_entry_gid(entry));
699 	if ((keys & F_UID) != 0)
700 		archive_string_sprintf(str, " uid=%jd",
701 		    (intmax_t)archive_entry_uid(entry));
702 
703 	switch (archive_entry_filetype(entry)) {
704 	case AE_IFLNK:
705 		if ((keys & F_TYPE) != 0)
706 			archive_strcat(str, " type=link");
707 		if ((keys & F_SLINK) != 0) {
708 			archive_strcat(str, " link=");
709 			mtree_quote(str, archive_entry_symlink(entry));
710 		}
711 		break;
712 	case AE_IFSOCK:
713 		if ((keys & F_TYPE) != 0)
714 			archive_strcat(str, " type=socket");
715 		break;
716 	case AE_IFCHR:
717 		if ((keys & F_TYPE) != 0)
718 			archive_strcat(str, " type=char");
719 		if ((keys & F_DEV) != 0) {
720 			archive_string_sprintf(str,
721 			    " device=native,%d,%d",
722 			    archive_entry_rdevmajor(entry),
723 			    archive_entry_rdevminor(entry));
724 		}
725 		break;
726 	case AE_IFBLK:
727 		if ((keys & F_TYPE) != 0)
728 			archive_strcat(str, " type=block");
729 		if ((keys & F_DEV) != 0) {
730 			archive_string_sprintf(str,
731 			    " device=native,%d,%d",
732 			    archive_entry_rdevmajor(entry),
733 			    archive_entry_rdevminor(entry));
734 		}
735 		break;
736 	case AE_IFDIR:
737 		if ((keys & F_TYPE) != 0)
738 			archive_strcat(str, " type=dir");
739 		break;
740 	case AE_IFIFO:
741 		if ((keys & F_TYPE) != 0)
742 			archive_strcat(str, " type=fifo");
743 		break;
744 	case AE_IFREG:
745 	default:	/* Handle unknown file types as regular files. */
746 		if ((keys & F_TYPE) != 0)
747 			archive_strcat(str, " type=file");
748 		if ((keys & F_SIZE) != 0)
749 			archive_string_sprintf(str, " size=%jd",
750 			    (intmax_t)archive_entry_size(entry));
751 		break;
752 	}
753 
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
817 	archive_strcat(str, "\n");
818 	if (mtree->indent)
819 		mtree_indent(mtree);
820 
821 	archive_entry_free(entry);
822 
823 	if (mtree->buf.length > 32768) {
824 		ret = (a->compressor.write)(a, mtree->buf.s, mtree->buf.length);
825 		archive_string_empty(&mtree->buf);
826 	} else
827 		ret = ARCHIVE_OK;
828 
829 	return (ret == ARCHIVE_OK ? ret : ARCHIVE_FATAL);
830 }
831 
832 static int
833 archive_write_mtree_finish(struct archive_write *a)
834 {
835 	struct mtree_writer *mtree= a->format_data;
836 
837 	archive_write_set_bytes_in_last_block(&a->archive, 1);
838 
839 	return (a->compressor.write)(a, mtree->buf.s, mtree->buf.length);
840 }
841 
842 static ssize_t
843 archive_write_mtree_data(struct archive_write *a, const void *buff, size_t n)
844 {
845 	struct mtree_writer *mtree= a->format_data;
846 
847 	if (n > mtree->entry_bytes_remaining)
848 		n = mtree->entry_bytes_remaining;
849 	if (mtree->dironly)
850 		/* We don't need compute a regular file sum */
851 		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
887 	return (n);
888 }
889 
890 static int
891 archive_write_mtree_destroy(struct archive_write *a)
892 {
893 	struct mtree_writer *mtree= a->format_data;
894 
895 	if (mtree == NULL)
896 		return (ARCHIVE_OK);
897 
898 	archive_entry_free(mtree->entry);
899 	archive_string_free(&mtree->ebuf);
900 	archive_string_free(&mtree->buf);
901 	archive_string_free(&mtree->set.parent);
902 	free(mtree);
903 	a->format_data = NULL;
904 	return (ARCHIVE_OK);
905 }
906 
907 static int
908 archive_write_mtree_options(struct archive_write *a, const char *key,
909     const char *value)
910 {
911 	struct mtree_writer *mtree= a->format_data;
912 	int keybit = 0;
913 
914 	switch (key[0]) {
915 	case 'a':
916 		if (strcmp(key, "all") == 0)
917 			keybit = ~0;
918 		break;
919 	case 'c':
920 		if (strcmp(key, "cksum") == 0)
921 			keybit = F_CKSUM;
922 		break;
923 	case 'd':
924 		if (strcmp(key, "device") == 0)
925 			keybit = F_DEV;
926 		else if (strcmp(key, "dironly") == 0) {
927 			mtree->dironly = (value != NULL)? 1: 0;
928 			return (ARCHIVE_OK);
929 		}
930 		break;
931 	case 'f':
932 		if (strcmp(key, "flags") == 0)
933 			keybit = F_FLAGS;
934 		break;
935 	case 'g':
936 		if (strcmp(key, "gid") == 0)
937 			keybit = F_GID;
938 		else if (strcmp(key, "gname") == 0)
939 			keybit = F_GNAME;
940 		break;
941 	case 'i':
942 		if (strcmp(key, "indent") == 0) {
943 			mtree->indent = (value != NULL)? 1: 0;
944 			return (ARCHIVE_OK);
945 		}
946 		break;
947 	case 'l':
948 		if (strcmp(key, "link") == 0)
949 			keybit = F_SLINK;
950 		break;
951 	case 'm':
952 		if (strcmp(key, "md5") == 0 ||
953 		    strcmp(key, "md5digest") == 0)
954 			keybit = F_MD5;
955 		if (strcmp(key, "mode") == 0)
956 			keybit = F_MODE;
957 		break;
958 	case 'n':
959 		if (strcmp(key, "nlink") == 0)
960 			keybit = F_NLINK;
961 		break;
962 	case 'r':
963 		if (strcmp(key, "ripemd160digest") == 0 ||
964 		    strcmp(key, "rmd160") == 0 ||
965 		    strcmp(key, "rmd160digest") == 0)
966 			keybit = F_RMD160;
967 		break;
968 	case 's':
969 		if (strcmp(key, "sha1") == 0 ||
970 		    strcmp(key, "sha1digest") == 0)
971 			keybit = F_SHA1;
972 		if (strcmp(key, "sha256") == 0 ||
973 		    strcmp(key, "sha256digest") == 0)
974 			keybit = F_SHA256;
975 		if (strcmp(key, "sha384") == 0 ||
976 		    strcmp(key, "sha384digest") == 0)
977 			keybit = F_SHA384;
978 		if (strcmp(key, "sha512") == 0 ||
979 		    strcmp(key, "sha512digest") == 0)
980 			keybit = F_SHA512;
981 		if (strcmp(key, "size") == 0)
982 			keybit = F_SIZE;
983 		break;
984 	case 't':
985 		if (strcmp(key, "time") == 0)
986 			keybit = F_TIME;
987 		else if (strcmp(key, "type") == 0)
988 			keybit = F_TYPE;
989 		break;
990 	case 'u':
991 		if (strcmp(key, "uid") == 0)
992 			keybit = F_UID;
993 		else if (strcmp(key, "uname") == 0)
994 			keybit = F_UNAME;
995 		else if (strcmp(key, "use-set") == 0) {
996 			mtree->set.output = (value != NULL)? 1: 0;
997 			return (ARCHIVE_OK);
998 		}
999 		break;
1000 	}
1001 	if (keybit != 0) {
1002 		if (value != NULL)
1003 			mtree->keys |= keybit;
1004 		else
1005 			mtree->keys &= ~keybit;
1006 		return (ARCHIVE_OK);
1007 	}
1008 
1009 	return (ARCHIVE_WARN);
1010 }
1011 
1012 int
1013 archive_write_set_format_mtree(struct archive *_a)
1014 {
1015 	struct archive_write *a = (struct archive_write *)_a;
1016 	struct mtree_writer *mtree;
1017 
1018 	if (a->format_destroy != NULL)
1019 		(a->format_destroy)(a);
1020 
1021 	if ((mtree = malloc(sizeof(*mtree))) == NULL) {
1022 		archive_set_error(&a->archive, ENOMEM,
1023 		    "Can't allocate mtree data");
1024 		return (ARCHIVE_FATAL);
1025 	}
1026 
1027 	mtree->entry = NULL;
1028 	mtree->first = 1;
1029 	memset(&(mtree->set), 0, sizeof(mtree->set));
1030 	archive_string_init(&mtree->set.parent);
1031 	mtree->keys = DEFAULT_KEYS;
1032 	mtree->dironly = 0;
1033 	mtree->indent = 0;
1034 	archive_string_init(&mtree->ebuf);
1035 	archive_string_init(&mtree->buf);
1036 	a->format_data = mtree;
1037 	a->format_destroy = archive_write_mtree_destroy;
1038 
1039 	a->pad_uncompressed = 0;
1040 	a->format_name = "mtree";
1041 	a->format_options = archive_write_mtree_options;
1042 	a->format_write_header = archive_write_mtree_header;
1043 	a->format_finish = archive_write_mtree_finish;
1044 	a->format_write_data = archive_write_mtree_data;
1045 	a->format_finish_entry = archive_write_mtree_finish_entry;
1046 	a->archive.archive_format = ARCHIVE_FORMAT_MTREE;
1047 	a->archive.archive_format_name = "mtree";
1048 
1049 	return (ARCHIVE_OK);
1050 }
1051