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