archive_write_set_format_mtree.c revision 368708
1/*-
2 * Copyright (c) 2008 Joerg Sonnenberger
3 * Copyright (c) 2009-2012 Michihiro NAKAJIMA
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: stable/10/contrib/libarchive/libarchive/archive_write_set_format_mtree.c 368708 2020-12-16 22:25:40Z mm $");
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_digest_private.h"
39#include "archive_entry.h"
40#include "archive_entry_private.h"
41#include "archive_private.h"
42#include "archive_rb.h"
43#include "archive_string.h"
44#include "archive_write_private.h"
45
46#define INDENTNAMELEN	15
47#define MAXLINELEN	80
48#define SET_KEYS	\
49	(F_FLAGS | F_GID | F_GNAME | F_MODE | F_TYPE | F_UID | F_UNAME)
50
51struct attr_counter {
52	struct attr_counter *prev;
53	struct attr_counter *next;
54	struct mtree_entry *m_entry;
55	int count;
56};
57
58struct att_counter_set {
59	struct attr_counter *uid_list;
60	struct attr_counter *gid_list;
61	struct attr_counter *mode_list;
62	struct attr_counter *flags_list;
63};
64
65struct mtree_chain {
66	struct mtree_entry *first;
67	struct mtree_entry **last;
68};
69
70/*
71 * The Data only for a directory file.
72 */
73struct dir_info {
74	struct archive_rb_tree rbtree;
75	struct mtree_chain children;
76	struct mtree_entry *chnext;
77	int virtual;
78};
79
80/*
81 * The Data only for a regular file.
82 */
83struct reg_info {
84	int compute_sum;
85	uint32_t crc;
86	struct ae_digest digest;
87};
88
89struct mtree_entry {
90	struct archive_rb_node rbnode;
91	struct mtree_entry *next;
92	struct mtree_entry *parent;
93	struct dir_info *dir_info;
94	struct reg_info *reg_info;
95
96	struct archive_string parentdir;
97	struct archive_string basename;
98	struct archive_string pathname;
99	struct archive_string symlink;
100	struct archive_string uname;
101	struct archive_string gname;
102	struct archive_string fflags_text;
103	unsigned int nlink;
104	mode_t filetype;
105	mode_t mode;
106	int64_t size;
107	int64_t uid;
108	int64_t gid;
109	time_t mtime;
110	long mtime_nsec;
111	unsigned long fflags_set;
112	unsigned long fflags_clear;
113	dev_t rdevmajor;
114	dev_t rdevminor;
115	dev_t devmajor;
116	dev_t devminor;
117	int64_t ino;
118};
119
120struct mtree_writer {
121	struct mtree_entry *mtree_entry;
122	struct mtree_entry *root;
123	struct mtree_entry *cur_dirent;
124	struct archive_string cur_dirstr;
125	struct mtree_chain file_list;
126
127	struct archive_string ebuf;
128	struct archive_string buf;
129	int first;
130	uint64_t entry_bytes_remaining;
131
132	/*
133	 * Set global value.
134	 */
135	struct {
136		int		processing;
137		mode_t		type;
138		int		keys;
139		int64_t		uid;
140		int64_t		gid;
141		mode_t		mode;
142		unsigned long	fflags_set;
143		unsigned long	fflags_clear;
144	} set;
145	struct att_counter_set	acs;
146	int classic;
147	int depth;
148
149	/* check sum */
150	int compute_sum;
151	uint32_t crc;
152	uint64_t crc_len;
153#ifdef ARCHIVE_HAS_MD5
154	archive_md5_ctx md5ctx;
155#endif
156#ifdef ARCHIVE_HAS_RMD160
157	archive_rmd160_ctx rmd160ctx;
158#endif
159#ifdef ARCHIVE_HAS_SHA1
160	archive_sha1_ctx sha1ctx;
161#endif
162#ifdef ARCHIVE_HAS_SHA256
163	archive_sha256_ctx sha256ctx;
164#endif
165#ifdef ARCHIVE_HAS_SHA384
166	archive_sha384_ctx sha384ctx;
167#endif
168#ifdef ARCHIVE_HAS_SHA512
169	archive_sha512_ctx sha512ctx;
170#endif
171	/* Keyword options */
172	int keys;
173#define	F_CKSUM		0x00000001		/* checksum */
174#define	F_DEV		0x00000002		/* device type */
175#define	F_DONE		0x00000004		/* directory done */
176#define	F_FLAGS		0x00000008		/* file flags */
177#define	F_GID		0x00000010		/* gid */
178#define	F_GNAME		0x00000020		/* group name */
179#define	F_IGN		0x00000040		/* ignore */
180#define	F_MAGIC		0x00000080		/* name has magic chars */
181#define	F_MD5		0x00000100		/* MD5 digest */
182#define	F_MODE		0x00000200		/* mode */
183#define	F_NLINK		0x00000400		/* number of links */
184#define	F_NOCHANGE 	0x00000800		/* If owner/mode "wrong", do
185						 * not change */
186#define	F_OPT		0x00001000		/* existence optional */
187#define	F_RMD160 	0x00002000		/* RIPEMD160 digest */
188#define	F_SHA1		0x00004000		/* SHA-1 digest */
189#define	F_SIZE		0x00008000		/* size */
190#define	F_SLINK		0x00010000		/* symbolic link */
191#define	F_TAGS		0x00020000		/* tags */
192#define	F_TIME		0x00040000		/* modification time */
193#define	F_TYPE		0x00080000		/* file type */
194#define	F_UID		0x00100000		/* uid */
195#define	F_UNAME		0x00200000		/* user name */
196#define	F_VISIT		0x00400000		/* file visited */
197#define	F_SHA256	0x00800000		/* SHA-256 digest */
198#define	F_SHA384	0x01000000		/* SHA-384 digest */
199#define	F_SHA512	0x02000000		/* SHA-512 digest */
200#define	F_INO		0x04000000		/* inode number */
201#define	F_RESDEV	0x08000000		/* device ID on which the
202						 * entry resides */
203
204	/* Options */
205	int dironly;		/* If it is set, ignore all files except
206				 * directory files, like mtree(8) -d option. */
207	int indent;		/* If it is set, indent output data. */
208	int output_global_set;	/* If it is set, use /set keyword to set
209				 * global values. When generating mtree
210				 * classic format, it is set by default. */
211};
212
213#define DEFAULT_KEYS	(F_DEV | F_FLAGS | F_GID | F_GNAME | F_SLINK | F_MODE\
214			 | F_NLINK | F_SIZE | F_TIME | F_TYPE | F_UID\
215			 | F_UNAME)
216#define attr_counter_set_reset	attr_counter_set_free
217
218static void attr_counter_free(struct attr_counter **);
219static int attr_counter_inc(struct attr_counter **, struct attr_counter *,
220	struct attr_counter *, struct mtree_entry *);
221static struct attr_counter * attr_counter_new(struct mtree_entry *,
222	struct attr_counter *);
223static int attr_counter_set_collect(struct mtree_writer *,
224	struct mtree_entry *);
225static void attr_counter_set_free(struct mtree_writer *);
226static int get_global_set_keys(struct mtree_writer *, struct mtree_entry *);
227static int mtree_entry_add_child_tail(struct mtree_entry *,
228	struct mtree_entry *);
229static int mtree_entry_create_virtual_dir(struct archive_write *, const char *,
230	struct mtree_entry **);
231static int mtree_entry_cmp_node(const struct archive_rb_node *,
232	const struct archive_rb_node *);
233static int mtree_entry_cmp_key(const struct archive_rb_node *, const void *);
234static int mtree_entry_exchange_same_entry(struct archive_write *,
235    struct mtree_entry *, struct mtree_entry *);
236static void mtree_entry_free(struct mtree_entry *);
237static int mtree_entry_new(struct archive_write *, struct archive_entry *,
238	struct mtree_entry **);
239static void mtree_entry_register_free(struct mtree_writer *);
240static void mtree_entry_register_init(struct mtree_writer *);
241static int mtree_entry_setup_filenames(struct archive_write *,
242	struct mtree_entry *, struct archive_entry *);
243static int mtree_entry_tree_add(struct archive_write *, struct mtree_entry **);
244static void sum_init(struct mtree_writer *);
245static void sum_update(struct mtree_writer *, const void *, size_t);
246static void sum_final(struct mtree_writer *, struct reg_info *);
247static void sum_write(struct archive_string *, struct reg_info *);
248static int write_mtree_entry(struct archive_write *, struct mtree_entry *);
249static int write_dot_dot_entry(struct archive_write *, struct mtree_entry *);
250
251#define	COMPUTE_CRC(var, ch)	(var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
252static const uint32_t crctab[] = {
253	0x0,
254	0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
255	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
256	0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
257	0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
258	0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
259	0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
260	0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
261	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
262	0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
263	0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
264	0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
265	0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
266	0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
267	0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
268	0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
269	0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
270	0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
271	0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
272	0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
273	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
274	0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
275	0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
276	0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
277	0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
278	0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
279	0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
280	0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
281	0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
282	0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
283	0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
284	0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
285	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
286	0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
287	0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
288	0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
289	0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
290	0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
291	0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
292	0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
293	0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
294	0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
295	0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
296	0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
297	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
298	0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
299	0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
300	0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
301	0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
302	0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
303	0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
304	0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
305};
306
307static const unsigned char safe_char[256] = {
308	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */
309	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
310	/* !"$%&'()*+,-./  EXCLUSION:0x20( ) 0x23(#) */
311	0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
312	/* 0123456789:;<>?  EXCLUSION:0x3d(=) */
313	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, /* 30 - 3F */
314	/* @ABCDEFGHIJKLMNO */
315	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
316	/* PQRSTUVWXYZ[]^_ EXCLUSION:0x5c(\)  */
317	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, /* 50 - 5F */
318	/* `abcdefghijklmno */
319	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
320	/* pqrstuvwxyz{|}~ */
321	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */
322	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
323	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
324	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
325	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
326	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
327	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
328	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
329	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
330};
331
332static void
333mtree_quote(struct archive_string *s, const char *str)
334{
335	const char *start;
336	char buf[4];
337	unsigned char c;
338
339	for (start = str; *str != '\0'; ++str) {
340		if (safe_char[*(const unsigned char *)str])
341			continue;
342		if (start != str)
343			archive_strncat(s, start, str - start);
344		c = (unsigned char)*str;
345		buf[0] = '\\';
346		buf[1] = (c / 64) + '0';
347		buf[2] = (c / 8 % 8) + '0';
348		buf[3] = (c % 8) + '0';
349		archive_strncat(s, buf, 4);
350		start = str + 1;
351	}
352
353	if (start != str)
354		archive_strncat(s, start, str - start);
355}
356
357/*
358 * Indent a line as the mtree utility does so it is readable for people.
359 */
360static void
361mtree_indent(struct mtree_writer *mtree)
362{
363	int i, fn, nd, pd;
364	const char *r, *s, *x;
365
366	if (mtree->classic) {
367		if (mtree->indent) {
368			nd = 0;
369			pd = mtree->depth * 4;
370		} else {
371			nd = mtree->depth?4:0;
372			pd = 0;
373		}
374	} else
375		nd = pd = 0;
376	fn = 1;
377	s = r = mtree->ebuf.s;
378	x = NULL;
379	while (*r == ' ')
380		r++;
381	while ((r = strchr(r, ' ')) != NULL) {
382		if (fn) {
383			fn = 0;
384			for (i = 0; i < nd + pd; i++)
385				archive_strappend_char(&mtree->buf, ' ');
386			archive_strncat(&mtree->buf, s, r - s);
387			if (nd + (r -s) > INDENTNAMELEN) {
388				archive_strncat(&mtree->buf, " \\\n", 3);
389				for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++)
390					archive_strappend_char(&mtree->buf, ' ');
391			} else {
392				for (i = (int)(r -s + nd);
393				    i < (INDENTNAMELEN + 1); i++)
394					archive_strappend_char(&mtree->buf, ' ');
395			}
396			s = ++r;
397			x = NULL;
398			continue;
399		}
400		if (pd + (r - s) <= MAXLINELEN - 3 - INDENTNAMELEN)
401			x = r++;
402		else {
403			if (x == NULL)
404				x = r;
405			archive_strncat(&mtree->buf, s, x - s);
406			archive_strncat(&mtree->buf, " \\\n", 3);
407			for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++)
408				archive_strappend_char(&mtree->buf, ' ');
409			s = r = ++x;
410			x = NULL;
411		}
412	}
413	if (fn) {
414		for (i = 0; i < nd + pd; i++)
415			archive_strappend_char(&mtree->buf, ' ');
416		archive_strcat(&mtree->buf, s);
417		s += strlen(s);
418	}
419	if (x != NULL && pd + strlen(s) > MAXLINELEN - 3 - INDENTNAMELEN) {
420		/* Last keyword is longer. */
421		archive_strncat(&mtree->buf, s, x - s);
422		archive_strncat(&mtree->buf, " \\\n", 3);
423		for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++)
424			archive_strappend_char(&mtree->buf, ' ');
425		s = ++x;
426	}
427	archive_strcat(&mtree->buf, s);
428	archive_string_empty(&mtree->ebuf);
429}
430
431/*
432 * Write /set keyword.
433 * Set the most used value of uid, gid, mode and fflags, which are
434 * collected by the attr_counter_set_collect() function.
435 */
436static void
437write_global(struct mtree_writer *mtree)
438{
439	struct archive_string setstr;
440	struct archive_string unsetstr;
441	struct att_counter_set *acs;
442	int keys, oldkeys, effkeys;
443
444	archive_string_init(&setstr);
445	archive_string_init(&unsetstr);
446	keys = mtree->keys & SET_KEYS;
447	oldkeys = mtree->set.keys;
448	effkeys = keys;
449	acs = &mtree->acs;
450	if (mtree->set.processing) {
451		/*
452		 * Check if the global data needs updating.
453		 */
454		effkeys &= ~F_TYPE;
455		if (acs->uid_list == NULL)
456			effkeys &= ~(F_UNAME | F_UID);
457		else if (oldkeys & (F_UNAME | F_UID)) {
458			if (acs->uid_list->count < 2 ||
459			    mtree->set.uid == acs->uid_list->m_entry->uid)
460				effkeys &= ~(F_UNAME | F_UID);
461		}
462		if (acs->gid_list == NULL)
463			effkeys &= ~(F_GNAME | F_GID);
464		else if (oldkeys & (F_GNAME | F_GID)) {
465			if (acs->gid_list->count < 2 ||
466			    mtree->set.gid == acs->gid_list->m_entry->gid)
467				effkeys &= ~(F_GNAME | F_GID);
468		}
469		if (acs->mode_list == NULL)
470			effkeys &= ~F_MODE;
471		else if (oldkeys & F_MODE) {
472			if (acs->mode_list->count < 2 ||
473			    mtree->set.mode == acs->mode_list->m_entry->mode)
474				effkeys &= ~F_MODE;
475		}
476		if (acs->flags_list == NULL)
477			effkeys &= ~F_FLAGS;
478		else if ((oldkeys & F_FLAGS) != 0) {
479			if (acs->flags_list->count < 2 ||
480			    (acs->flags_list->m_entry->fflags_set ==
481				mtree->set.fflags_set &&
482			     acs->flags_list->m_entry->fflags_clear ==
483				mtree->set.fflags_clear))
484				effkeys &= ~F_FLAGS;
485		}
486	} else {
487		if (acs->uid_list == NULL)
488			keys &= ~(F_UNAME | F_UID);
489		if (acs->gid_list == NULL)
490			keys &= ~(F_GNAME | F_GID);
491		if (acs->mode_list == NULL)
492			keys &= ~F_MODE;
493		if (acs->flags_list == NULL)
494			keys &= ~F_FLAGS;
495	}
496	if ((keys & effkeys & F_TYPE) != 0) {
497		if (mtree->dironly) {
498			archive_strcat(&setstr, " type=dir");
499			mtree->set.type = AE_IFDIR;
500		} else {
501			archive_strcat(&setstr, " type=file");
502			mtree->set.type = AE_IFREG;
503		}
504	}
505	if ((keys & effkeys & F_UNAME) != 0) {
506		if (archive_strlen(&(acs->uid_list->m_entry->uname)) > 0) {
507			archive_strcat(&setstr, " uname=");
508			mtree_quote(&setstr, acs->uid_list->m_entry->uname.s);
509		} else {
510			keys &= ~F_UNAME;
511			if ((oldkeys & F_UNAME) != 0)
512				archive_strcat(&unsetstr, " uname");
513		}
514	}
515	if ((keys & effkeys & F_UID) != 0) {
516		mtree->set.uid = acs->uid_list->m_entry->uid;
517		archive_string_sprintf(&setstr, " uid=%jd",
518		    (intmax_t)mtree->set.uid);
519	}
520	if ((keys & effkeys & F_GNAME) != 0) {
521		if (archive_strlen(&(acs->gid_list->m_entry->gname)) > 0) {
522			archive_strcat(&setstr, " gname=");
523			mtree_quote(&setstr, acs->gid_list->m_entry->gname.s);
524		} else {
525			keys &= ~F_GNAME;
526			if ((oldkeys & F_GNAME) != 0)
527				archive_strcat(&unsetstr, " gname");
528		}
529	}
530	if ((keys & effkeys & F_GID) != 0) {
531		mtree->set.gid = acs->gid_list->m_entry->gid;
532		archive_string_sprintf(&setstr, " gid=%jd",
533		    (intmax_t)mtree->set.gid);
534	}
535	if ((keys & effkeys & F_MODE) != 0) {
536		mtree->set.mode = acs->mode_list->m_entry->mode;
537		archive_string_sprintf(&setstr, " mode=%o",
538		    (unsigned int)mtree->set.mode);
539	}
540	if ((keys & effkeys & F_FLAGS) != 0) {
541		if (archive_strlen(
542		    &(acs->flags_list->m_entry->fflags_text)) > 0) {
543			archive_strcat(&setstr, " flags=");
544			mtree_quote(&setstr,
545			    acs->flags_list->m_entry->fflags_text.s);
546			mtree->set.fflags_set =
547			    acs->flags_list->m_entry->fflags_set;
548			mtree->set.fflags_clear =
549			    acs->flags_list->m_entry->fflags_clear;
550		} else {
551			keys &= ~F_FLAGS;
552			if ((oldkeys & F_FLAGS) != 0)
553				archive_strcat(&unsetstr, " flags");
554		}
555	}
556	if (unsetstr.length > 0)
557		archive_string_sprintf(&mtree->buf, "/unset%s\n", unsetstr.s);
558	archive_string_free(&unsetstr);
559	if (setstr.length > 0)
560		archive_string_sprintf(&mtree->buf, "/set%s\n", setstr.s);
561	archive_string_free(&setstr);
562	mtree->set.keys = keys;
563	mtree->set.processing = 1;
564}
565
566static struct attr_counter *
567attr_counter_new(struct mtree_entry *me, struct attr_counter *prev)
568{
569	struct attr_counter *ac;
570
571	ac = malloc(sizeof(*ac));
572	if (ac != NULL) {
573		ac->prev = prev;
574		ac->next = NULL;
575		ac->count = 1;
576		ac->m_entry = me;
577	}
578	return (ac);
579}
580
581static void
582attr_counter_free(struct attr_counter **top)
583{
584	struct attr_counter *ac, *tac;
585
586	if (*top == NULL)
587		return;
588	ac = *top;
589        while (ac != NULL) {
590		tac = ac->next;
591		free(ac);
592		ac = tac;
593	}
594	*top = NULL;
595}
596
597static int
598attr_counter_inc(struct attr_counter **top, struct attr_counter *ac,
599    struct attr_counter *last, struct mtree_entry *me)
600{
601	struct attr_counter *pac;
602
603	if (ac != NULL) {
604		ac->count++;
605		if (*top == ac || ac->prev->count >= ac->count)
606			return (0);
607		for (pac = ac->prev; pac; pac = pac->prev) {
608			if (pac->count >= ac->count)
609				break;
610		}
611		ac->prev->next = ac->next;
612		if (ac->next != NULL)
613			ac->next->prev = ac->prev;
614		if (pac != NULL) {
615			ac->prev = pac;
616			ac->next = pac->next;
617			pac->next = ac;
618			if (ac->next != NULL)
619				ac->next->prev = ac;
620		} else {
621			ac->prev = NULL;
622			ac->next = *top;
623			*top = ac;
624			ac->next->prev = ac;
625		}
626	} else if (last != NULL) {
627		ac = attr_counter_new(me, last);
628		if (ac == NULL)
629			return (-1);
630		last->next = ac;
631	}
632	return (0);
633}
634
635/*
636 * Tabulate uid, gid, mode and fflags of a entry in order to be used for /set.
637 */
638static int
639attr_counter_set_collect(struct mtree_writer *mtree, struct mtree_entry *me)
640{
641	struct attr_counter *ac, *last;
642	struct att_counter_set *acs = &mtree->acs;
643	int keys = mtree->keys;
644
645	if (keys & (F_UNAME | F_UID)) {
646		if (acs->uid_list == NULL) {
647			acs->uid_list = attr_counter_new(me, NULL);
648			if (acs->uid_list == NULL)
649				return (-1);
650		} else {
651			last = NULL;
652			for (ac = acs->uid_list; ac; ac = ac->next) {
653				if (ac->m_entry->uid == me->uid)
654					break;
655				last = ac;
656			}
657			if (attr_counter_inc(&acs->uid_list, ac, last, me) < 0)
658				return (-1);
659		}
660	}
661	if (keys & (F_GNAME | F_GID)) {
662		if (acs->gid_list == NULL) {
663			acs->gid_list = attr_counter_new(me, NULL);
664			if (acs->gid_list == NULL)
665				return (-1);
666		} else {
667			last = NULL;
668			for (ac = acs->gid_list; ac; ac = ac->next) {
669				if (ac->m_entry->gid == me->gid)
670					break;
671				last = ac;
672			}
673			if (attr_counter_inc(&acs->gid_list, ac, last, me) < 0)
674				return (-1);
675		}
676	}
677	if (keys & F_MODE) {
678		if (acs->mode_list == NULL) {
679			acs->mode_list = attr_counter_new(me, NULL);
680			if (acs->mode_list == NULL)
681				return (-1);
682		} else {
683			last = NULL;
684			for (ac = acs->mode_list; ac; ac = ac->next) {
685				if (ac->m_entry->mode == me->mode)
686					break;
687				last = ac;
688			}
689			if (attr_counter_inc(&acs->mode_list, ac, last, me) < 0)
690				return (-1);
691		}
692	}
693	if (keys & F_FLAGS) {
694		if (acs->flags_list == NULL) {
695			acs->flags_list = attr_counter_new(me, NULL);
696			if (acs->flags_list == NULL)
697				return (-1);
698		} else {
699			last = NULL;
700			for (ac = acs->flags_list; ac; ac = ac->next) {
701				if (ac->m_entry->fflags_set == me->fflags_set &&
702				    ac->m_entry->fflags_clear ==
703							me->fflags_clear)
704					break;
705				last = ac;
706			}
707			if (attr_counter_inc(&acs->flags_list, ac, last, me) < 0)
708				return (-1);
709		}
710	}
711
712	return (0);
713}
714
715static void
716attr_counter_set_free(struct mtree_writer *mtree)
717{
718	struct att_counter_set *acs = &mtree->acs;
719
720	attr_counter_free(&acs->uid_list);
721	attr_counter_free(&acs->gid_list);
722	attr_counter_free(&acs->mode_list);
723	attr_counter_free(&acs->flags_list);
724}
725
726static int
727get_global_set_keys(struct mtree_writer *mtree, struct mtree_entry *me)
728{
729	int keys;
730
731	keys = mtree->keys;
732
733	/*
734	 * If a keyword has been set by /set, we do not need to
735	 * output it.
736	 */
737	if (mtree->set.keys == 0)
738		return (keys);/* /set is not used. */
739
740	if ((mtree->set.keys & (F_GNAME | F_GID)) != 0 &&
741	     mtree->set.gid == me->gid)
742		keys &= ~(F_GNAME | F_GID);
743	if ((mtree->set.keys & (F_UNAME | F_UID)) != 0 &&
744	     mtree->set.uid == me->uid)
745		keys &= ~(F_UNAME | F_UID);
746	if (mtree->set.keys & F_FLAGS) {
747		if (mtree->set.fflags_set == me->fflags_set &&
748		    mtree->set.fflags_clear == me->fflags_clear)
749			keys &= ~F_FLAGS;
750	}
751	if ((mtree->set.keys & F_MODE) != 0 && mtree->set.mode == me->mode)
752		keys &= ~F_MODE;
753
754	switch (me->filetype) {
755	case AE_IFLNK: case AE_IFSOCK: case AE_IFCHR:
756	case AE_IFBLK: case AE_IFIFO:
757		break;
758	case AE_IFDIR:
759		if ((mtree->set.keys & F_TYPE) != 0 &&
760		    mtree->set.type == AE_IFDIR)
761			keys &= ~F_TYPE;
762		break;
763	case AE_IFREG:
764	default:	/* Handle unknown file types as regular files. */
765		if ((mtree->set.keys & F_TYPE) != 0 &&
766		    mtree->set.type == AE_IFREG)
767			keys &= ~F_TYPE;
768		break;
769	}
770
771	return (keys);
772}
773
774static int
775mtree_entry_new(struct archive_write *a, struct archive_entry *entry,
776    struct mtree_entry **m_entry)
777{
778	struct mtree_entry *me;
779	const char *s;
780	int r;
781	static const struct archive_rb_tree_ops rb_ops = {
782		mtree_entry_cmp_node, mtree_entry_cmp_key
783	};
784
785	me = calloc(1, sizeof(*me));
786	if (me == NULL) {
787		archive_set_error(&a->archive, ENOMEM,
788		    "Can't allocate memory for a mtree entry");
789		*m_entry = NULL;
790		return (ARCHIVE_FATAL);
791	}
792
793	r = mtree_entry_setup_filenames(a, me, entry);
794	if (r < ARCHIVE_WARN) {
795		mtree_entry_free(me);
796		*m_entry = NULL;
797		return (r);
798	}
799
800	if ((s = archive_entry_symlink(entry)) != NULL)
801		archive_strcpy(&me->symlink, s);
802	me->nlink = archive_entry_nlink(entry);
803	me->filetype = archive_entry_filetype(entry);
804	me->mode = archive_entry_mode(entry) & 07777;
805	me->uid = archive_entry_uid(entry);
806	me->gid = archive_entry_gid(entry);
807	if ((s = archive_entry_uname(entry)) != NULL)
808		archive_strcpy(&me->uname, s);
809	if ((s = archive_entry_gname(entry)) != NULL)
810		archive_strcpy(&me->gname, s);
811	if ((s = archive_entry_fflags_text(entry)) != NULL)
812		archive_strcpy(&me->fflags_text, s);
813	archive_entry_fflags(entry, &me->fflags_set, &me->fflags_clear);
814	me->mtime = archive_entry_mtime(entry);
815	me->mtime_nsec = archive_entry_mtime_nsec(entry);
816	me->rdevmajor = archive_entry_rdevmajor(entry);
817	me->rdevminor = archive_entry_rdevminor(entry);
818	me->devmajor = archive_entry_devmajor(entry);
819	me->devminor = archive_entry_devminor(entry);
820	me->ino = archive_entry_ino(entry);
821	me->size = archive_entry_size(entry);
822	if (me->filetype == AE_IFDIR) {
823		me->dir_info = calloc(1, sizeof(*me->dir_info));
824		if (me->dir_info == NULL) {
825			mtree_entry_free(me);
826			archive_set_error(&a->archive, ENOMEM,
827			    "Can't allocate memory for a mtree entry");
828			*m_entry = NULL;
829			return (ARCHIVE_FATAL);
830		}
831		__archive_rb_tree_init(&me->dir_info->rbtree, &rb_ops);
832		me->dir_info->children.first = NULL;
833		me->dir_info->children.last = &(me->dir_info->children.first);
834		me->dir_info->chnext = NULL;
835	} else if (me->filetype == AE_IFREG) {
836		me->reg_info = calloc(1, sizeof(*me->reg_info));
837		if (me->reg_info == NULL) {
838			mtree_entry_free(me);
839			archive_set_error(&a->archive, ENOMEM,
840			    "Can't allocate memory for a mtree entry");
841			*m_entry = NULL;
842			return (ARCHIVE_FATAL);
843		}
844		me->reg_info->compute_sum = 0;
845	}
846
847	*m_entry = me;
848	return (ARCHIVE_OK);
849}
850
851static void
852mtree_entry_free(struct mtree_entry *me)
853{
854	archive_string_free(&me->parentdir);
855	archive_string_free(&me->basename);
856	archive_string_free(&me->pathname);
857	archive_string_free(&me->symlink);
858	archive_string_free(&me->uname);
859	archive_string_free(&me->gname);
860	archive_string_free(&me->fflags_text);
861	free(me->dir_info);
862	free(me->reg_info);
863	free(me);
864}
865
866static int
867archive_write_mtree_header(struct archive_write *a,
868    struct archive_entry *entry)
869{
870	struct mtree_writer *mtree= a->format_data;
871	struct mtree_entry *mtree_entry;
872	int r, r2;
873
874	if (mtree->first) {
875		mtree->first = 0;
876		archive_strcat(&mtree->buf, "#mtree\n");
877		if ((mtree->keys & SET_KEYS) == 0)
878			mtree->output_global_set = 0;/* Disabled. */
879	}
880
881	mtree->entry_bytes_remaining = archive_entry_size(entry);
882
883	/* While directory only mode, we do not handle non directory files. */
884	if (mtree->dironly && archive_entry_filetype(entry) != AE_IFDIR)
885		return (ARCHIVE_OK);
886
887	r2 = mtree_entry_new(a, entry, &mtree_entry);
888	if (r2 < ARCHIVE_WARN)
889		return (r2);
890	r = mtree_entry_tree_add(a, &mtree_entry);
891	if (r < ARCHIVE_WARN) {
892		mtree_entry_free(mtree_entry);
893		return (r);
894	}
895	mtree->mtree_entry = mtree_entry;
896
897	/* If the current file is a regular file, we have to
898	 * compute the sum of its content.
899	 * Initialize a bunch of checksum context. */
900	if (mtree_entry->reg_info)
901		sum_init(mtree);
902
903	return (r2);
904}
905
906static int
907write_mtree_entry(struct archive_write *a, struct mtree_entry *me)
908{
909	struct mtree_writer *mtree = a->format_data;
910	struct archive_string *str;
911	int keys, ret;
912
913	if (me->dir_info) {
914		if (mtree->classic) {
915			/*
916			 * Output a comment line to describe the full
917			 * pathname of the entry as mtree utility does
918			 * while generating classic format.
919			 */
920			if (!mtree->dironly)
921				archive_strappend_char(&mtree->buf, '\n');
922			if (me->parentdir.s)
923				archive_string_sprintf(&mtree->buf,
924				    "# %s/%s\n",
925				    me->parentdir.s, me->basename.s);
926			else
927				archive_string_sprintf(&mtree->buf,
928				    "# %s\n",
929				    me->basename.s);
930		}
931		if (mtree->output_global_set)
932			write_global(mtree);
933	}
934	archive_string_empty(&mtree->ebuf);
935	str = (mtree->indent || mtree->classic)? &mtree->ebuf : &mtree->buf;
936
937	if (!mtree->classic && me->parentdir.s) {
938		/*
939		 * If generating format is not classic one(v1), output
940		 * a full pathname.
941		 */
942		mtree_quote(str, me->parentdir.s);
943		archive_strappend_char(str, '/');
944	}
945	mtree_quote(str, me->basename.s);
946
947	keys = get_global_set_keys(mtree, me);
948	if ((keys & F_NLINK) != 0 &&
949	    me->nlink != 1 && me->filetype != AE_IFDIR)
950		archive_string_sprintf(str, " nlink=%u", me->nlink);
951
952	if ((keys & F_GNAME) != 0 && archive_strlen(&me->gname) > 0) {
953		archive_strcat(str, " gname=");
954		mtree_quote(str, me->gname.s);
955	}
956	if ((keys & F_UNAME) != 0 && archive_strlen(&me->uname) > 0) {
957		archive_strcat(str, " uname=");
958		mtree_quote(str, me->uname.s);
959	}
960	if ((keys & F_FLAGS) != 0) {
961		if (archive_strlen(&me->fflags_text) > 0) {
962			archive_strcat(str, " flags=");
963			mtree_quote(str, me->fflags_text.s);
964		} else if (mtree->set.processing &&
965		    (mtree->set.keys & F_FLAGS) != 0)
966			/* Overwrite the global parameter. */
967			archive_strcat(str, " flags=none");
968	}
969	if ((keys & F_TIME) != 0)
970		archive_string_sprintf(str, " time=%jd.%jd",
971		    (intmax_t)me->mtime, (intmax_t)me->mtime_nsec);
972	if ((keys & F_MODE) != 0)
973		archive_string_sprintf(str, " mode=%o", (unsigned int)me->mode);
974	if ((keys & F_GID) != 0)
975		archive_string_sprintf(str, " gid=%jd", (intmax_t)me->gid);
976	if ((keys & F_UID) != 0)
977		archive_string_sprintf(str, " uid=%jd", (intmax_t)me->uid);
978
979	if ((keys & F_INO) != 0)
980		archive_string_sprintf(str, " inode=%jd", (intmax_t)me->ino);
981	if ((keys & F_RESDEV) != 0) {
982		archive_string_sprintf(str,
983		    " resdevice=native,%ju,%ju",
984		    (uintmax_t)me->devmajor,
985		    (uintmax_t)me->devminor);
986	}
987
988	switch (me->filetype) {
989	case AE_IFLNK:
990		if ((keys & F_TYPE) != 0)
991			archive_strcat(str, " type=link");
992		if ((keys & F_SLINK) != 0) {
993			archive_strcat(str, " link=");
994			mtree_quote(str, me->symlink.s);
995		}
996		break;
997	case AE_IFSOCK:
998		if ((keys & F_TYPE) != 0)
999			archive_strcat(str, " type=socket");
1000		break;
1001	case AE_IFCHR:
1002		if ((keys & F_TYPE) != 0)
1003			archive_strcat(str, " type=char");
1004		if ((keys & F_DEV) != 0) {
1005			archive_string_sprintf(str,
1006			    " device=native,%ju,%ju",
1007			    (uintmax_t)me->rdevmajor,
1008			    (uintmax_t)me->rdevminor);
1009		}
1010		break;
1011	case AE_IFBLK:
1012		if ((keys & F_TYPE) != 0)
1013			archive_strcat(str, " type=block");
1014		if ((keys & F_DEV) != 0) {
1015			archive_string_sprintf(str,
1016			    " device=native,%ju,%ju",
1017			    (uintmax_t)me->rdevmajor,
1018			    (uintmax_t)me->rdevminor);
1019		}
1020		break;
1021	case AE_IFDIR:
1022		if ((keys & F_TYPE) != 0)
1023			archive_strcat(str, " type=dir");
1024		break;
1025	case AE_IFIFO:
1026		if ((keys & F_TYPE) != 0)
1027			archive_strcat(str, " type=fifo");
1028		break;
1029	case AE_IFREG:
1030	default:	/* Handle unknown file types as regular files. */
1031		if ((keys & F_TYPE) != 0)
1032			archive_strcat(str, " type=file");
1033		if ((keys & F_SIZE) != 0)
1034			archive_string_sprintf(str, " size=%jd",
1035			    (intmax_t)me->size);
1036		break;
1037	}
1038
1039	/* Write a bunch of sum. */
1040	if (me->reg_info)
1041		sum_write(str, me->reg_info);
1042
1043	archive_strappend_char(str, '\n');
1044	if (mtree->indent || mtree->classic)
1045		mtree_indent(mtree);
1046
1047	if (mtree->buf.length > 32768) {
1048		ret = __archive_write_output(
1049			a, mtree->buf.s, mtree->buf.length);
1050		archive_string_empty(&mtree->buf);
1051	} else
1052		ret = ARCHIVE_OK;
1053	return (ret);
1054}
1055
1056static int
1057write_dot_dot_entry(struct archive_write *a, struct mtree_entry *n)
1058{
1059	struct mtree_writer *mtree = a->format_data;
1060	int ret;
1061
1062	if (n->parentdir.s) {
1063		if (mtree->indent) {
1064			int i, pd = mtree->depth * 4;
1065			for (i = 0; i < pd; i++)
1066				archive_strappend_char(&mtree->buf, ' ');
1067		}
1068		archive_string_sprintf(&mtree->buf, "# %s/%s\n",
1069			n->parentdir.s, n->basename.s);
1070	}
1071
1072	if (mtree->indent) {
1073		archive_string_empty(&mtree->ebuf);
1074		archive_strncat(&mtree->ebuf, "..\n\n", (mtree->dironly)?3:4);
1075		mtree_indent(mtree);
1076	} else
1077		archive_strncat(&mtree->buf, "..\n\n", (mtree->dironly)?3:4);
1078
1079	if (mtree->buf.length > 32768) {
1080		ret = __archive_write_output(
1081			a, mtree->buf.s, mtree->buf.length);
1082		archive_string_empty(&mtree->buf);
1083	} else
1084		ret = ARCHIVE_OK;
1085	return (ret);
1086}
1087
1088/*
1089 * Write mtree entries saved at attr_counter_set_collect() function.
1090 */
1091static int
1092write_mtree_entry_tree(struct archive_write *a)
1093{
1094	struct mtree_writer *mtree = a->format_data;
1095	struct mtree_entry *np = mtree->root;
1096	struct archive_rb_node *n;
1097	int ret;
1098
1099	do {
1100		if (mtree->output_global_set) {
1101			/*
1102			 * Collect attribute information to know which value
1103			 * is frequently used among the children.
1104			 */
1105			attr_counter_set_reset(mtree);
1106			ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) {
1107				struct mtree_entry *e = (struct mtree_entry *)n;
1108				if (attr_counter_set_collect(mtree, e) < 0) {
1109					archive_set_error(&a->archive, ENOMEM,
1110					    "Can't allocate memory");
1111					return (ARCHIVE_FATAL);
1112				}
1113			}
1114		}
1115		if (!np->dir_info->virtual || mtree->classic) {
1116			ret = write_mtree_entry(a, np);
1117			if (ret != ARCHIVE_OK)
1118				return (ARCHIVE_FATAL);
1119		} else {
1120			/* Whenever output_global_set is enabled
1121			 * output global value(/set keywords)
1122			 * even if the directory entry is not allowed
1123			 * to be written because the global values
1124			 * can be used for the children. */
1125			if (mtree->output_global_set)
1126				write_global(mtree);
1127		}
1128		/*
1129		 * Output the attribute of all files except directory files.
1130		 */
1131		mtree->depth++;
1132		ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) {
1133			struct mtree_entry *e = (struct mtree_entry *)n;
1134
1135			if (e->dir_info)
1136				mtree_entry_add_child_tail(np, e);
1137			else {
1138				ret = write_mtree_entry(a, e);
1139				if (ret != ARCHIVE_OK)
1140					return (ARCHIVE_FATAL);
1141			}
1142		}
1143		mtree->depth--;
1144
1145		if (np->dir_info->children.first != NULL) {
1146			/*
1147			 * Descend the tree.
1148			 */
1149			np = np->dir_info->children.first;
1150			if (mtree->indent)
1151				mtree->depth++;
1152			continue;
1153		} else if (mtree->classic) {
1154			/*
1155			 * While printing mtree classic, if there are not
1156			 * any directory files(except "." and "..") in the
1157			 * directory, output two dots ".." as returning
1158			 * the parent directory.
1159			 */
1160			ret = write_dot_dot_entry(a, np);
1161			if (ret != ARCHIVE_OK)
1162				return (ARCHIVE_FATAL);
1163		}
1164
1165		while (np != np->parent) {
1166			if (np->dir_info->chnext == NULL) {
1167				/*
1168				 * Ascend the tree; go back to the parent.
1169				 */
1170				if (mtree->indent)
1171					mtree->depth--;
1172				if (mtree->classic) {
1173					ret = write_dot_dot_entry(a,
1174						np->parent);
1175					if (ret != ARCHIVE_OK)
1176						return (ARCHIVE_FATAL);
1177				}
1178				np = np->parent;
1179			} else {
1180				/*
1181				 * Switch to next mtree entry in the directory.
1182				 */
1183				np = np->dir_info->chnext;
1184				break;
1185			}
1186		}
1187	} while (np != np->parent);
1188
1189	return (ARCHIVE_OK);
1190}
1191
1192static int
1193archive_write_mtree_finish_entry(struct archive_write *a)
1194{
1195	struct mtree_writer *mtree = a->format_data;
1196	struct mtree_entry *me;
1197
1198	if ((me = mtree->mtree_entry) == NULL)
1199		return (ARCHIVE_OK);
1200	mtree->mtree_entry = NULL;
1201
1202	if (me->reg_info)
1203		sum_final(mtree, me->reg_info);
1204
1205	return (ARCHIVE_OK);
1206}
1207
1208static int
1209archive_write_mtree_close(struct archive_write *a)
1210{
1211	struct mtree_writer *mtree= a->format_data;
1212	int ret;
1213
1214	if (mtree->root != NULL) {
1215		ret = write_mtree_entry_tree(a);
1216		if (ret != ARCHIVE_OK)
1217			return (ARCHIVE_FATAL);
1218	}
1219
1220	archive_write_set_bytes_in_last_block(&a->archive, 1);
1221
1222	return __archive_write_output(a, mtree->buf.s, mtree->buf.length);
1223}
1224
1225static ssize_t
1226archive_write_mtree_data(struct archive_write *a, const void *buff, size_t n)
1227{
1228	struct mtree_writer *mtree= a->format_data;
1229
1230	if (n > mtree->entry_bytes_remaining)
1231		n = (size_t)mtree->entry_bytes_remaining;
1232	mtree->entry_bytes_remaining -= n;
1233
1234	/* We don't need to compute a regular file sum */
1235	if (mtree->mtree_entry == NULL)
1236		return (n);
1237
1238	if (mtree->mtree_entry->filetype == AE_IFREG)
1239		sum_update(mtree, buff, n);
1240
1241	return (n);
1242}
1243
1244static int
1245archive_write_mtree_free(struct archive_write *a)
1246{
1247	struct mtree_writer *mtree= a->format_data;
1248
1249	if (mtree == NULL)
1250		return (ARCHIVE_OK);
1251
1252	/* Make sure we do not leave any entries. */
1253	mtree_entry_register_free(mtree);
1254	archive_string_free(&mtree->cur_dirstr);
1255	archive_string_free(&mtree->ebuf);
1256	archive_string_free(&mtree->buf);
1257	attr_counter_set_free(mtree);
1258	free(mtree);
1259	a->format_data = NULL;
1260	return (ARCHIVE_OK);
1261}
1262
1263static int
1264archive_write_mtree_options(struct archive_write *a, const char *key,
1265    const char *value)
1266{
1267	struct mtree_writer *mtree= a->format_data;
1268	int keybit = 0;
1269
1270	switch (key[0]) {
1271	case 'a':
1272		if (strcmp(key, "all") == 0)
1273			keybit = ~0;
1274		break;
1275	case 'c':
1276		if (strcmp(key, "cksum") == 0)
1277			keybit = F_CKSUM;
1278		break;
1279	case 'd':
1280		if (strcmp(key, "device") == 0)
1281			keybit = F_DEV;
1282		else if (strcmp(key, "dironly") == 0) {
1283			mtree->dironly = (value != NULL)? 1: 0;
1284			return (ARCHIVE_OK);
1285		}
1286		break;
1287	case 'f':
1288		if (strcmp(key, "flags") == 0)
1289			keybit = F_FLAGS;
1290		break;
1291	case 'g':
1292		if (strcmp(key, "gid") == 0)
1293			keybit = F_GID;
1294		else if (strcmp(key, "gname") == 0)
1295			keybit = F_GNAME;
1296		break;
1297	case 'i':
1298		if (strcmp(key, "indent") == 0) {
1299			mtree->indent = (value != NULL)? 1: 0;
1300			return (ARCHIVE_OK);
1301		} else if (strcmp(key, "inode") == 0) {
1302			keybit = F_INO;
1303		}
1304		break;
1305	case 'l':
1306		if (strcmp(key, "link") == 0)
1307			keybit = F_SLINK;
1308		break;
1309	case 'm':
1310		if (strcmp(key, "md5") == 0 ||
1311		    strcmp(key, "md5digest") == 0)
1312			keybit = F_MD5;
1313		if (strcmp(key, "mode") == 0)
1314			keybit = F_MODE;
1315		break;
1316	case 'n':
1317		if (strcmp(key, "nlink") == 0)
1318			keybit = F_NLINK;
1319		break;
1320	case 'r':
1321		if (strcmp(key, "resdevice") == 0) {
1322			keybit = F_RESDEV;
1323		} else if (strcmp(key, "ripemd160digest") == 0 ||
1324		    strcmp(key, "rmd160") == 0 ||
1325		    strcmp(key, "rmd160digest") == 0)
1326			keybit = F_RMD160;
1327		break;
1328	case 's':
1329		if (strcmp(key, "sha1") == 0 ||
1330		    strcmp(key, "sha1digest") == 0)
1331			keybit = F_SHA1;
1332		if (strcmp(key, "sha256") == 0 ||
1333		    strcmp(key, "sha256digest") == 0)
1334			keybit = F_SHA256;
1335		if (strcmp(key, "sha384") == 0 ||
1336		    strcmp(key, "sha384digest") == 0)
1337			keybit = F_SHA384;
1338		if (strcmp(key, "sha512") == 0 ||
1339		    strcmp(key, "sha512digest") == 0)
1340			keybit = F_SHA512;
1341		if (strcmp(key, "size") == 0)
1342			keybit = F_SIZE;
1343		break;
1344	case 't':
1345		if (strcmp(key, "time") == 0)
1346			keybit = F_TIME;
1347		else if (strcmp(key, "type") == 0)
1348			keybit = F_TYPE;
1349		break;
1350	case 'u':
1351		if (strcmp(key, "uid") == 0)
1352			keybit = F_UID;
1353		else if (strcmp(key, "uname") == 0)
1354			keybit = F_UNAME;
1355		else if (strcmp(key, "use-set") == 0) {
1356			mtree->output_global_set = (value != NULL)? 1: 0;
1357			return (ARCHIVE_OK);
1358		}
1359		break;
1360	}
1361	if (keybit != 0) {
1362		if (value != NULL)
1363			mtree->keys |= keybit;
1364		else
1365			mtree->keys &= ~keybit;
1366		return (ARCHIVE_OK);
1367	}
1368
1369	/* Note: The "warn" return is just to inform the options
1370	 * supervisor that we didn't handle it.  It will generate
1371	 * a suitable error if no one used this option. */
1372	return (ARCHIVE_WARN);
1373}
1374
1375static int
1376archive_write_set_format_mtree_default(struct archive *_a, const char *fn)
1377{
1378	struct archive_write *a = (struct archive_write *)_a;
1379	struct mtree_writer *mtree;
1380
1381	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, fn);
1382
1383	if (a->format_free != NULL)
1384		(a->format_free)(a);
1385
1386	if ((mtree = calloc(1, sizeof(*mtree))) == NULL) {
1387		archive_set_error(&a->archive, ENOMEM,
1388		    "Can't allocate mtree data");
1389		return (ARCHIVE_FATAL);
1390	}
1391
1392	mtree->mtree_entry = NULL;
1393	mtree->first = 1;
1394	memset(&(mtree->set), 0, sizeof(mtree->set));
1395	mtree->keys = DEFAULT_KEYS;
1396	mtree->dironly = 0;
1397	mtree->indent = 0;
1398	archive_string_init(&mtree->ebuf);
1399	archive_string_init(&mtree->buf);
1400	mtree_entry_register_init(mtree);
1401	a->format_data = mtree;
1402	a->format_free = archive_write_mtree_free;
1403	a->format_name = "mtree";
1404	a->format_options = archive_write_mtree_options;
1405	a->format_write_header = archive_write_mtree_header;
1406	a->format_close = archive_write_mtree_close;
1407	a->format_write_data = archive_write_mtree_data;
1408	a->format_finish_entry = archive_write_mtree_finish_entry;
1409	a->archive.archive_format = ARCHIVE_FORMAT_MTREE;
1410	a->archive.archive_format_name = "mtree";
1411
1412	return (ARCHIVE_OK);
1413}
1414
1415int
1416archive_write_set_format_mtree(struct archive *_a)
1417{
1418	return archive_write_set_format_mtree_default(_a,
1419		"archive_write_set_format_mtree");
1420}
1421
1422int
1423archive_write_set_format_mtree_classic(struct archive *_a)
1424{
1425	int r;
1426
1427	r = archive_write_set_format_mtree_default(_a,
1428		"archive_write_set_format_mtree_classic");
1429	if (r == ARCHIVE_OK) {
1430		struct archive_write *a = (struct archive_write *)_a;
1431		struct mtree_writer *mtree;
1432
1433		mtree = (struct mtree_writer *)a->format_data;
1434
1435		/* Set to output a mtree archive in classic format. */
1436		mtree->classic = 1;
1437		/* Basically, mtree classic format uses '/set' global
1438		 * value. */
1439		mtree->output_global_set = 1;
1440	}
1441	return (r);
1442}
1443
1444static void
1445sum_init(struct mtree_writer *mtree)
1446{
1447
1448	mtree->compute_sum = 0;
1449
1450	if (mtree->keys & F_CKSUM) {
1451		mtree->compute_sum |= F_CKSUM;
1452		mtree->crc = 0;
1453		mtree->crc_len = 0;
1454	}
1455#ifdef ARCHIVE_HAS_MD5
1456	if (mtree->keys & F_MD5) {
1457		if (archive_md5_init(&mtree->md5ctx) == ARCHIVE_OK)
1458			mtree->compute_sum |= F_MD5;
1459		else
1460			mtree->keys &= ~F_MD5;/* Not supported. */
1461	}
1462#endif
1463#ifdef ARCHIVE_HAS_RMD160
1464	if (mtree->keys & F_RMD160) {
1465		if (archive_rmd160_init(&mtree->rmd160ctx) == ARCHIVE_OK)
1466			mtree->compute_sum |= F_RMD160;
1467		else
1468			mtree->keys &= ~F_RMD160;/* Not supported. */
1469	}
1470#endif
1471#ifdef ARCHIVE_HAS_SHA1
1472	if (mtree->keys & F_SHA1) {
1473		if (archive_sha1_init(&mtree->sha1ctx) == ARCHIVE_OK)
1474			mtree->compute_sum |= F_SHA1;
1475		else
1476			mtree->keys &= ~F_SHA1;/* Not supported. */
1477	}
1478#endif
1479#ifdef ARCHIVE_HAS_SHA256
1480	if (mtree->keys & F_SHA256) {
1481		if (archive_sha256_init(&mtree->sha256ctx) == ARCHIVE_OK)
1482			mtree->compute_sum |= F_SHA256;
1483		else
1484			mtree->keys &= ~F_SHA256;/* Not supported. */
1485	}
1486#endif
1487#ifdef ARCHIVE_HAS_SHA384
1488	if (mtree->keys & F_SHA384) {
1489		if (archive_sha384_init(&mtree->sha384ctx) == ARCHIVE_OK)
1490			mtree->compute_sum |= F_SHA384;
1491		else
1492			mtree->keys &= ~F_SHA384;/* Not supported. */
1493	}
1494#endif
1495#ifdef ARCHIVE_HAS_SHA512
1496	if (mtree->keys & F_SHA512) {
1497		if (archive_sha512_init(&mtree->sha512ctx) == ARCHIVE_OK)
1498			mtree->compute_sum |= F_SHA512;
1499		else
1500			mtree->keys &= ~F_SHA512;/* Not supported. */
1501	}
1502#endif
1503}
1504
1505static void
1506sum_update(struct mtree_writer *mtree, const void *buff, size_t n)
1507{
1508	if (mtree->compute_sum & F_CKSUM) {
1509		/*
1510		 * Compute a POSIX 1003.2 checksum
1511		 */
1512		const unsigned char *p;
1513		size_t nn;
1514
1515		for (nn = n, p = buff; nn--; ++p)
1516			COMPUTE_CRC(mtree->crc, *p);
1517		mtree->crc_len += n;
1518	}
1519#ifdef ARCHIVE_HAS_MD5
1520	if (mtree->compute_sum & F_MD5)
1521		archive_md5_update(&mtree->md5ctx, buff, n);
1522#endif
1523#ifdef ARCHIVE_HAS_RMD160
1524	if (mtree->compute_sum & F_RMD160)
1525		archive_rmd160_update(&mtree->rmd160ctx, buff, n);
1526#endif
1527#ifdef ARCHIVE_HAS_SHA1
1528	if (mtree->compute_sum & F_SHA1)
1529		archive_sha1_update(&mtree->sha1ctx, buff, n);
1530#endif
1531#ifdef ARCHIVE_HAS_SHA256
1532	if (mtree->compute_sum & F_SHA256)
1533		archive_sha256_update(&mtree->sha256ctx, buff, n);
1534#endif
1535#ifdef ARCHIVE_HAS_SHA384
1536	if (mtree->compute_sum & F_SHA384)
1537		archive_sha384_update(&mtree->sha384ctx, buff, n);
1538#endif
1539#ifdef ARCHIVE_HAS_SHA512
1540	if (mtree->compute_sum & F_SHA512)
1541		archive_sha512_update(&mtree->sha512ctx, buff, n);
1542#endif
1543}
1544
1545static void
1546sum_final(struct mtree_writer *mtree, struct reg_info *reg)
1547{
1548
1549	if (mtree->compute_sum & F_CKSUM) {
1550		uint64_t len;
1551		/* Include the length of the file. */
1552		for (len = mtree->crc_len; len != 0; len >>= 8)
1553			COMPUTE_CRC(mtree->crc, len & 0xff);
1554		reg->crc = ~mtree->crc;
1555	}
1556#ifdef ARCHIVE_HAS_MD5
1557	if (mtree->compute_sum & F_MD5)
1558		archive_md5_final(&mtree->md5ctx, reg->digest.md5);
1559#endif
1560#ifdef ARCHIVE_HAS_RMD160
1561	if (mtree->compute_sum & F_RMD160)
1562		archive_rmd160_final(&mtree->rmd160ctx, reg->digest.rmd160);
1563#endif
1564#ifdef ARCHIVE_HAS_SHA1
1565	if (mtree->compute_sum & F_SHA1)
1566		archive_sha1_final(&mtree->sha1ctx, reg->digest.sha1);
1567#endif
1568#ifdef ARCHIVE_HAS_SHA256
1569	if (mtree->compute_sum & F_SHA256)
1570		archive_sha256_final(&mtree->sha256ctx, reg->digest.sha256);
1571#endif
1572#ifdef ARCHIVE_HAS_SHA384
1573	if (mtree->compute_sum & F_SHA384)
1574		archive_sha384_final(&mtree->sha384ctx, reg->digest.sha384);
1575#endif
1576#ifdef ARCHIVE_HAS_SHA512
1577	if (mtree->compute_sum & F_SHA512)
1578		archive_sha512_final(&mtree->sha512ctx, reg->digest.sha512);
1579#endif
1580	/* Save what types of sum are computed. */
1581	reg->compute_sum = mtree->compute_sum;
1582}
1583
1584#if defined(ARCHIVE_HAS_MD5) || defined(ARCHIVE_HAS_RMD160) || \
1585    defined(ARCHIVE_HAS_SHA1) || defined(ARCHIVE_HAS_SHA256) || \
1586    defined(ARCHIVE_HAS_SHA384) || defined(ARCHIVE_HAS_SHA512)
1587static void
1588strappend_bin(struct archive_string *s, const unsigned char *bin, int n)
1589{
1590	static const char hex[] = "0123456789abcdef";
1591	int i;
1592
1593	for (i = 0; i < n; i++) {
1594		archive_strappend_char(s, hex[bin[i] >> 4]);
1595		archive_strappend_char(s, hex[bin[i] & 0x0f]);
1596	}
1597}
1598#endif
1599
1600static void
1601sum_write(struct archive_string *str, struct reg_info *reg)
1602{
1603
1604	if (reg->compute_sum & F_CKSUM) {
1605		archive_string_sprintf(str, " cksum=%ju",
1606		    (uintmax_t)reg->crc);
1607	}
1608
1609#define append_digest(_s, _r, _t) \
1610	strappend_bin(_s, _r->digest._t, sizeof(_r->digest._t))
1611
1612#ifdef ARCHIVE_HAS_MD5
1613	if (reg->compute_sum & F_MD5) {
1614		archive_strcat(str, " md5digest=");
1615		append_digest(str, reg, md5);
1616	}
1617#endif
1618#ifdef ARCHIVE_HAS_RMD160
1619	if (reg->compute_sum & F_RMD160) {
1620		archive_strcat(str, " rmd160digest=");
1621		append_digest(str, reg, rmd160);
1622	}
1623#endif
1624#ifdef ARCHIVE_HAS_SHA1
1625	if (reg->compute_sum & F_SHA1) {
1626		archive_strcat(str, " sha1digest=");
1627		append_digest(str, reg, sha1);
1628	}
1629#endif
1630#ifdef ARCHIVE_HAS_SHA256
1631	if (reg->compute_sum & F_SHA256) {
1632		archive_strcat(str, " sha256digest=");
1633		append_digest(str, reg, sha256);
1634	}
1635#endif
1636#ifdef ARCHIVE_HAS_SHA384
1637	if (reg->compute_sum & F_SHA384) {
1638		archive_strcat(str, " sha384digest=");
1639		append_digest(str, reg, sha384);
1640	}
1641#endif
1642#ifdef ARCHIVE_HAS_SHA512
1643	if (reg->compute_sum & F_SHA512) {
1644		archive_strcat(str, " sha512digest=");
1645		append_digest(str, reg, sha512);
1646	}
1647#endif
1648#undef append_digest
1649}
1650
1651static int
1652mtree_entry_cmp_node(const struct archive_rb_node *n1,
1653    const struct archive_rb_node *n2)
1654{
1655	const struct mtree_entry *e1 = (const struct mtree_entry *)n1;
1656	const struct mtree_entry *e2 = (const struct mtree_entry *)n2;
1657
1658	return (strcmp(e2->basename.s, e1->basename.s));
1659}
1660
1661static int
1662mtree_entry_cmp_key(const struct archive_rb_node *n, const void *key)
1663{
1664	const struct mtree_entry *e = (const struct mtree_entry *)n;
1665
1666	return (strcmp((const char *)key, e->basename.s));
1667}
1668
1669#if defined(_WIN32) || defined(__CYGWIN__)
1670static int
1671cleanup_backslash_1(char *p)
1672{
1673	int mb, dos;
1674
1675	mb = dos = 0;
1676	while (*p) {
1677		if (*(unsigned char *)p > 127)
1678			mb = 1;
1679		if (*p == '\\') {
1680			/* If we have not met any multi-byte characters,
1681			 * we can replace '\' with '/'. */
1682			if (!mb)
1683				*p = '/';
1684			dos = 1;
1685		}
1686		p++;
1687	}
1688	if (!mb || !dos)
1689		return (0);
1690	return (-1);
1691}
1692
1693static void
1694cleanup_backslash_2(wchar_t *p)
1695{
1696
1697	/* Convert a path-separator from '\' to  '/' */
1698	while (*p != L'\0') {
1699		if (*p == L'\\')
1700			*p = L'/';
1701		p++;
1702	}
1703}
1704#endif
1705
1706/*
1707 * Generate a parent directory name and a base name from a pathname.
1708 */
1709static int
1710mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file,
1711    struct archive_entry *entry)
1712{
1713	const char *pathname;
1714	char *p, *dirname, *slash;
1715	size_t len;
1716	int ret = ARCHIVE_OK;
1717
1718	archive_strcpy(&file->pathname, archive_entry_pathname(entry));
1719#if defined(_WIN32) || defined(__CYGWIN__)
1720	/*
1721	 * Convert a path-separator from '\' to  '/'
1722	 */
1723	if (cleanup_backslash_1(file->pathname.s) != 0) {
1724		const wchar_t *wp = archive_entry_pathname_w(entry);
1725		struct archive_wstring ws;
1726
1727		if (wp != NULL) {
1728			int r;
1729			archive_string_init(&ws);
1730			archive_wstrcpy(&ws, wp);
1731			cleanup_backslash_2(ws.s);
1732			archive_string_empty(&(file->pathname));
1733			r = archive_string_append_from_wcs(&(file->pathname),
1734			    ws.s, ws.length);
1735			archive_wstring_free(&ws);
1736			if (r < 0 && errno == ENOMEM) {
1737				archive_set_error(&a->archive, ENOMEM,
1738				    "Can't allocate memory");
1739				return (ARCHIVE_FATAL);
1740			}
1741		}
1742	}
1743#else
1744	(void)a; /* UNUSED */
1745#endif
1746	pathname =  file->pathname.s;
1747	if (strcmp(pathname, ".") == 0) {
1748		archive_strcpy(&file->basename, ".");
1749		return (ARCHIVE_OK);
1750	}
1751
1752	archive_strcpy(&(file->parentdir), pathname);
1753
1754	len = file->parentdir.length;
1755	p = dirname = file->parentdir.s;
1756
1757	/*
1758	 * Remove leading '/' and '../' elements
1759	 */
1760	while (*p) {
1761		if (p[0] == '/') {
1762			p++;
1763			len--;
1764		} else if (p[0] != '.')
1765			break;
1766		else if (p[1] == '.' && p[2] == '/') {
1767			p += 3;
1768			len -= 3;
1769		} else
1770			break;
1771	}
1772	if (p != dirname) {
1773		memmove(dirname, p, len+1);
1774		p = dirname;
1775	}
1776	/*
1777	 * Remove "/","/." and "/.." elements from tail.
1778	 */
1779	while (len > 0) {
1780		size_t ll = len;
1781
1782		if (len > 0 && p[len-1] == '/') {
1783			p[len-1] = '\0';
1784			len--;
1785		}
1786		if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
1787			p[len-2] = '\0';
1788			len -= 2;
1789		}
1790		if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
1791		    p[len-1] == '.') {
1792			p[len-3] = '\0';
1793			len -= 3;
1794		}
1795		if (ll == len)
1796			break;
1797	}
1798	while (*p) {
1799		if (p[0] == '/') {
1800			if (p[1] == '/')
1801				/* Convert '//' --> '/' */
1802				strcpy(p, p+1);
1803			else if (p[1] == '.' && p[2] == '/')
1804				/* Convert '/./' --> '/' */
1805				strcpy(p, p+2);
1806			else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
1807				/* Convert 'dir/dir1/../dir2/'
1808				 *     --> 'dir/dir2/'
1809				 */
1810				char *rp = p -1;
1811				while (rp >= dirname) {
1812					if (*rp == '/')
1813						break;
1814					--rp;
1815				}
1816				if (rp > dirname) {
1817					strcpy(rp, p+3);
1818					p = rp;
1819				} else {
1820					strcpy(dirname, p+4);
1821					p = dirname;
1822				}
1823			} else
1824				p++;
1825		} else
1826			p++;
1827	}
1828	p = dirname;
1829	len = strlen(p);
1830
1831	/*
1832	 * Add "./" prefix.
1833	 * NOTE: If the pathname does not have a path separator, we have
1834	 * to add "./" to the head of the pathname because mtree reader
1835	 * will suppose that it is v1(a.k.a classic) mtree format and
1836	 * change the directory unexpectedly and so it will make a wrong
1837	 * path.
1838	 */
1839	if (strcmp(p, ".") != 0 && strncmp(p, "./", 2) != 0) {
1840		struct archive_string as;
1841		archive_string_init(&as);
1842		archive_strcpy(&as, "./");
1843		archive_strncat(&as, p, len);
1844		archive_string_empty(&file->parentdir);
1845		archive_string_concat(&file->parentdir, &as);
1846		archive_string_free(&as);
1847		p = file->parentdir.s;
1848		len = archive_strlen(&file->parentdir);
1849	}
1850
1851	/*
1852	 * Find out the position which points the last position of
1853	 * path separator('/').
1854	 */
1855	slash = NULL;
1856	for (; *p != '\0'; p++) {
1857		if (*p == '/')
1858			slash = p;
1859	}
1860	if (slash == NULL) {
1861		/* The pathname doesn't have a parent directory. */
1862		file->parentdir.length = len;
1863		archive_string_copy(&(file->basename), &(file->parentdir));
1864		archive_string_empty(&(file->parentdir));
1865		*file->parentdir.s = '\0';
1866		return (ret);
1867	}
1868
1869	/* Make a basename from file->parentdir.s and slash */
1870	*slash  = '\0';
1871	file->parentdir.length = slash - file->parentdir.s;
1872	archive_strcpy(&(file->basename),  slash + 1);
1873	return (ret);
1874}
1875
1876static int
1877mtree_entry_create_virtual_dir(struct archive_write *a, const char *pathname,
1878    struct mtree_entry **m_entry)
1879{
1880	struct archive_entry *entry;
1881	struct mtree_entry *file;
1882	int r;
1883
1884	entry = archive_entry_new();
1885	if (entry == NULL) {
1886		*m_entry = NULL;
1887		archive_set_error(&a->archive, ENOMEM,
1888		    "Can't allocate memory");
1889		return (ARCHIVE_FATAL);
1890	}
1891	archive_entry_copy_pathname(entry, pathname);
1892	archive_entry_set_mode(entry, AE_IFDIR | 0755);
1893	archive_entry_set_mtime(entry, time(NULL), 0);
1894
1895	r = mtree_entry_new(a, entry, &file);
1896	archive_entry_free(entry);
1897	if (r < ARCHIVE_WARN) {
1898		*m_entry = NULL;
1899		archive_set_error(&a->archive, ENOMEM,
1900		    "Can't allocate memory");
1901		return (ARCHIVE_FATAL);
1902	}
1903
1904	file->dir_info->virtual = 1;
1905
1906	*m_entry = file;
1907	return (ARCHIVE_OK);
1908}
1909
1910static void
1911mtree_entry_register_add(struct mtree_writer *mtree, struct mtree_entry *file)
1912{
1913        file->next = NULL;
1914        *mtree->file_list.last = file;
1915        mtree->file_list.last = &(file->next);
1916}
1917
1918static void
1919mtree_entry_register_init(struct mtree_writer *mtree)
1920{
1921	mtree->file_list.first = NULL;
1922	mtree->file_list.last = &(mtree->file_list.first);
1923}
1924
1925static void
1926mtree_entry_register_free(struct mtree_writer *mtree)
1927{
1928	struct mtree_entry *file, *file_next;
1929
1930	file = mtree->file_list.first;
1931	while (file != NULL) {
1932		file_next = file->next;
1933		mtree_entry_free(file);
1934		file = file_next;
1935	}
1936}
1937
1938static int
1939mtree_entry_add_child_tail(struct mtree_entry *parent,
1940    struct mtree_entry *child)
1941{
1942	child->dir_info->chnext = NULL;
1943	*parent->dir_info->children.last = child;
1944	parent->dir_info->children.last = &(child->dir_info->chnext);
1945	return (1);
1946}
1947
1948/*
1949 * Find a entry from a parent entry with the name.
1950 */
1951static struct mtree_entry *
1952mtree_entry_find_child(struct mtree_entry *parent, const char *child_name)
1953{
1954	struct mtree_entry *np;
1955
1956	if (parent == NULL)
1957		return (NULL);
1958	np = (struct mtree_entry *)__archive_rb_tree_find_node(
1959	    &(parent->dir_info->rbtree), child_name);
1960	return (np);
1961}
1962
1963static int
1964get_path_component(char *name, size_t n, const char *fn)
1965{
1966	char *p;
1967	size_t l;
1968
1969	p = strchr(fn, '/');
1970	if (p == NULL) {
1971		if ((l = strlen(fn)) == 0)
1972			return (0);
1973	} else
1974		l = p - fn;
1975	if (l > n -1)
1976		return (-1);
1977	memcpy(name, fn, l);
1978	name[l] = '\0';
1979
1980	return ((int)l);
1981}
1982
1983/*
1984 * Add a new entry into the tree.
1985 */
1986static int
1987mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep)
1988{
1989#if defined(_WIN32) && !defined(__CYGWIN__)
1990	char name[_MAX_FNAME];/* Included null terminator size. */
1991#elif defined(NAME_MAX) && NAME_MAX >= 255
1992	char name[NAME_MAX+1];
1993#else
1994	char name[256];
1995#endif
1996	struct mtree_writer *mtree = (struct mtree_writer *)a->format_data;
1997	struct mtree_entry *dent, *file, *np;
1998	const char *fn, *p;
1999	int l, r;
2000
2001	file = *filep;
2002	if (file->parentdir.length == 0 && file->basename.length == 1 &&
2003	    file->basename.s[0] == '.') {
2004		file->parent = file;
2005		if (mtree->root != NULL) {
2006			np = mtree->root;
2007			goto same_entry;
2008		}
2009		mtree->root = file;
2010		mtree_entry_register_add(mtree, file);
2011		return (ARCHIVE_OK);
2012	}
2013
2014	if (file->parentdir.length == 0) {
2015		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2016		    "Internal programming error "
2017		    "in generating canonical name for %s",
2018		    file->pathname.s);
2019		return (ARCHIVE_FAILED);
2020	}
2021
2022	fn = p = file->parentdir.s;
2023
2024	/*
2025	 * If the path of the parent directory of `file' entry is
2026	 * the same as the path of `cur_dirent', add `file' entry to
2027	 * `cur_dirent'.
2028	 */
2029	if (archive_strlen(&(mtree->cur_dirstr))
2030	      == archive_strlen(&(file->parentdir)) &&
2031	    strcmp(mtree->cur_dirstr.s, fn) == 0) {
2032		if (!__archive_rb_tree_insert_node(
2033		    &(mtree->cur_dirent->dir_info->rbtree),
2034		    (struct archive_rb_node *)file)) {
2035			/* There is the same name in the tree. */
2036			np = (struct mtree_entry *)__archive_rb_tree_find_node(
2037			    &(mtree->cur_dirent->dir_info->rbtree),
2038			    file->basename.s);
2039			goto same_entry;
2040		}
2041		file->parent = mtree->cur_dirent;
2042		mtree_entry_register_add(mtree, file);
2043		return (ARCHIVE_OK);
2044	}
2045
2046	dent = mtree->root;
2047	for (;;) {
2048		l = get_path_component(name, sizeof(name), fn);
2049		if (l == 0) {
2050			np = NULL;
2051			break;
2052		}
2053		if (l < 0) {
2054			archive_set_error(&a->archive,
2055			    ARCHIVE_ERRNO_MISC,
2056			    "A name buffer is too small");
2057			return (ARCHIVE_FATAL);
2058		}
2059		if (l == 1 && name[0] == '.' && dent != NULL &&
2060		    dent == mtree->root) {
2061			fn += l;
2062			if (fn[0] == '/')
2063				fn++;
2064			continue;
2065		}
2066
2067		np = mtree_entry_find_child(dent, name);
2068		if (np == NULL || fn[0] == '\0')
2069			break;
2070
2071		/* Find next sub directory. */
2072		if (!np->dir_info) {
2073			/* NOT Directory! */
2074			archive_set_error(&a->archive,
2075			    ARCHIVE_ERRNO_MISC,
2076			    "`%s' is not directory, we cannot insert `%s' ",
2077			    np->pathname.s, file->pathname.s);
2078			return (ARCHIVE_FAILED);
2079		}
2080		fn += l;
2081		if (fn[0] == '/')
2082			fn++;
2083		dent = np;
2084	}
2085	if (np == NULL) {
2086		/*
2087		 * Create virtual parent directories.
2088		 */
2089		while (fn[0] != '\0') {
2090			struct mtree_entry *vp;
2091			struct archive_string as;
2092
2093			archive_string_init(&as);
2094			archive_strncat(&as, p, fn - p + l);
2095			if (as.s[as.length-1] == '/') {
2096				as.s[as.length-1] = '\0';
2097				as.length--;
2098			}
2099			r = mtree_entry_create_virtual_dir(a, as.s, &vp);
2100			archive_string_free(&as);
2101			if (r < ARCHIVE_WARN)
2102				return (r);
2103
2104			if (strcmp(vp->pathname.s, ".") == 0) {
2105				vp->parent = vp;
2106				mtree->root = vp;
2107			} else {
2108				__archive_rb_tree_insert_node(
2109				    &(dent->dir_info->rbtree),
2110				    (struct archive_rb_node *)vp);
2111				vp->parent = dent;
2112			}
2113			mtree_entry_register_add(mtree, vp);
2114			np = vp;
2115
2116			fn += l;
2117			if (fn[0] == '/')
2118				fn++;
2119			l = get_path_component(name, sizeof(name), fn);
2120			if (l < 0) {
2121				archive_string_free(&as);
2122				archive_set_error(&a->archive,
2123				    ARCHIVE_ERRNO_MISC,
2124				    "A name buffer is too small");
2125				return (ARCHIVE_FATAL);
2126			}
2127			dent = np;
2128		}
2129
2130		/* Found out the parent directory where `file' can be
2131		 * inserted. */
2132		mtree->cur_dirent = dent;
2133		archive_string_empty(&(mtree->cur_dirstr));
2134		archive_string_ensure(&(mtree->cur_dirstr),
2135		    archive_strlen(&(dent->parentdir)) +
2136		    archive_strlen(&(dent->basename)) + 2);
2137		if (archive_strlen(&(dent->parentdir)) +
2138		    archive_strlen(&(dent->basename)) == 0)
2139			mtree->cur_dirstr.s[0] = 0;
2140		else {
2141			if (archive_strlen(&(dent->parentdir)) > 0) {
2142				archive_string_copy(&(mtree->cur_dirstr),
2143				    &(dent->parentdir));
2144				archive_strappend_char(
2145				    &(mtree->cur_dirstr), '/');
2146			}
2147			archive_string_concat(&(mtree->cur_dirstr),
2148			    &(dent->basename));
2149		}
2150
2151		if (!__archive_rb_tree_insert_node(
2152		    &(dent->dir_info->rbtree),
2153		    (struct archive_rb_node *)file)) {
2154			np = (struct mtree_entry *)__archive_rb_tree_find_node(
2155			    &(dent->dir_info->rbtree), file->basename.s);
2156			goto same_entry;
2157		}
2158		file->parent = dent;
2159		mtree_entry_register_add(mtree, file);
2160		return (ARCHIVE_OK);
2161	}
2162
2163same_entry:
2164	/*
2165	 * We have already has the entry the filename of which is
2166	 * the same.
2167	 */
2168	r = mtree_entry_exchange_same_entry(a, np, file);
2169	if (r < ARCHIVE_WARN)
2170		return (r);
2171	if (np->dir_info)
2172		np->dir_info->virtual = 0;
2173	*filep = np;
2174	mtree_entry_free(file);
2175	return (ARCHIVE_WARN);
2176}
2177
2178static int
2179mtree_entry_exchange_same_entry(struct archive_write *a, struct mtree_entry *np,
2180    struct mtree_entry *file)
2181{
2182
2183	if ((np->mode & AE_IFMT) != (file->mode & AE_IFMT)) {
2184		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2185		    "Found duplicate entries `%s' and its file type is "
2186		    "different",
2187		    np->pathname.s);
2188		return (ARCHIVE_FAILED);
2189	}
2190
2191	/* Update the existent mtree entry's attributes by the new one's. */
2192	archive_string_empty(&np->symlink);
2193	archive_string_concat(&np->symlink, &file->symlink);
2194	archive_string_empty(&np->uname);
2195	archive_string_concat(&np->uname, &file->uname);
2196	archive_string_empty(&np->gname);
2197	archive_string_concat(&np->gname, &file->gname);
2198	archive_string_empty(&np->fflags_text);
2199	archive_string_concat(&np->fflags_text, &file->fflags_text);
2200	np->nlink = file->nlink;
2201	np->filetype = file->filetype;
2202	np->mode = file->mode;
2203	np->size = file->size;
2204	np->uid = file->uid;
2205	np->gid = file->gid;
2206	np->fflags_set = file->fflags_set;
2207	np->fflags_clear = file->fflags_clear;
2208	np->mtime = file->mtime;
2209	np->mtime_nsec = file->mtime_nsec;
2210	np->rdevmajor = file->rdevmajor;
2211	np->rdevminor = file->rdevminor;
2212	np->devmajor = file->devmajor;
2213	np->devminor = file->devminor;
2214	np->ino = file->ino;
2215
2216	return (ARCHIVE_WARN);
2217}
2218