xref: /freebsd/contrib/libarchive/libarchive/archive_write_set_format_mtree.c (revision 2e113ef82465598b8c26e0ca415fbe90677fbd47)
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 
29 #ifdef HAVE_SYS_TYPES_H
30 #include <sys/types.h>
31 #endif
32 #include <errno.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include "archive.h"
37 #include "archive_digest_private.h"
38 #include "archive_entry.h"
39 #include "archive_entry_private.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 
50 struct attr_counter {
51 	struct attr_counter *prev;
52 	struct attr_counter *next;
53 	struct mtree_entry *m_entry;
54 	int count;
55 };
56 
57 struct attr_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 
64 struct mtree_chain {
65 	struct mtree_entry *first;
66 	struct mtree_entry **last;
67 };
68 
69 /*
70  * The Data only for a directory file.
71  */
72 struct 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  */
82 struct reg_info {
83 	int compute_sum;
84 	uint32_t crc;
85 	uint_least32_t mset_digest;
86 	struct ae_digest digest;
87 };
88 
89 struct 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 
120 struct 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 attr_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 
218 static void attr_counter_free(struct attr_counter **);
219 static int attr_counter_inc(struct attr_counter **, struct attr_counter *,
220 	struct attr_counter *, struct mtree_entry *);
221 static struct attr_counter * attr_counter_new(struct mtree_entry *,
222 	struct attr_counter *);
223 static int attr_counter_set_collect(struct mtree_writer *,
224 	struct mtree_entry *);
225 static void attr_counter_set_free(struct mtree_writer *);
226 static int get_global_set_keys(struct mtree_writer *, struct mtree_entry *);
227 static int mtree_entry_add_child_tail(struct mtree_entry *,
228 	struct mtree_entry *);
229 static int mtree_entry_create_virtual_dir(struct archive_write *, const char *,
230 	struct mtree_entry **);
231 static int mtree_entry_cmp_node(const struct archive_rb_node *,
232 	const struct archive_rb_node *);
233 static int mtree_entry_cmp_key(const struct archive_rb_node *, const void *);
234 static int mtree_entry_exchange_same_entry(struct archive_write *,
235     struct mtree_entry *, struct mtree_entry *);
236 static void mtree_entry_free(struct mtree_entry *);
237 static int mtree_entry_new(struct archive_write *, struct archive_entry *,
238 	struct mtree_entry **);
239 static void mtree_entry_register_free(struct mtree_writer *);
240 static void mtree_entry_register_init(struct mtree_writer *);
241 static int mtree_entry_setup_filenames(struct archive_write *,
242 	struct mtree_entry *, struct archive_entry *);
243 static int mtree_entry_tree_add(struct archive_write *, struct mtree_entry **);
244 static void sum_init(struct mtree_writer *);
245 static void sum_update(struct mtree_writer *, const void *, size_t);
246 static void sum_final(struct mtree_writer *, struct reg_info *);
247 static void sum_write(struct archive_string *, struct reg_info *);
248 static int write_mtree_entry(struct archive_write *, struct mtree_entry *);
249 static 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)]
252 static 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 
307 static 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 
332 static void
mtree_quote(struct archive_string * s,const char * str)333 mtree_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  */
360 static void
mtree_indent(struct mtree_writer * mtree)361 mtree_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  */
436 static void
write_global(struct mtree_writer * mtree)437 write_global(struct mtree_writer *mtree)
438 {
439 	struct archive_string setstr;
440 	struct archive_string unsetstr;
441 	struct attr_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 
566 static struct attr_counter *
attr_counter_new(struct mtree_entry * me,struct attr_counter * prev)567 attr_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 
581 static void
attr_counter_free(struct attr_counter ** top)582 attr_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 
597 static int
attr_counter_inc(struct attr_counter ** top,struct attr_counter * ac,struct attr_counter * last,struct mtree_entry * me)598 attr_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  */
638 static int
attr_counter_set_collect(struct mtree_writer * mtree,struct mtree_entry * me)639 attr_counter_set_collect(struct mtree_writer *mtree, struct mtree_entry *me)
640 {
641 	struct attr_counter *ac, *last;
642 	struct attr_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 
715 static void
attr_counter_set_free(struct mtree_writer * mtree)716 attr_counter_set_free(struct mtree_writer *mtree)
717 {
718 	struct attr_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 
726 static int
get_global_set_keys(struct mtree_writer * mtree,struct mtree_entry * me)727 get_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 
774 static int
mtree_entry_new(struct archive_write * a,struct archive_entry * entry,struct mtree_entry ** m_entry)775 mtree_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 
851 static void
mtree_entry_free(struct mtree_entry * me)852 mtree_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 
866 static void
mtree_copy_ae_digests(struct reg_info * reg,struct archive_entry * entry,int compute_sum)867 mtree_copy_ae_digests(struct reg_info *reg, struct archive_entry *entry, int compute_sum)
868 {
869 	reg->compute_sum = compute_sum;
870 	reg->mset_digest = entry->mset_digest;
871 
872 	if ((reg->compute_sum & F_MD5)
873 		&& (reg->mset_digest & AE_MSET_DIGEST_MD5)) {
874 
875 		memcpy(&reg->digest.md5, entry->digest.md5,
876 			sizeof(reg->digest.md5));
877 	}
878 	if ((reg->compute_sum & F_RMD160)
879 		&& (reg->mset_digest & AE_MSET_DIGEST_RMD160)) {
880 
881 		memcpy(&reg->digest.rmd160, entry->digest.rmd160,
882 			sizeof(reg->digest.rmd160));
883 	}
884 	if ((reg->compute_sum & F_SHA1)
885 		&& (reg->mset_digest & AE_MSET_DIGEST_SHA1)) {
886 
887 		memcpy(&reg->digest.sha1, entry->digest.sha1,
888 			sizeof(reg->digest.sha1));
889 	}
890 	if ((reg->compute_sum & F_SHA256)
891 		&& (reg->mset_digest & AE_MSET_DIGEST_SHA256)) {
892 
893 		memcpy(&reg->digest.sha256, entry->digest.sha256,
894 			sizeof(reg->digest.sha256));
895 	}
896 	if ((reg->compute_sum & F_SHA384)
897 		&& (reg->mset_digest & AE_MSET_DIGEST_SHA384)) {
898 
899 		memcpy(&reg->digest.sha384, entry->digest.sha384,
900 			sizeof(reg->digest.sha384));
901 	}
902 	if ((reg->compute_sum & F_SHA512)
903 		&& (reg->mset_digest & AE_MSET_DIGEST_SHA512)) {
904 
905 		memcpy(&reg->digest.sha512, entry->digest.sha512,
906 			sizeof(reg->digest.sha512));
907 	}
908 }
909 
910 static int
archive_write_mtree_header(struct archive_write * a,struct archive_entry * entry)911 archive_write_mtree_header(struct archive_write *a,
912     struct archive_entry *entry)
913 {
914 	struct mtree_writer *mtree= a->format_data;
915 	struct mtree_entry *mtree_entry;
916 	int r, r2;
917 
918 	if (mtree->first) {
919 		mtree->first = 0;
920 		archive_strcat(&mtree->buf, "#mtree\n");
921 		if ((mtree->keys & SET_KEYS) == 0)
922 			mtree->output_global_set = 0;/* Disabled. */
923 	}
924 
925 	mtree->entry_bytes_remaining = archive_entry_size(entry);
926 
927 	/* While directory only mode, we do not handle non directory files. */
928 	if (mtree->dironly && archive_entry_filetype(entry) != AE_IFDIR)
929 		return (ARCHIVE_OK);
930 
931 	r2 = mtree_entry_new(a, entry, &mtree_entry);
932 	if (r2 < ARCHIVE_WARN)
933 		return (r2);
934 	r = mtree_entry_tree_add(a, &mtree_entry);
935 	if (r < ARCHIVE_WARN) {
936 		mtree_entry_free(mtree_entry);
937 		return (r);
938 	}
939 	mtree->mtree_entry = mtree_entry;
940 
941 	/* If the current file is a regular file, we have to
942 	 * compute the sum of its content.
943 	 * Initialize a bunch of checksum context. */
944 	if (mtree_entry->reg_info) {
945 		sum_init(mtree);
946 		/* honor archive_entry_set_digest() calls. These values will be
947 		 * overwritten if archive_write_mtree_data() is called */
948 		mtree_copy_ae_digests(mtree_entry->reg_info, entry, mtree->compute_sum);
949 	}
950 
951 	return (r2);
952 }
953 
954 static int
write_mtree_entry(struct archive_write * a,struct mtree_entry * me)955 write_mtree_entry(struct archive_write *a, struct mtree_entry *me)
956 {
957 	struct mtree_writer *mtree = a->format_data;
958 	struct archive_string *str;
959 	int keys, ret;
960 
961 	if (me->dir_info) {
962 		if (mtree->classic) {
963 			/*
964 			 * Output a comment line to describe the full
965 			 * pathname of the entry as mtree utility does
966 			 * while generating classic format.
967 			 */
968 			if (!mtree->dironly)
969 				archive_strappend_char(&mtree->buf, '\n');
970 			if (me->parentdir.s)
971 				archive_string_sprintf(&mtree->buf,
972 				    "# %s/%s\n",
973 				    me->parentdir.s, me->basename.s);
974 			else
975 				archive_string_sprintf(&mtree->buf,
976 				    "# %s\n",
977 				    me->basename.s);
978 		}
979 		if (mtree->output_global_set)
980 			write_global(mtree);
981 	}
982 	archive_string_empty(&mtree->ebuf);
983 	str = (mtree->indent || mtree->classic)? &mtree->ebuf : &mtree->buf;
984 
985 	if (!mtree->classic && me->parentdir.s) {
986 		/*
987 		 * If generating format is not classic one(v1), output
988 		 * a full pathname.
989 		 */
990 		mtree_quote(str, me->parentdir.s);
991 		archive_strappend_char(str, '/');
992 	}
993 	mtree_quote(str, me->basename.s);
994 
995 	keys = get_global_set_keys(mtree, me);
996 	if ((keys & F_NLINK) != 0 &&
997 	    me->nlink != 1 && me->filetype != AE_IFDIR)
998 		archive_string_sprintf(str, " nlink=%u", me->nlink);
999 
1000 	if ((keys & F_GNAME) != 0 && archive_strlen(&me->gname) > 0) {
1001 		archive_strcat(str, " gname=");
1002 		mtree_quote(str, me->gname.s);
1003 	}
1004 	if ((keys & F_UNAME) != 0 && archive_strlen(&me->uname) > 0) {
1005 		archive_strcat(str, " uname=");
1006 		mtree_quote(str, me->uname.s);
1007 	}
1008 	if ((keys & F_FLAGS) != 0) {
1009 		if (archive_strlen(&me->fflags_text) > 0) {
1010 			archive_strcat(str, " flags=");
1011 			mtree_quote(str, me->fflags_text.s);
1012 		} else if (mtree->set.processing &&
1013 		    (mtree->set.keys & F_FLAGS) != 0)
1014 			/* Overwrite the global parameter. */
1015 			archive_strcat(str, " flags=none");
1016 	}
1017 	if ((keys & F_TIME) != 0)
1018 		archive_string_sprintf(str, " time=%jd.%jd",
1019 		    (intmax_t)me->mtime, (intmax_t)me->mtime_nsec);
1020 	if ((keys & F_MODE) != 0)
1021 		archive_string_sprintf(str, " mode=%o", (unsigned int)me->mode);
1022 	if ((keys & F_GID) != 0)
1023 		archive_string_sprintf(str, " gid=%jd", (intmax_t)me->gid);
1024 	if ((keys & F_UID) != 0)
1025 		archive_string_sprintf(str, " uid=%jd", (intmax_t)me->uid);
1026 
1027 	if ((keys & F_INO) != 0)
1028 		archive_string_sprintf(str, " inode=%jd", (intmax_t)me->ino);
1029 	if ((keys & F_RESDEV) != 0) {
1030 		archive_string_sprintf(str,
1031 		    " resdevice=native,%ju,%ju",
1032 		    (uintmax_t)me->devmajor,
1033 		    (uintmax_t)me->devminor);
1034 	}
1035 
1036 	switch (me->filetype) {
1037 	case AE_IFLNK:
1038 		if ((keys & F_TYPE) != 0)
1039 			archive_strcat(str, " type=link");
1040 		if ((keys & F_SLINK) != 0) {
1041 			archive_strcat(str, " link=");
1042 			mtree_quote(str, me->symlink.s);
1043 		}
1044 		break;
1045 	case AE_IFSOCK:
1046 		if ((keys & F_TYPE) != 0)
1047 			archive_strcat(str, " type=socket");
1048 		break;
1049 	case AE_IFCHR:
1050 		if ((keys & F_TYPE) != 0)
1051 			archive_strcat(str, " type=char");
1052 		if ((keys & F_DEV) != 0) {
1053 			archive_string_sprintf(str,
1054 			    " device=native,%ju,%ju",
1055 			    (uintmax_t)me->rdevmajor,
1056 			    (uintmax_t)me->rdevminor);
1057 		}
1058 		break;
1059 	case AE_IFBLK:
1060 		if ((keys & F_TYPE) != 0)
1061 			archive_strcat(str, " type=block");
1062 		if ((keys & F_DEV) != 0) {
1063 			archive_string_sprintf(str,
1064 			    " device=native,%ju,%ju",
1065 			    (uintmax_t)me->rdevmajor,
1066 			    (uintmax_t)me->rdevminor);
1067 		}
1068 		break;
1069 	case AE_IFDIR:
1070 		if ((keys & F_TYPE) != 0)
1071 			archive_strcat(str, " type=dir");
1072 		break;
1073 	case AE_IFIFO:
1074 		if ((keys & F_TYPE) != 0)
1075 			archive_strcat(str, " type=fifo");
1076 		break;
1077 	case AE_IFREG:
1078 	default:	/* Handle unknown file types as regular files. */
1079 		if ((keys & F_TYPE) != 0)
1080 			archive_strcat(str, " type=file");
1081 		if ((keys & F_SIZE) != 0)
1082 			archive_string_sprintf(str, " size=%jd",
1083 			    (intmax_t)me->size);
1084 		break;
1085 	}
1086 
1087 	/* Write a bunch of sum. */
1088 	if (me->reg_info)
1089 		sum_write(str, me->reg_info);
1090 
1091 	archive_strappend_char(str, '\n');
1092 	if (mtree->indent || mtree->classic)
1093 		mtree_indent(mtree);
1094 
1095 	if (mtree->buf.length > 32768) {
1096 		ret = __archive_write_output(
1097 			a, mtree->buf.s, mtree->buf.length);
1098 		archive_string_empty(&mtree->buf);
1099 	} else
1100 		ret = ARCHIVE_OK;
1101 	return (ret);
1102 }
1103 
1104 static int
write_dot_dot_entry(struct archive_write * a,struct mtree_entry * n)1105 write_dot_dot_entry(struct archive_write *a, struct mtree_entry *n)
1106 {
1107 	struct mtree_writer *mtree = a->format_data;
1108 	int ret;
1109 
1110 	if (n->parentdir.s) {
1111 		if (mtree->indent) {
1112 			int i, pd = mtree->depth * 4;
1113 			for (i = 0; i < pd; i++)
1114 				archive_strappend_char(&mtree->buf, ' ');
1115 		}
1116 		archive_string_sprintf(&mtree->buf, "# %s/%s\n",
1117 			n->parentdir.s, n->basename.s);
1118 	}
1119 
1120 	if (mtree->indent) {
1121 		archive_string_empty(&mtree->ebuf);
1122 		archive_strncat(&mtree->ebuf, "..\n\n", (mtree->dironly)?3:4);
1123 		mtree_indent(mtree);
1124 	} else
1125 		archive_strncat(&mtree->buf, "..\n\n", (mtree->dironly)?3:4);
1126 
1127 	if (mtree->buf.length > 32768) {
1128 		ret = __archive_write_output(
1129 			a, mtree->buf.s, mtree->buf.length);
1130 		archive_string_empty(&mtree->buf);
1131 	} else
1132 		ret = ARCHIVE_OK;
1133 	return (ret);
1134 }
1135 
1136 /*
1137  * Write mtree entries saved at attr_counter_set_collect() function.
1138  */
1139 static int
write_mtree_entry_tree(struct archive_write * a)1140 write_mtree_entry_tree(struct archive_write *a)
1141 {
1142 	struct mtree_writer *mtree = a->format_data;
1143 	struct mtree_entry *np = mtree->root;
1144 	struct archive_rb_node *n;
1145 	int ret;
1146 
1147 	do {
1148 		if (mtree->output_global_set) {
1149 			/*
1150 			 * Collect attribute information to know which value
1151 			 * is frequently used among the children.
1152 			 */
1153 			attr_counter_set_reset(mtree);
1154 			ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) {
1155 				struct mtree_entry *e = (struct mtree_entry *)n;
1156 				if (attr_counter_set_collect(mtree, e) < 0) {
1157 					archive_set_error(&a->archive, ENOMEM,
1158 					    "Can't allocate memory");
1159 					return (ARCHIVE_FATAL);
1160 				}
1161 			}
1162 		}
1163 		if (!np->dir_info->virtual || mtree->classic) {
1164 			ret = write_mtree_entry(a, np);
1165 			if (ret != ARCHIVE_OK)
1166 				return (ARCHIVE_FATAL);
1167 		} else {
1168 			/* Whenever output_global_set is enabled
1169 			 * output global value(/set keywords)
1170 			 * even if the directory entry is not allowed
1171 			 * to be written because the global values
1172 			 * can be used for the children. */
1173 			if (mtree->output_global_set)
1174 				write_global(mtree);
1175 		}
1176 		/*
1177 		 * Output the attribute of all files except directory files.
1178 		 */
1179 		mtree->depth++;
1180 		ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) {
1181 			struct mtree_entry *e = (struct mtree_entry *)n;
1182 
1183 			if (e->dir_info)
1184 				mtree_entry_add_child_tail(np, e);
1185 			else {
1186 				ret = write_mtree_entry(a, e);
1187 				if (ret != ARCHIVE_OK)
1188 					return (ARCHIVE_FATAL);
1189 			}
1190 		}
1191 		mtree->depth--;
1192 
1193 		if (np->dir_info->children.first != NULL) {
1194 			/*
1195 			 * Descend the tree.
1196 			 */
1197 			np = np->dir_info->children.first;
1198 			if (mtree->indent)
1199 				mtree->depth++;
1200 			continue;
1201 		} else if (mtree->classic) {
1202 			/*
1203 			 * While printing mtree classic, if there are not
1204 			 * any directory files(except "." and "..") in the
1205 			 * directory, output two dots ".." as returning
1206 			 * the parent directory.
1207 			 */
1208 			ret = write_dot_dot_entry(a, np);
1209 			if (ret != ARCHIVE_OK)
1210 				return (ARCHIVE_FATAL);
1211 		}
1212 
1213 		while (np != np->parent) {
1214 			if (np->dir_info->chnext == NULL) {
1215 				/*
1216 				 * Ascend the tree; go back to the parent.
1217 				 */
1218 				if (mtree->indent)
1219 					mtree->depth--;
1220 				if (mtree->classic) {
1221 					ret = write_dot_dot_entry(a,
1222 						np->parent);
1223 					if (ret != ARCHIVE_OK)
1224 						return (ARCHIVE_FATAL);
1225 				}
1226 				np = np->parent;
1227 			} else {
1228 				/*
1229 				 * Switch to next mtree entry in the directory.
1230 				 */
1231 				np = np->dir_info->chnext;
1232 				break;
1233 			}
1234 		}
1235 	} while (np != np->parent);
1236 
1237 	return (ARCHIVE_OK);
1238 }
1239 
1240 static int
archive_write_mtree_finish_entry(struct archive_write * a)1241 archive_write_mtree_finish_entry(struct archive_write *a)
1242 {
1243 	struct mtree_writer *mtree = a->format_data;
1244 	struct mtree_entry *me;
1245 
1246 	if ((me = mtree->mtree_entry) == NULL)
1247 		return (ARCHIVE_OK);
1248 	mtree->mtree_entry = NULL;
1249 
1250 	if (me->reg_info)
1251 		sum_final(mtree, me->reg_info);
1252 
1253 	return (ARCHIVE_OK);
1254 }
1255 
1256 static int
archive_write_mtree_close(struct archive_write * a)1257 archive_write_mtree_close(struct archive_write *a)
1258 {
1259 	struct mtree_writer *mtree= a->format_data;
1260 	int ret;
1261 
1262 	if (mtree->root != NULL) {
1263 		ret = write_mtree_entry_tree(a);
1264 		if (ret != ARCHIVE_OK)
1265 			return (ARCHIVE_FATAL);
1266 	}
1267 
1268 	archive_write_set_bytes_in_last_block(&a->archive, 1);
1269 
1270 	return __archive_write_output(a, mtree->buf.s, mtree->buf.length);
1271 }
1272 
1273 static ssize_t
archive_write_mtree_data(struct archive_write * a,const void * buff,size_t n)1274 archive_write_mtree_data(struct archive_write *a, const void *buff, size_t n)
1275 {
1276 	struct mtree_writer *mtree= a->format_data;
1277 
1278 	if (n > mtree->entry_bytes_remaining)
1279 		n = (size_t)mtree->entry_bytes_remaining;
1280 	mtree->entry_bytes_remaining -= n;
1281 
1282 	/* We don't need to compute a regular file sum */
1283 	if (mtree->mtree_entry == NULL)
1284 		return (n);
1285 
1286 	if (mtree->mtree_entry->filetype == AE_IFREG)
1287 		sum_update(mtree, buff, n);
1288 
1289 	return (n);
1290 }
1291 
1292 static int
archive_write_mtree_free(struct archive_write * a)1293 archive_write_mtree_free(struct archive_write *a)
1294 {
1295 	struct mtree_writer *mtree= a->format_data;
1296 
1297 	if (mtree == NULL)
1298 		return (ARCHIVE_OK);
1299 
1300 	/* Make sure we do not leave any entries. */
1301 	mtree_entry_register_free(mtree);
1302 	archive_string_free(&mtree->cur_dirstr);
1303 	archive_string_free(&mtree->ebuf);
1304 	archive_string_free(&mtree->buf);
1305 	attr_counter_set_free(mtree);
1306 	free(mtree);
1307 	a->format_data = NULL;
1308 	return (ARCHIVE_OK);
1309 }
1310 
1311 static int
archive_write_mtree_options(struct archive_write * a,const char * key,const char * value)1312 archive_write_mtree_options(struct archive_write *a, const char *key,
1313     const char *value)
1314 {
1315 	struct mtree_writer *mtree= a->format_data;
1316 	int keybit = 0;
1317 
1318 	switch (key[0]) {
1319 	case 'a':
1320 		if (strcmp(key, "all") == 0)
1321 			keybit = ~0;
1322 		break;
1323 	case 'c':
1324 		if (strcmp(key, "cksum") == 0)
1325 			keybit = F_CKSUM;
1326 		break;
1327 	case 'd':
1328 		if (strcmp(key, "device") == 0)
1329 			keybit = F_DEV;
1330 		else if (strcmp(key, "dironly") == 0) {
1331 			mtree->dironly = (value != NULL)? 1: 0;
1332 			return (ARCHIVE_OK);
1333 		}
1334 		break;
1335 	case 'f':
1336 		if (strcmp(key, "flags") == 0)
1337 			keybit = F_FLAGS;
1338 		break;
1339 	case 'g':
1340 		if (strcmp(key, "gid") == 0)
1341 			keybit = F_GID;
1342 		else if (strcmp(key, "gname") == 0)
1343 			keybit = F_GNAME;
1344 		break;
1345 	case 'i':
1346 		if (strcmp(key, "indent") == 0) {
1347 			mtree->indent = (value != NULL)? 1: 0;
1348 			return (ARCHIVE_OK);
1349 		} else if (strcmp(key, "inode") == 0) {
1350 			keybit = F_INO;
1351 		}
1352 		break;
1353 	case 'l':
1354 		if (strcmp(key, "link") == 0)
1355 			keybit = F_SLINK;
1356 		break;
1357 	case 'm':
1358 		if (strcmp(key, "md5") == 0 ||
1359 		    strcmp(key, "md5digest") == 0)
1360 			keybit = F_MD5;
1361 		if (strcmp(key, "mode") == 0)
1362 			keybit = F_MODE;
1363 		break;
1364 	case 'n':
1365 		if (strcmp(key, "nlink") == 0)
1366 			keybit = F_NLINK;
1367 		break;
1368 	case 'r':
1369 		if (strcmp(key, "resdevice") == 0) {
1370 			keybit = F_RESDEV;
1371 		} else if (strcmp(key, "ripemd160digest") == 0 ||
1372 		    strcmp(key, "rmd160") == 0 ||
1373 		    strcmp(key, "rmd160digest") == 0)
1374 			keybit = F_RMD160;
1375 		break;
1376 	case 's':
1377 		if (strcmp(key, "sha1") == 0 ||
1378 		    strcmp(key, "sha1digest") == 0)
1379 			keybit = F_SHA1;
1380 		if (strcmp(key, "sha256") == 0 ||
1381 		    strcmp(key, "sha256digest") == 0)
1382 			keybit = F_SHA256;
1383 		if (strcmp(key, "sha384") == 0 ||
1384 		    strcmp(key, "sha384digest") == 0)
1385 			keybit = F_SHA384;
1386 		if (strcmp(key, "sha512") == 0 ||
1387 		    strcmp(key, "sha512digest") == 0)
1388 			keybit = F_SHA512;
1389 		if (strcmp(key, "size") == 0)
1390 			keybit = F_SIZE;
1391 		break;
1392 	case 't':
1393 		if (strcmp(key, "time") == 0)
1394 			keybit = F_TIME;
1395 		else if (strcmp(key, "type") == 0)
1396 			keybit = F_TYPE;
1397 		break;
1398 	case 'u':
1399 		if (strcmp(key, "uid") == 0)
1400 			keybit = F_UID;
1401 		else if (strcmp(key, "uname") == 0)
1402 			keybit = F_UNAME;
1403 		else if (strcmp(key, "use-set") == 0) {
1404 			mtree->output_global_set = (value != NULL)? 1: 0;
1405 			return (ARCHIVE_OK);
1406 		}
1407 		break;
1408 	}
1409 	if (keybit != 0) {
1410 		if (value != NULL)
1411 			mtree->keys |= keybit;
1412 		else
1413 			mtree->keys &= ~keybit;
1414 		return (ARCHIVE_OK);
1415 	}
1416 
1417 	/* Note: The "warn" return is just to inform the options
1418 	 * supervisor that we didn't handle it.  It will generate
1419 	 * a suitable error if no one used this option. */
1420 	return (ARCHIVE_WARN);
1421 }
1422 
1423 static int
archive_write_set_format_mtree_default(struct archive * _a,const char * fn)1424 archive_write_set_format_mtree_default(struct archive *_a, const char *fn)
1425 {
1426 	struct archive_write *a = (struct archive_write *)_a;
1427 	struct mtree_writer *mtree;
1428 
1429 	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, fn);
1430 
1431 	if (a->format_free != NULL)
1432 		(a->format_free)(a);
1433 
1434 	if ((mtree = calloc(1, sizeof(*mtree))) == NULL) {
1435 		archive_set_error(&a->archive, ENOMEM,
1436 		    "Can't allocate mtree data");
1437 		return (ARCHIVE_FATAL);
1438 	}
1439 
1440 	mtree->mtree_entry = NULL;
1441 	mtree->first = 1;
1442 	memset(&(mtree->set), 0, sizeof(mtree->set));
1443 	mtree->keys = DEFAULT_KEYS;
1444 	mtree->dironly = 0;
1445 	mtree->indent = 0;
1446 	archive_string_init(&mtree->ebuf);
1447 	archive_string_init(&mtree->buf);
1448 	mtree_entry_register_init(mtree);
1449 	a->format_data = mtree;
1450 	a->format_free = archive_write_mtree_free;
1451 	a->format_name = "mtree";
1452 	a->format_options = archive_write_mtree_options;
1453 	a->format_write_header = archive_write_mtree_header;
1454 	a->format_close = archive_write_mtree_close;
1455 	a->format_write_data = archive_write_mtree_data;
1456 	a->format_finish_entry = archive_write_mtree_finish_entry;
1457 	a->archive.archive_format = ARCHIVE_FORMAT_MTREE;
1458 	a->archive.archive_format_name = "mtree";
1459 
1460 	return (ARCHIVE_OK);
1461 }
1462 
1463 int
archive_write_set_format_mtree(struct archive * _a)1464 archive_write_set_format_mtree(struct archive *_a)
1465 {
1466 	return archive_write_set_format_mtree_default(_a,
1467 		"archive_write_set_format_mtree");
1468 }
1469 
1470 int
archive_write_set_format_mtree_classic(struct archive * _a)1471 archive_write_set_format_mtree_classic(struct archive *_a)
1472 {
1473 	int r;
1474 
1475 	r = archive_write_set_format_mtree_default(_a,
1476 		"archive_write_set_format_mtree_classic");
1477 	if (r == ARCHIVE_OK) {
1478 		struct archive_write *a = (struct archive_write *)_a;
1479 		struct mtree_writer *mtree;
1480 
1481 		mtree = (struct mtree_writer *)a->format_data;
1482 
1483 		/* Set to output a mtree archive in classic format. */
1484 		mtree->classic = 1;
1485 		/* Basically, mtree classic format uses '/set' global
1486 		 * value. */
1487 		mtree->output_global_set = 1;
1488 	}
1489 	return (r);
1490 }
1491 
1492 static void
sum_init(struct mtree_writer * mtree)1493 sum_init(struct mtree_writer *mtree)
1494 {
1495 
1496 	mtree->compute_sum = 0;
1497 
1498 	if (mtree->keys & F_CKSUM) {
1499 		mtree->compute_sum |= F_CKSUM;
1500 		mtree->crc = 0;
1501 		mtree->crc_len = 0;
1502 	}
1503 #ifdef ARCHIVE_HAS_MD5
1504 	if (mtree->keys & F_MD5) {
1505 		if (archive_md5_init(&mtree->md5ctx) == ARCHIVE_OK)
1506 			mtree->compute_sum |= F_MD5;
1507 		else
1508 			mtree->keys &= ~F_MD5;/* Not supported. */
1509 	}
1510 #endif
1511 #ifdef ARCHIVE_HAS_RMD160
1512 	if (mtree->keys & F_RMD160) {
1513 		if (archive_rmd160_init(&mtree->rmd160ctx) == ARCHIVE_OK)
1514 			mtree->compute_sum |= F_RMD160;
1515 		else
1516 			mtree->keys &= ~F_RMD160;/* Not supported. */
1517 	}
1518 #endif
1519 #ifdef ARCHIVE_HAS_SHA1
1520 	if (mtree->keys & F_SHA1) {
1521 		if (archive_sha1_init(&mtree->sha1ctx) == ARCHIVE_OK)
1522 			mtree->compute_sum |= F_SHA1;
1523 		else
1524 			mtree->keys &= ~F_SHA1;/* Not supported. */
1525 	}
1526 #endif
1527 #ifdef ARCHIVE_HAS_SHA256
1528 	if (mtree->keys & F_SHA256) {
1529 		if (archive_sha256_init(&mtree->sha256ctx) == ARCHIVE_OK)
1530 			mtree->compute_sum |= F_SHA256;
1531 		else
1532 			mtree->keys &= ~F_SHA256;/* Not supported. */
1533 	}
1534 #endif
1535 #ifdef ARCHIVE_HAS_SHA384
1536 	if (mtree->keys & F_SHA384) {
1537 		if (archive_sha384_init(&mtree->sha384ctx) == ARCHIVE_OK)
1538 			mtree->compute_sum |= F_SHA384;
1539 		else
1540 			mtree->keys &= ~F_SHA384;/* Not supported. */
1541 	}
1542 #endif
1543 #ifdef ARCHIVE_HAS_SHA512
1544 	if (mtree->keys & F_SHA512) {
1545 		if (archive_sha512_init(&mtree->sha512ctx) == ARCHIVE_OK)
1546 			mtree->compute_sum |= F_SHA512;
1547 		else
1548 			mtree->keys &= ~F_SHA512;/* Not supported. */
1549 	}
1550 #endif
1551 }
1552 
1553 static void
sum_update(struct mtree_writer * mtree,const void * buff,size_t n)1554 sum_update(struct mtree_writer *mtree, const void *buff, size_t n)
1555 {
1556 	if (mtree->compute_sum & F_CKSUM) {
1557 		/*
1558 		 * Compute a POSIX 1003.2 checksum
1559 		 */
1560 		const unsigned char *p;
1561 		size_t nn;
1562 
1563 		for (nn = n, p = buff; nn--; ++p)
1564 			COMPUTE_CRC(mtree->crc, *p);
1565 		mtree->crc_len += n;
1566 	}
1567 #ifdef ARCHIVE_HAS_MD5
1568 	if (mtree->compute_sum & F_MD5) {
1569 		archive_md5_update(&mtree->md5ctx, buff, n);
1570 		mtree->mtree_entry->reg_info->mset_digest &=
1571 			~AE_MSET_DIGEST_MD5;
1572 	}
1573 #endif
1574 #ifdef ARCHIVE_HAS_RMD160
1575 	if (mtree->compute_sum & F_RMD160) {
1576 		archive_rmd160_update(&mtree->rmd160ctx, buff, n);
1577 		mtree->mtree_entry->reg_info->mset_digest &=
1578 			~AE_MSET_DIGEST_RMD160;
1579 	}
1580 #endif
1581 #ifdef ARCHIVE_HAS_SHA1
1582 	if (mtree->compute_sum & F_SHA1) {
1583 		archive_sha1_update(&mtree->sha1ctx, buff, n);
1584 		mtree->mtree_entry->reg_info->mset_digest &=
1585 			~AE_MSET_DIGEST_SHA1;
1586 	}
1587 #endif
1588 #ifdef ARCHIVE_HAS_SHA256
1589 	if (mtree->compute_sum & F_SHA256) {
1590 		archive_sha256_update(&mtree->sha256ctx, buff, n);
1591 		mtree->mtree_entry->reg_info->mset_digest &=
1592 			~AE_MSET_DIGEST_SHA256;
1593 	}
1594 #endif
1595 #ifdef ARCHIVE_HAS_SHA384
1596 	if (mtree->compute_sum & F_SHA384) {
1597 		archive_sha384_update(&mtree->sha384ctx, buff, n);
1598 		mtree->mtree_entry->reg_info->mset_digest &=
1599 			~AE_MSET_DIGEST_SHA384;
1600 	}
1601 #endif
1602 #ifdef ARCHIVE_HAS_SHA512
1603 	if (mtree->compute_sum & F_SHA512) {
1604 		archive_sha512_update(&mtree->sha512ctx, buff, n);
1605 		mtree->mtree_entry->reg_info->mset_digest &=
1606 			~AE_MSET_DIGEST_SHA512;
1607 	}
1608 #endif
1609 }
1610 
1611 static void
sum_final(struct mtree_writer * mtree,struct reg_info * reg)1612 sum_final(struct mtree_writer *mtree, struct reg_info *reg)
1613 {
1614 
1615 	if (mtree->compute_sum & F_CKSUM) {
1616 		uint64_t len;
1617 		/* Include the length of the file. */
1618 		for (len = mtree->crc_len; len != 0; len >>= 8)
1619 			COMPUTE_CRC(mtree->crc, len & 0xff);
1620 		reg->crc = ~mtree->crc;
1621 	}
1622 #ifdef ARCHIVE_HAS_MD5
1623 	if ((mtree->compute_sum & F_MD5)
1624 		&& !(reg->mset_digest & AE_MSET_DIGEST_MD5))
1625 
1626 		archive_md5_final(&mtree->md5ctx, reg->digest.md5);
1627 #endif
1628 #ifdef ARCHIVE_HAS_RMD160
1629 	if ((mtree->compute_sum & F_RMD160)
1630 		&& !(reg->mset_digest & AE_MSET_DIGEST_RMD160))
1631 
1632 		archive_rmd160_final(&mtree->rmd160ctx, reg->digest.rmd160);
1633 #endif
1634 #ifdef ARCHIVE_HAS_SHA1
1635 	if ((mtree->compute_sum & F_SHA1)
1636 		&& !(reg->mset_digest & AE_MSET_DIGEST_SHA1))
1637 
1638 		archive_sha1_final(&mtree->sha1ctx, reg->digest.sha1);
1639 #endif
1640 #ifdef ARCHIVE_HAS_SHA256
1641 	if ((mtree->compute_sum & F_SHA256)
1642 		&& !(reg->mset_digest & AE_MSET_DIGEST_SHA256))
1643 
1644 		archive_sha256_final(&mtree->sha256ctx, reg->digest.sha256);
1645 #endif
1646 #ifdef ARCHIVE_HAS_SHA384
1647 	if ((mtree->compute_sum & F_SHA384)
1648 		&& !(reg->mset_digest & AE_MSET_DIGEST_SHA384))
1649 
1650 		archive_sha384_final(&mtree->sha384ctx, reg->digest.sha384);
1651 #endif
1652 #ifdef ARCHIVE_HAS_SHA512
1653 	if ((mtree->compute_sum & F_SHA512)
1654 		&& !(reg->mset_digest & AE_MSET_DIGEST_SHA512))
1655 
1656 		archive_sha512_final(&mtree->sha512ctx, reg->digest.sha512);
1657 #endif
1658 	/* Save what types of sum are computed. */
1659 	reg->compute_sum = mtree->compute_sum;
1660 }
1661 
1662 #if defined(ARCHIVE_HAS_MD5) || defined(ARCHIVE_HAS_RMD160) || \
1663     defined(ARCHIVE_HAS_SHA1) || defined(ARCHIVE_HAS_SHA256) || \
1664     defined(ARCHIVE_HAS_SHA384) || defined(ARCHIVE_HAS_SHA512)
1665 static void
strappend_bin(struct archive_string * s,const unsigned char * bin,int n)1666 strappend_bin(struct archive_string *s, const unsigned char *bin, int n)
1667 {
1668 	static const char hex[] = "0123456789abcdef";
1669 	int i;
1670 
1671 	for (i = 0; i < n; i++) {
1672 		archive_strappend_char(s, hex[bin[i] >> 4]);
1673 		archive_strappend_char(s, hex[bin[i] & 0x0f]);
1674 	}
1675 }
1676 #endif
1677 
1678 static void
sum_write(struct archive_string * str,struct reg_info * reg)1679 sum_write(struct archive_string *str, struct reg_info *reg)
1680 {
1681 
1682 	if (reg->compute_sum & F_CKSUM) {
1683 		archive_string_sprintf(str, " cksum=%ju",
1684 		    (uintmax_t)reg->crc);
1685 	}
1686 
1687 #define append_digest(_s, _r, _t) \
1688 	strappend_bin(_s, _r->digest._t, sizeof(_r->digest._t))
1689 
1690 #ifdef ARCHIVE_HAS_MD5
1691 	if (reg->compute_sum & F_MD5) {
1692 		archive_strcat(str, " md5digest=");
1693 		append_digest(str, reg, md5);
1694 	}
1695 #endif
1696 #ifdef ARCHIVE_HAS_RMD160
1697 	if (reg->compute_sum & F_RMD160) {
1698 		archive_strcat(str, " rmd160digest=");
1699 		append_digest(str, reg, rmd160);
1700 	}
1701 #endif
1702 #ifdef ARCHIVE_HAS_SHA1
1703 	if (reg->compute_sum & F_SHA1) {
1704 		archive_strcat(str, " sha1digest=");
1705 		append_digest(str, reg, sha1);
1706 	}
1707 #endif
1708 #ifdef ARCHIVE_HAS_SHA256
1709 	if (reg->compute_sum & F_SHA256) {
1710 		archive_strcat(str, " sha256digest=");
1711 		append_digest(str, reg, sha256);
1712 	}
1713 #endif
1714 #ifdef ARCHIVE_HAS_SHA384
1715 	if (reg->compute_sum & F_SHA384) {
1716 		archive_strcat(str, " sha384digest=");
1717 		append_digest(str, reg, sha384);
1718 	}
1719 #endif
1720 #ifdef ARCHIVE_HAS_SHA512
1721 	if (reg->compute_sum & F_SHA512) {
1722 		archive_strcat(str, " sha512digest=");
1723 		append_digest(str, reg, sha512);
1724 	}
1725 #endif
1726 #undef append_digest
1727 }
1728 
1729 static int
mtree_entry_cmp_node(const struct archive_rb_node * n1,const struct archive_rb_node * n2)1730 mtree_entry_cmp_node(const struct archive_rb_node *n1,
1731     const struct archive_rb_node *n2)
1732 {
1733 	const struct mtree_entry *e1 = (const struct mtree_entry *)n1;
1734 	const struct mtree_entry *e2 = (const struct mtree_entry *)n2;
1735 
1736 	return (strcmp(e2->basename.s, e1->basename.s));
1737 }
1738 
1739 static int
mtree_entry_cmp_key(const struct archive_rb_node * n,const void * key)1740 mtree_entry_cmp_key(const struct archive_rb_node *n, const void *key)
1741 {
1742 	const struct mtree_entry *e = (const struct mtree_entry *)n;
1743 
1744 	return (strcmp((const char *)key, e->basename.s));
1745 }
1746 
1747 #if defined(_WIN32) || defined(__CYGWIN__)
1748 static int
cleanup_backslash_1(char * p)1749 cleanup_backslash_1(char *p)
1750 {
1751 	int mb, dos;
1752 
1753 	mb = dos = 0;
1754 	while (*p) {
1755 		if (*(unsigned char *)p > 127)
1756 			mb = 1;
1757 		if (*p == '\\') {
1758 			/* If we have not met any multi-byte characters,
1759 			 * we can replace '\' with '/'. */
1760 			if (!mb)
1761 				*p = '/';
1762 			dos = 1;
1763 		}
1764 		p++;
1765 	}
1766 	if (!mb || !dos)
1767 		return (0);
1768 	return (-1);
1769 }
1770 
1771 static void
cleanup_backslash_2(wchar_t * p)1772 cleanup_backslash_2(wchar_t *p)
1773 {
1774 
1775 	/* Convert a path-separator from '\' to  '/' */
1776 	while (*p != L'\0') {
1777 		if (*p == L'\\')
1778 			*p = L'/';
1779 		p++;
1780 	}
1781 }
1782 #endif
1783 
1784 /*
1785  * Generate a parent directory name and a base name from a pathname.
1786  */
1787 static int
mtree_entry_setup_filenames(struct archive_write * a,struct mtree_entry * file,struct archive_entry * entry)1788 mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file,
1789     struct archive_entry *entry)
1790 {
1791 	const char *pathname;
1792 	char *p, *dirname, *slash;
1793 	size_t len;
1794 	int ret = ARCHIVE_OK;
1795 
1796 	archive_strcpy(&file->pathname, archive_entry_pathname(entry));
1797 #if defined(_WIN32) || defined(__CYGWIN__)
1798 	/*
1799 	 * Convert a path-separator from '\' to  '/'
1800 	 */
1801 	if (cleanup_backslash_1(file->pathname.s) != 0) {
1802 		const wchar_t *wp = archive_entry_pathname_w(entry);
1803 		struct archive_wstring ws;
1804 
1805 		if (wp != NULL) {
1806 			int r;
1807 			archive_string_init(&ws);
1808 			archive_wstrcpy(&ws, wp);
1809 			cleanup_backslash_2(ws.s);
1810 			archive_string_empty(&(file->pathname));
1811 			r = archive_string_append_from_wcs(&(file->pathname),
1812 			    ws.s, ws.length);
1813 			archive_wstring_free(&ws);
1814 			if (r < 0 && errno == ENOMEM) {
1815 				archive_set_error(&a->archive, ENOMEM,
1816 				    "Can't allocate memory");
1817 				return (ARCHIVE_FATAL);
1818 			}
1819 		}
1820 	}
1821 #else
1822 	(void)a; /* UNUSED */
1823 #endif
1824 	pathname =  file->pathname.s;
1825 	if (strcmp(pathname, ".") == 0) {
1826 		archive_strcpy(&file->basename, ".");
1827 		return (ARCHIVE_OK);
1828 	}
1829 
1830 	archive_strcpy(&(file->parentdir), pathname);
1831 
1832 	len = file->parentdir.length;
1833 	p = dirname = file->parentdir.s;
1834 
1835 	/*
1836 	 * Remove leading '/' and '../' elements
1837 	 */
1838 	while (*p) {
1839 		if (p[0] == '/') {
1840 			p++;
1841 			len--;
1842 		} else if (p[0] != '.')
1843 			break;
1844 		else if (p[1] == '.' && p[2] == '/') {
1845 			p += 3;
1846 			len -= 3;
1847 		} else
1848 			break;
1849 	}
1850 	if (p != dirname) {
1851 		memmove(dirname, p, len+1);
1852 		p = dirname;
1853 	}
1854 	/*
1855 	 * Remove "/","/." and "/.." elements from tail.
1856 	 */
1857 	while (len > 0) {
1858 		size_t ll = len;
1859 
1860 		if (len > 0 && p[len-1] == '/') {
1861 			p[len-1] = '\0';
1862 			len--;
1863 		}
1864 		if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
1865 			p[len-2] = '\0';
1866 			len -= 2;
1867 		}
1868 		if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
1869 		    p[len-1] == '.') {
1870 			p[len-3] = '\0';
1871 			len -= 3;
1872 		}
1873 		if (ll == len)
1874 			break;
1875 	}
1876 	while (*p) {
1877 		if (p[0] == '/') {
1878 			if (p[1] == '/')
1879 				/* Convert '//' --> '/' */
1880 				memmove(p, p+1, strlen(p+1) + 1);
1881 			else if (p[1] == '.' && p[2] == '/')
1882 				/* Convert '/./' --> '/' */
1883 				memmove(p, p+2, strlen(p+2) + 1);
1884 			else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
1885 				/* Convert 'dir/dir1/../dir2/'
1886 				 *     --> 'dir/dir2/'
1887 				 */
1888 				char *rp = p -1;
1889 				while (rp >= dirname) {
1890 					if (*rp == '/')
1891 						break;
1892 					--rp;
1893 				}
1894 				if (rp > dirname) {
1895 					strcpy(rp, p+3);
1896 					p = rp;
1897 				} else {
1898 					strcpy(dirname, p+4);
1899 					p = dirname;
1900 				}
1901 			} else
1902 				p++;
1903 		} else
1904 			p++;
1905 	}
1906 	p = dirname;
1907 	len = strlen(p);
1908 
1909 	/*
1910 	 * Add "./" prefix.
1911 	 * NOTE: If the pathname does not have a path separator, we have
1912 	 * to add "./" to the head of the pathname because mtree reader
1913 	 * will suppose that it is v1(a.k.a classic) mtree format and
1914 	 * change the directory unexpectedly and so it will make a wrong
1915 	 * path.
1916 	 */
1917 	if (strcmp(p, ".") != 0 && strncmp(p, "./", 2) != 0) {
1918 		struct archive_string as;
1919 		archive_string_init(&as);
1920 		archive_strcpy(&as, "./");
1921 		archive_strncat(&as, p, len);
1922 		archive_string_empty(&file->parentdir);
1923 		archive_string_concat(&file->parentdir, &as);
1924 		archive_string_free(&as);
1925 		p = file->parentdir.s;
1926 		len = archive_strlen(&file->parentdir);
1927 	}
1928 
1929 	/*
1930 	 * Find out the position which points the last position of
1931 	 * path separator('/').
1932 	 */
1933 	slash = NULL;
1934 	for (; *p != '\0'; p++) {
1935 		if (*p == '/')
1936 			slash = p;
1937 	}
1938 	if (slash == NULL) {
1939 		/* The pathname doesn't have a parent directory. */
1940 		file->parentdir.length = len;
1941 		archive_string_copy(&(file->basename), &(file->parentdir));
1942 		archive_string_empty(&(file->parentdir));
1943 		*file->parentdir.s = '\0';
1944 		return (ret);
1945 	}
1946 
1947 	/* Make a basename from file->parentdir.s and slash */
1948 	*slash  = '\0';
1949 	file->parentdir.length = slash - file->parentdir.s;
1950 	archive_strcpy(&(file->basename),  slash + 1);
1951 	return (ret);
1952 }
1953 
1954 static int
mtree_entry_create_virtual_dir(struct archive_write * a,const char * pathname,struct mtree_entry ** m_entry)1955 mtree_entry_create_virtual_dir(struct archive_write *a, const char *pathname,
1956     struct mtree_entry **m_entry)
1957 {
1958 	struct archive_entry *entry;
1959 	struct mtree_entry *file;
1960 	int r;
1961 
1962 	entry = archive_entry_new();
1963 	if (entry == NULL) {
1964 		*m_entry = NULL;
1965 		archive_set_error(&a->archive, ENOMEM,
1966 		    "Can't allocate memory");
1967 		return (ARCHIVE_FATAL);
1968 	}
1969 	archive_entry_copy_pathname(entry, pathname);
1970 	archive_entry_set_mode(entry, AE_IFDIR | 0755);
1971 	archive_entry_set_mtime(entry, time(NULL), 0);
1972 
1973 	r = mtree_entry_new(a, entry, &file);
1974 	archive_entry_free(entry);
1975 	if (r < ARCHIVE_WARN) {
1976 		*m_entry = NULL;
1977 		archive_set_error(&a->archive, ENOMEM,
1978 		    "Can't allocate memory");
1979 		return (ARCHIVE_FATAL);
1980 	}
1981 
1982 	file->dir_info->virtual = 1;
1983 
1984 	*m_entry = file;
1985 	return (ARCHIVE_OK);
1986 }
1987 
1988 static void
mtree_entry_register_add(struct mtree_writer * mtree,struct mtree_entry * file)1989 mtree_entry_register_add(struct mtree_writer *mtree, struct mtree_entry *file)
1990 {
1991         file->next = NULL;
1992         *mtree->file_list.last = file;
1993         mtree->file_list.last = &(file->next);
1994 }
1995 
1996 static void
mtree_entry_register_init(struct mtree_writer * mtree)1997 mtree_entry_register_init(struct mtree_writer *mtree)
1998 {
1999 	mtree->file_list.first = NULL;
2000 	mtree->file_list.last = &(mtree->file_list.first);
2001 }
2002 
2003 static void
mtree_entry_register_free(struct mtree_writer * mtree)2004 mtree_entry_register_free(struct mtree_writer *mtree)
2005 {
2006 	struct mtree_entry *file, *file_next;
2007 
2008 	file = mtree->file_list.first;
2009 	while (file != NULL) {
2010 		file_next = file->next;
2011 		mtree_entry_free(file);
2012 		file = file_next;
2013 	}
2014 }
2015 
2016 static int
mtree_entry_add_child_tail(struct mtree_entry * parent,struct mtree_entry * child)2017 mtree_entry_add_child_tail(struct mtree_entry *parent,
2018     struct mtree_entry *child)
2019 {
2020 	child->dir_info->chnext = NULL;
2021 	*parent->dir_info->children.last = child;
2022 	parent->dir_info->children.last = &(child->dir_info->chnext);
2023 	return (1);
2024 }
2025 
2026 /*
2027  * Find a entry from a parent entry with the name.
2028  */
2029 static struct mtree_entry *
mtree_entry_find_child(struct mtree_entry * parent,const char * child_name)2030 mtree_entry_find_child(struct mtree_entry *parent, const char *child_name)
2031 {
2032 	struct mtree_entry *np;
2033 
2034 	if (parent == NULL)
2035 		return (NULL);
2036 	np = (struct mtree_entry *)__archive_rb_tree_find_node(
2037 	    &(parent->dir_info->rbtree), child_name);
2038 	return (np);
2039 }
2040 
2041 static int
get_path_component(char * name,size_t n,const char * fn)2042 get_path_component(char *name, size_t n, const char *fn)
2043 {
2044 	char *p;
2045 	size_t l;
2046 
2047 	p = strchr(fn, '/');
2048 	if (p == NULL) {
2049 		if ((l = strlen(fn)) == 0)
2050 			return (0);
2051 	} else
2052 		l = p - fn;
2053 	if (l > n -1)
2054 		return (-1);
2055 	memcpy(name, fn, l);
2056 	name[l] = '\0';
2057 
2058 	return ((int)l);
2059 }
2060 
2061 /*
2062  * Add a new entry into the tree.
2063  */
2064 static int
mtree_entry_tree_add(struct archive_write * a,struct mtree_entry ** filep)2065 mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep)
2066 {
2067 #if defined(_WIN32) && !defined(__CYGWIN__)
2068 	char name[_MAX_FNAME];/* Included null terminator size. */
2069 #elif defined(NAME_MAX) && NAME_MAX >= 255
2070 	char name[NAME_MAX+1];
2071 #else
2072 	char name[256];
2073 #endif
2074 	struct mtree_writer *mtree = (struct mtree_writer *)a->format_data;
2075 	struct mtree_entry *dent, *file, *np;
2076 	const char *fn, *p;
2077 	int l, r;
2078 
2079 	file = *filep;
2080 	if (file->parentdir.length == 0 && file->basename.length == 1 &&
2081 	    file->basename.s[0] == '.') {
2082 		file->parent = file;
2083 		if (mtree->root != NULL) {
2084 			np = mtree->root;
2085 			goto same_entry;
2086 		}
2087 		mtree->root = file;
2088 		mtree_entry_register_add(mtree, file);
2089 		return (ARCHIVE_OK);
2090 	}
2091 
2092 	if (file->parentdir.length == 0) {
2093 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2094 		    "Internal programming error "
2095 		    "in generating canonical name for %s",
2096 		    file->pathname.s);
2097 		return (ARCHIVE_FAILED);
2098 	}
2099 
2100 	fn = p = file->parentdir.s;
2101 
2102 	/*
2103 	 * If the path of the parent directory of `file' entry is
2104 	 * the same as the path of `cur_dirent', add `file' entry to
2105 	 * `cur_dirent'.
2106 	 */
2107 	if (archive_strlen(&(mtree->cur_dirstr))
2108 	      == archive_strlen(&(file->parentdir)) &&
2109 	    strcmp(mtree->cur_dirstr.s, fn) == 0) {
2110 		if (!__archive_rb_tree_insert_node(
2111 		    &(mtree->cur_dirent->dir_info->rbtree),
2112 		    (struct archive_rb_node *)file)) {
2113 			/* There is the same name in the tree. */
2114 			np = (struct mtree_entry *)__archive_rb_tree_find_node(
2115 			    &(mtree->cur_dirent->dir_info->rbtree),
2116 			    file->basename.s);
2117 			goto same_entry;
2118 		}
2119 		file->parent = mtree->cur_dirent;
2120 		mtree_entry_register_add(mtree, file);
2121 		return (ARCHIVE_OK);
2122 	}
2123 
2124 	dent = mtree->root;
2125 	for (;;) {
2126 		l = get_path_component(name, sizeof(name), fn);
2127 		if (l == 0) {
2128 			np = NULL;
2129 			break;
2130 		}
2131 		if (l < 0) {
2132 			archive_set_error(&a->archive,
2133 			    ARCHIVE_ERRNO_MISC,
2134 			    "A name buffer is too small");
2135 			return (ARCHIVE_FATAL);
2136 		}
2137 		if (l == 1 && name[0] == '.' && dent != NULL &&
2138 		    dent == mtree->root) {
2139 			fn += l;
2140 			if (fn[0] == '/')
2141 				fn++;
2142 			continue;
2143 		}
2144 
2145 		np = mtree_entry_find_child(dent, name);
2146 		if (np == NULL || fn[0] == '\0')
2147 			break;
2148 
2149 		/* Find next sub directory. */
2150 		if (!np->dir_info) {
2151 			/* NOT Directory! */
2152 			archive_set_error(&a->archive,
2153 			    ARCHIVE_ERRNO_MISC,
2154 			    "`%s' is not directory, we cannot insert `%s' ",
2155 			    np->pathname.s, file->pathname.s);
2156 			return (ARCHIVE_FAILED);
2157 		}
2158 		fn += l;
2159 		if (fn[0] == '/')
2160 			fn++;
2161 		dent = np;
2162 	}
2163 	if (np == NULL) {
2164 		/*
2165 		 * Create virtual parent directories.
2166 		 */
2167 		while (fn[0] != '\0') {
2168 			struct mtree_entry *vp;
2169 			struct archive_string as;
2170 
2171 			archive_string_init(&as);
2172 			archive_strncat(&as, p, fn - p + l);
2173 			if (as.s[as.length-1] == '/') {
2174 				as.s[as.length-1] = '\0';
2175 				as.length--;
2176 			}
2177 			r = mtree_entry_create_virtual_dir(a, as.s, &vp);
2178 			archive_string_free(&as);
2179 			if (r < ARCHIVE_WARN)
2180 				return (r);
2181 
2182 			if (strcmp(vp->pathname.s, ".") == 0) {
2183 				vp->parent = vp;
2184 				mtree->root = vp;
2185 			} else {
2186 				__archive_rb_tree_insert_node(
2187 				    &(dent->dir_info->rbtree),
2188 				    (struct archive_rb_node *)vp);
2189 				vp->parent = dent;
2190 			}
2191 			mtree_entry_register_add(mtree, vp);
2192 			np = vp;
2193 
2194 			fn += l;
2195 			if (fn[0] == '/')
2196 				fn++;
2197 			l = get_path_component(name, sizeof(name), fn);
2198 			if (l < 0) {
2199 				archive_string_free(&as);
2200 				archive_set_error(&a->archive,
2201 				    ARCHIVE_ERRNO_MISC,
2202 				    "A name buffer is too small");
2203 				return (ARCHIVE_FATAL);
2204 			}
2205 			dent = np;
2206 		}
2207 
2208 		/* Found out the parent directory where `file' can be
2209 		 * inserted. */
2210 		mtree->cur_dirent = dent;
2211 		archive_string_empty(&(mtree->cur_dirstr));
2212 		if (archive_string_ensure(&(mtree->cur_dirstr),
2213 		    archive_strlen(&(dent->parentdir)) +
2214 		    archive_strlen(&(dent->basename)) + 2) == NULL) {
2215 			archive_set_error(&a->archive, ENOMEM,
2216 			    "Can't allocate memory");
2217 			return (ARCHIVE_FATAL);
2218 		}
2219 		if (archive_strlen(&(dent->parentdir)) +
2220 		    archive_strlen(&(dent->basename)) == 0)
2221 			mtree->cur_dirstr.s[0] = 0;
2222 		else {
2223 			if (archive_strlen(&(dent->parentdir)) > 0) {
2224 				archive_string_copy(&(mtree->cur_dirstr),
2225 				    &(dent->parentdir));
2226 				archive_strappend_char(
2227 				    &(mtree->cur_dirstr), '/');
2228 			}
2229 			archive_string_concat(&(mtree->cur_dirstr),
2230 			    &(dent->basename));
2231 		}
2232 
2233 		if (!__archive_rb_tree_insert_node(
2234 		    &(dent->dir_info->rbtree),
2235 		    (struct archive_rb_node *)file)) {
2236 			np = (struct mtree_entry *)__archive_rb_tree_find_node(
2237 			    &(dent->dir_info->rbtree), file->basename.s);
2238 			goto same_entry;
2239 		}
2240 		file->parent = dent;
2241 		mtree_entry_register_add(mtree, file);
2242 		return (ARCHIVE_OK);
2243 	}
2244 
2245 same_entry:
2246 	/*
2247 	 * We have already has the entry the filename of which is
2248 	 * the same.
2249 	 */
2250 	r = mtree_entry_exchange_same_entry(a, np, file);
2251 	if (r < ARCHIVE_WARN)
2252 		return (r);
2253 	if (np->dir_info)
2254 		np->dir_info->virtual = 0;
2255 	*filep = np;
2256 	mtree_entry_free(file);
2257 	return (ARCHIVE_WARN);
2258 }
2259 
2260 static int
mtree_entry_exchange_same_entry(struct archive_write * a,struct mtree_entry * np,struct mtree_entry * file)2261 mtree_entry_exchange_same_entry(struct archive_write *a, struct mtree_entry *np,
2262     struct mtree_entry *file)
2263 {
2264 
2265 	if ((np->mode & AE_IFMT) != (file->mode & AE_IFMT)) {
2266 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2267 		    "Found duplicate entries `%s' and its file type is "
2268 		    "different",
2269 		    np->pathname.s);
2270 		return (ARCHIVE_FAILED);
2271 	}
2272 
2273 	/* Update the existent mtree entry's attributes by the new one's. */
2274 	archive_string_empty(&np->symlink);
2275 	archive_string_concat(&np->symlink, &file->symlink);
2276 	archive_string_empty(&np->uname);
2277 	archive_string_concat(&np->uname, &file->uname);
2278 	archive_string_empty(&np->gname);
2279 	archive_string_concat(&np->gname, &file->gname);
2280 	archive_string_empty(&np->fflags_text);
2281 	archive_string_concat(&np->fflags_text, &file->fflags_text);
2282 	np->nlink = file->nlink;
2283 	np->filetype = file->filetype;
2284 	np->mode = file->mode;
2285 	np->size = file->size;
2286 	np->uid = file->uid;
2287 	np->gid = file->gid;
2288 	np->fflags_set = file->fflags_set;
2289 	np->fflags_clear = file->fflags_clear;
2290 	np->mtime = file->mtime;
2291 	np->mtime_nsec = file->mtime_nsec;
2292 	np->rdevmajor = file->rdevmajor;
2293 	np->rdevminor = file->rdevminor;
2294 	np->devmajor = file->devmajor;
2295 	np->devminor = file->devminor;
2296 	np->ino = file->ino;
2297 
2298 	return (ARCHIVE_WARN);
2299 }
2300