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(®->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(®->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(®->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(®->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(®->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(®->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