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