2 * Copyright (c) 2008 Joerg Sonnenberger
3 * Copyright (c) 2009-2012 Michihiro NAKAJIMA
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
27 #include "archive_platform.h"
28 __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_mtree.c 201171 2009-12-29 06:39:07Z kientzle $");
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
38 #include "archive_crypto_private.h"
39 #include "archive_entry.h"
40 #include "archive_private.h"
41 #include "archive_rb.h"
42 #include "archive_string.h"
43 #include "archive_write_private.h"
45 #define INDENTNAMELEN 15
48 (F_FLAGS | F_GID | F_GNAME | F_MODE | F_TYPE | F_UID | F_UNAME)
51 struct attr_counter *prev;
52 struct attr_counter *next;
53 struct mtree_entry *m_entry;
57 struct att_counter_set {
58 struct attr_counter *uid_list;
59 struct attr_counter *gid_list;
60 struct attr_counter *mode_list;
61 struct attr_counter *flags_list;
65 struct mtree_entry *first;
66 struct mtree_entry **last;
70 * The Data only for a directory file.
73 struct archive_rb_tree rbtree;
74 struct mtree_chain children;
75 struct mtree_entry *chnext;
80 * The Data only for a regular file.
85 #ifdef ARCHIVE_HAS_MD5
86 unsigned char buf_md5[16];
88 #ifdef ARCHIVE_HAS_RMD160
89 unsigned char buf_rmd160[20];
91 #ifdef ARCHIVE_HAS_SHA1
92 unsigned char buf_sha1[20];
94 #ifdef ARCHIVE_HAS_SHA256
95 unsigned char buf_sha256[32];
97 #ifdef ARCHIVE_HAS_SHA384
98 unsigned char buf_sha384[48];
100 #ifdef ARCHIVE_HAS_SHA512
101 unsigned char buf_sha512[64];
106 struct archive_rb_node rbnode;
107 struct mtree_entry *next;
108 struct mtree_entry *parent;
109 struct dir_info *dir_info;
110 struct reg_info *reg_info;
112 struct archive_string parentdir;
113 struct archive_string basename;
114 struct archive_string pathname;
115 struct archive_string symlink;
116 struct archive_string uname;
117 struct archive_string gname;
118 struct archive_string fflags_text;
127 unsigned long fflags_set;
128 unsigned long fflags_clear;
133 struct mtree_writer {
134 struct mtree_entry *mtree_entry;
135 struct mtree_entry *root;
136 struct mtree_entry *cur_dirent;
137 struct archive_string cur_dirstr;
138 struct mtree_chain file_list;
140 struct archive_string ebuf;
141 struct archive_string buf;
143 uint64_t entry_bytes_remaining;
155 unsigned long fflags_set;
156 unsigned long fflags_clear;
158 struct att_counter_set acs;
166 #ifdef ARCHIVE_HAS_MD5
167 archive_md5_ctx md5ctx;
169 #ifdef ARCHIVE_HAS_RMD160
170 archive_rmd160_ctx rmd160ctx;
172 #ifdef ARCHIVE_HAS_SHA1
173 archive_sha1_ctx sha1ctx;
175 #ifdef ARCHIVE_HAS_SHA256
176 archive_sha256_ctx sha256ctx;
178 #ifdef ARCHIVE_HAS_SHA384
179 archive_sha384_ctx sha384ctx;
181 #ifdef ARCHIVE_HAS_SHA512
182 archive_sha512_ctx sha512ctx;
184 /* Keyword options */
186 #define F_CKSUM 0x00000001 /* check sum */
187 #define F_DEV 0x00000002 /* device type */
188 #define F_DONE 0x00000004 /* directory done */
189 #define F_FLAGS 0x00000008 /* file flags */
190 #define F_GID 0x00000010 /* gid */
191 #define F_GNAME 0x00000020 /* group name */
192 #define F_IGN 0x00000040 /* ignore */
193 #define F_MAGIC 0x00000080 /* name has magic chars */
194 #define F_MD5 0x00000100 /* MD5 digest */
195 #define F_MODE 0x00000200 /* mode */
196 #define F_NLINK 0x00000400 /* number of links */
197 #define F_NOCHANGE 0x00000800 /* If owner/mode "wrong", do
199 #define F_OPT 0x00001000 /* existence optional */
200 #define F_RMD160 0x00002000 /* RIPEMD160 digest */
201 #define F_SHA1 0x00004000 /* SHA-1 digest */
202 #define F_SIZE 0x00008000 /* size */
203 #define F_SLINK 0x00010000 /* symbolic link */
204 #define F_TAGS 0x00020000 /* tags */
205 #define F_TIME 0x00040000 /* modification time */
206 #define F_TYPE 0x00080000 /* file type */
207 #define F_UID 0x00100000 /* uid */
208 #define F_UNAME 0x00200000 /* user name */
209 #define F_VISIT 0x00400000 /* file visited */
210 #define F_SHA256 0x00800000 /* SHA-256 digest */
211 #define F_SHA384 0x01000000 /* SHA-384 digest */
212 #define F_SHA512 0x02000000 /* SHA-512 digest */
215 int dironly; /* If it is set, ignore all files except
216 * directory files, like mtree(8) -d option. */
217 int indent; /* If it is set, indent output data. */
218 int output_global_set; /* If it is set, use /set keyword to set
219 * global values. When generating mtree
220 * classic format, it is set by default. */
223 #define DEFAULT_KEYS (F_DEV | F_FLAGS | F_GID | F_GNAME | F_SLINK | F_MODE\
224 | F_NLINK | F_SIZE | F_TIME | F_TYPE | F_UID\
226 #define attr_counter_set_reset attr_counter_set_free
228 static void attr_counter_free(struct attr_counter **);
229 static int attr_counter_inc(struct attr_counter **, struct attr_counter *,
230 struct attr_counter *, struct mtree_entry *);
231 static struct attr_counter * attr_counter_new(struct mtree_entry *,
232 struct attr_counter *);
233 static int attr_counter_set_collect(struct mtree_writer *,
234 struct mtree_entry *);
235 static void attr_counter_set_free(struct mtree_writer *);
236 static int get_global_set_keys(struct mtree_writer *, struct mtree_entry *);
237 static int mtree_entry_add_child_tail(struct mtree_entry *,
238 struct mtree_entry *);
239 static int mtree_entry_create_virtual_dir(struct archive_write *, const char *,
240 struct mtree_entry **);
241 static int mtree_entry_cmp_node(const struct archive_rb_node *,
242 const struct archive_rb_node *);
243 static int mtree_entry_cmp_key(const struct archive_rb_node *, const void *);
244 static int mtree_entry_exchange_same_entry(struct archive_write *,
245 struct mtree_entry *, struct mtree_entry *);
246 static void mtree_entry_free(struct mtree_entry *);
247 static int mtree_entry_new(struct archive_write *, struct archive_entry *,
248 struct mtree_entry **);
249 static void mtree_entry_register_free(struct mtree_writer *);
250 static void mtree_entry_register_init(struct mtree_writer *);
251 static int mtree_entry_setup_filenames(struct archive_write *,
252 struct mtree_entry *, struct archive_entry *);
253 static int mtree_entry_tree_add(struct archive_write *, struct mtree_entry **);
254 static void sum_init(struct mtree_writer *);
255 static void sum_update(struct mtree_writer *, const void *, size_t);
256 static void sum_final(struct mtree_writer *, struct reg_info *);
257 static void sum_write(struct archive_string *, struct reg_info *);
258 static int write_mtree_entry(struct archive_write *, struct mtree_entry *);
259 static int write_dot_dot_entry(struct archive_write *, struct mtree_entry *);
261 #define COMPUTE_CRC(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
262 static const uint32_t crctab[] = {
264 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
265 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
266 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
267 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
268 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
269 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
270 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
271 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
272 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
273 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
274 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
275 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
276 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
277 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
278 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
279 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
280 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
281 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
282 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
283 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
284 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
285 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
286 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
287 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
288 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
289 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
290 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
291 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
292 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
293 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
294 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
295 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
296 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
297 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
298 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
299 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
300 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
301 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
302 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
303 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
304 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
305 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
306 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
307 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
308 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
309 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
310 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
311 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
312 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
313 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
314 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
317 static const unsigned char safe_char[256] = {
318 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */
319 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
320 /* !"$%&'()*+,-./ EXCLUSION:0x20( ) 0x23(#) */
321 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
322 /* 0123456789:;<>? EXCLUSION:0x3d(=) */
323 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, /* 30 - 3F */
324 /* @ABCDEFGHIJKLMNO */
325 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
326 /* PQRSTUVWXYZ[]^_ EXCLUSION:0x5c(\) */
327 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, /* 50 - 5F */
328 /* `abcdefghijklmno */
329 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
330 /* pqrstuvwxyz{|}~ */
331 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */
332 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
333 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
334 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
335 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
336 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
337 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
338 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
339 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
343 mtree_quote(struct archive_string *s, const char *str)
349 for (start = str; *str != '\0'; ++str) {
350 if (safe_char[*(const unsigned char *)str])
353 archive_strncat(s, start, str - start);
354 c = (unsigned char)*str;
356 buf[1] = (c / 64) + '0';
357 buf[2] = (c / 8 % 8) + '0';
358 buf[3] = (c % 8) + '0';
359 archive_strncat(s, buf, 4);
364 archive_strncat(s, start, str - start);
368 * Indent a line as mtree utility to be readable for people.
371 mtree_indent(struct mtree_writer *mtree)
374 const char *r, *s, *x;
376 if (mtree->classic) {
379 pd = mtree->depth * 4;
381 nd = mtree->depth?4:0;
387 s = r = mtree->ebuf.s;
391 while ((r = strchr(r, ' ')) != NULL) {
394 for (i = 0; i < nd + pd; i++)
395 archive_strappend_char(&mtree->buf, ' ');
396 archive_strncat(&mtree->buf, s, r - s);
397 if (nd + (r -s) > INDENTNAMELEN) {
398 archive_strncat(&mtree->buf, " \\\n", 3);
399 for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++)
400 archive_strappend_char(&mtree->buf, ' ');
402 for (i = (int)(r -s + nd);
403 i < (INDENTNAMELEN + 1); i++)
404 archive_strappend_char(&mtree->buf, ' ');
410 if (pd + (r - s) <= MAXLINELEN - 3 - INDENTNAMELEN)
415 archive_strncat(&mtree->buf, s, x - s);
416 archive_strncat(&mtree->buf, " \\\n", 3);
417 for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++)
418 archive_strappend_char(&mtree->buf, ' ');
424 for (i = 0; i < nd + pd; i++)
425 archive_strappend_char(&mtree->buf, ' ');
426 archive_strcat(&mtree->buf, s);
429 if (x != NULL && pd + strlen(s) > MAXLINELEN - 3 - INDENTNAMELEN) {
430 /* Last keyword is longer. */
431 archive_strncat(&mtree->buf, s, x - s);
432 archive_strncat(&mtree->buf, " \\\n", 3);
433 for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++)
434 archive_strappend_char(&mtree->buf, ' ');
437 archive_strcat(&mtree->buf, s);
438 archive_string_empty(&mtree->ebuf);
442 * Write /set keyword.
443 * Set most used value of uid,gid,mode and fflags, which are
444 * collected by attr_counter_set_collect() function.
447 write_global(struct mtree_writer *mtree)
449 struct archive_string setstr;
450 struct archive_string unsetstr;
451 struct att_counter_set *acs;
452 int keys, oldkeys, effkeys;
454 archive_string_init(&setstr);
455 archive_string_init(&unsetstr);
456 keys = mtree->keys & SET_KEYS;
457 oldkeys = mtree->set.keys;
460 if (mtree->set.processing) {
462 * Check if the global data needs updating.
465 if (acs->uid_list == NULL)
466 effkeys &= ~(F_UNAME | F_UID);
467 else if (oldkeys & (F_UNAME | F_UID)) {
468 if (acs->uid_list->count < 2 ||
469 mtree->set.uid == acs->uid_list->m_entry->uid)
470 effkeys &= ~(F_UNAME | F_UID);
472 if (acs->gid_list == NULL)
473 effkeys &= ~(F_GNAME | F_GID);
474 else if (oldkeys & (F_GNAME | F_GID)) {
475 if (acs->gid_list->count < 2 ||
476 mtree->set.gid == acs->gid_list->m_entry->gid)
477 effkeys &= ~(F_GNAME | F_GID);
479 if (acs->mode_list == NULL)
481 else if (oldkeys & F_MODE) {
482 if (acs->mode_list->count < 2 ||
483 mtree->set.mode == acs->mode_list->m_entry->mode)
486 if (acs->flags_list == NULL)
488 else if ((oldkeys & F_FLAGS) != 0) {
489 if (acs->flags_list->count < 2 ||
490 (acs->flags_list->m_entry->fflags_set ==
491 mtree->set.fflags_set &&
492 acs->flags_list->m_entry->fflags_clear ==
493 mtree->set.fflags_clear))
497 if (acs->uid_list == NULL)
498 keys &= ~(F_UNAME | F_UID);
499 if (acs->gid_list == NULL)
500 keys &= ~(F_GNAME | F_GID);
501 if (acs->mode_list == NULL)
503 if (acs->flags_list == NULL)
506 if ((keys & effkeys & F_TYPE) != 0) {
507 if (mtree->dironly) {
508 archive_strcat(&setstr, " type=dir");
509 mtree->set.type = AE_IFDIR;
511 archive_strcat(&setstr, " type=file");
512 mtree->set.type = AE_IFREG;
515 if ((keys & effkeys & F_UNAME) != 0) {
516 if (archive_strlen(&(acs->uid_list->m_entry->uname)) > 0) {
517 archive_strcat(&setstr, " uname=");
518 mtree_quote(&setstr, acs->uid_list->m_entry->uname.s);
521 if ((oldkeys & F_UNAME) != 0)
522 archive_strcat(&unsetstr, " uname");
525 if ((keys & effkeys & F_UID) != 0) {
526 mtree->set.uid = acs->uid_list->m_entry->uid;
527 archive_string_sprintf(&setstr, " uid=%jd",
528 (intmax_t)mtree->set.uid);
530 if ((keys & effkeys & F_GNAME) != 0) {
531 if (archive_strlen(&(acs->gid_list->m_entry->gname)) > 0) {
532 archive_strcat(&setstr, " gname=");
533 mtree_quote(&setstr, acs->gid_list->m_entry->gname.s);
536 if ((oldkeys & F_GNAME) != 0)
537 archive_strcat(&unsetstr, " gname");
540 if ((keys & effkeys & F_GID) != 0) {
541 mtree->set.gid = acs->gid_list->m_entry->gid;
542 archive_string_sprintf(&setstr, " gid=%jd",
543 (intmax_t)mtree->set.gid);
545 if ((keys & effkeys & F_MODE) != 0) {
546 mtree->set.mode = acs->mode_list->m_entry->mode;
547 archive_string_sprintf(&setstr, " mode=%o",
548 (unsigned int)mtree->set.mode);
550 if ((keys & effkeys & F_FLAGS) != 0) {
552 &(acs->flags_list->m_entry->fflags_text)) > 0) {
553 archive_strcat(&setstr, " flags=");
555 acs->flags_list->m_entry->fflags_text.s);
556 mtree->set.fflags_set =
557 acs->flags_list->m_entry->fflags_set;
558 mtree->set.fflags_clear =
559 acs->flags_list->m_entry->fflags_clear;
562 if ((oldkeys & F_FLAGS) != 0)
563 archive_strcat(&unsetstr, " flags");
566 if (unsetstr.length > 0)
567 archive_string_sprintf(&mtree->buf, "/unset%s\n", unsetstr.s);
568 archive_string_free(&unsetstr);
569 if (setstr.length > 0)
570 archive_string_sprintf(&mtree->buf, "/set%s\n", setstr.s);
571 archive_string_free(&setstr);
572 mtree->set.keys = keys;
573 mtree->set.processing = 1;
576 static struct attr_counter *
577 attr_counter_new(struct mtree_entry *me, struct attr_counter *prev)
579 struct attr_counter *ac;
581 ac = malloc(sizeof(*ac));
592 attr_counter_free(struct attr_counter **top)
594 struct attr_counter *ac, *tac;
608 attr_counter_inc(struct attr_counter **top, struct attr_counter *ac,
609 struct attr_counter *last, struct mtree_entry *me)
611 struct attr_counter *pac;
615 if (*top == ac || ac->prev->count >= ac->count)
617 for (pac = ac->prev; pac; pac = pac->prev) {
618 if (pac->count >= ac->count)
621 ac->prev->next = ac->next;
622 if (ac->next != NULL)
623 ac->next->prev = ac->prev;
626 ac->next = pac->next;
628 if (ac->next != NULL)
637 ac = attr_counter_new(me, last);
646 * Tabulate uid,gid,mode and fflags of a entry in order to be used for /set.
649 attr_counter_set_collect(struct mtree_writer *mtree, struct mtree_entry *me)
651 struct attr_counter *ac, *last;
652 struct att_counter_set *acs = &mtree->acs;
653 int keys = mtree->keys;
655 if (keys & (F_UNAME | F_UID)) {
656 if (acs->uid_list == NULL) {
657 acs->uid_list = attr_counter_new(me, NULL);
658 if (acs->uid_list == NULL)
662 for (ac = acs->uid_list; ac; ac = ac->next) {
663 if (ac->m_entry->uid == me->uid)
667 if (attr_counter_inc(&acs->uid_list, ac, last, me) < 0)
671 if (keys & (F_GNAME | F_GID)) {
672 if (acs->gid_list == NULL) {
673 acs->gid_list = attr_counter_new(me, NULL);
674 if (acs->gid_list == NULL)
678 for (ac = acs->gid_list; ac; ac = ac->next) {
679 if (ac->m_entry->gid == me->gid)
683 if (attr_counter_inc(&acs->gid_list, ac, last, me) < 0)
688 if (acs->mode_list == NULL) {
689 acs->mode_list = attr_counter_new(me, NULL);
690 if (acs->mode_list == NULL)
694 for (ac = acs->mode_list; ac; ac = ac->next) {
695 if (ac->m_entry->mode == me->mode)
699 if (attr_counter_inc(&acs->mode_list, ac, last, me) < 0)
703 if (keys & F_FLAGS) {
704 if (acs->flags_list == NULL) {
705 acs->flags_list = attr_counter_new(me, NULL);
706 if (acs->flags_list == NULL)
710 for (ac = acs->flags_list; ac; ac = ac->next) {
711 if (ac->m_entry->fflags_set == me->fflags_set &&
712 ac->m_entry->fflags_clear ==
717 if (attr_counter_inc(&acs->flags_list, ac, last, me) < 0)
726 attr_counter_set_free(struct mtree_writer *mtree)
728 struct att_counter_set *acs = &mtree->acs;
730 attr_counter_free(&acs->uid_list);
731 attr_counter_free(&acs->gid_list);
732 attr_counter_free(&acs->mode_list);
733 attr_counter_free(&acs->flags_list);
737 get_global_set_keys(struct mtree_writer *mtree, struct mtree_entry *me)
744 * If a keyword has been set by /set, we do not need to
747 if (mtree->set.keys == 0)
748 return (keys);/* /set is not used. */
750 if ((mtree->set.keys & (F_GNAME | F_GID)) != 0 &&
751 mtree->set.gid == me->gid)
752 keys &= ~(F_GNAME | F_GID);
753 if ((mtree->set.keys & (F_UNAME | F_UID)) != 0 &&
754 mtree->set.uid == me->uid)
755 keys &= ~(F_UNAME | F_UID);
756 if (mtree->set.keys & F_FLAGS) {
757 if (mtree->set.fflags_set == me->fflags_set &&
758 mtree->set.fflags_clear == me->fflags_clear)
761 if ((mtree->set.keys & F_MODE) != 0 && mtree->set.mode == me->mode)
764 switch (me->filetype) {
765 case AE_IFLNK: case AE_IFSOCK: case AE_IFCHR:
766 case AE_IFBLK: case AE_IFIFO:
769 if ((mtree->set.keys & F_TYPE) != 0 &&
770 mtree->set.type == AE_IFDIR)
774 default: /* Handle unknown file types as regular files. */
775 if ((mtree->set.keys & F_TYPE) != 0 &&
776 mtree->set.type == AE_IFREG)
785 mtree_entry_new(struct archive_write *a, struct archive_entry *entry,
786 struct mtree_entry **m_entry)
788 struct mtree_entry *me;
791 static const struct archive_rb_tree_ops rb_ops = {
792 mtree_entry_cmp_node, mtree_entry_cmp_key
795 me = calloc(1, sizeof(*me));
797 archive_set_error(&a->archive, ENOMEM,
798 "Can't allocate memory for a mtree entry");
800 return (ARCHIVE_FATAL);
803 r = mtree_entry_setup_filenames(a, me, entry);
804 if (r < ARCHIVE_WARN) {
805 mtree_entry_free(me);
810 if ((s = archive_entry_symlink(entry)) != NULL)
811 archive_strcpy(&me->symlink, s);
812 me->nlink = archive_entry_nlink(entry);
813 me->filetype = archive_entry_filetype(entry);
814 me->mode = archive_entry_mode(entry) & 07777;
815 me->uid = archive_entry_uid(entry);
816 me->gid = archive_entry_gid(entry);
817 if ((s = archive_entry_uname(entry)) != NULL)
818 archive_strcpy(&me->uname, s);
819 if ((s = archive_entry_gname(entry)) != NULL)
820 archive_strcpy(&me->gname, s);
821 if ((s = archive_entry_fflags_text(entry)) != NULL)
822 archive_strcpy(&me->fflags_text, s);
823 archive_entry_fflags(entry, &me->fflags_set, &me->fflags_clear);
824 me->mtime = archive_entry_mtime(entry);
825 me->mtime_nsec = archive_entry_mtime_nsec(entry);
826 me->rdevmajor = archive_entry_rdevmajor(entry);
827 me->rdevminor = archive_entry_rdevminor(entry);
828 me->size = archive_entry_size(entry);
829 if (me->filetype == AE_IFDIR) {
830 me->dir_info = calloc(1, sizeof(*me->dir_info));
831 if (me->dir_info == NULL) {
832 mtree_entry_free(me);
833 archive_set_error(&a->archive, ENOMEM,
834 "Can't allocate memory for a mtree entry");
836 return (ARCHIVE_FATAL);
838 __archive_rb_tree_init(&me->dir_info->rbtree, &rb_ops);
839 me->dir_info->children.first = NULL;
840 me->dir_info->children.last = &(me->dir_info->children.first);
841 me->dir_info->chnext = NULL;
842 } else if (me->filetype == AE_IFREG) {
843 me->reg_info = calloc(1, sizeof(*me->reg_info));
844 if (me->reg_info == NULL) {
845 mtree_entry_free(me);
846 archive_set_error(&a->archive, ENOMEM,
847 "Can't allocate memory for a mtree entry");
849 return (ARCHIVE_FATAL);
851 me->reg_info->compute_sum = 0;
859 mtree_entry_free(struct mtree_entry *me)
861 archive_string_free(&me->parentdir);
862 archive_string_free(&me->basename);
863 archive_string_free(&me->pathname);
864 archive_string_free(&me->symlink);
865 archive_string_free(&me->uname);
866 archive_string_free(&me->gname);
867 archive_string_free(&me->fflags_text);
874 archive_write_mtree_header(struct archive_write *a,
875 struct archive_entry *entry)
877 struct mtree_writer *mtree= a->format_data;
878 struct mtree_entry *mtree_entry;
883 archive_strcat(&mtree->buf, "#mtree\n");
884 if ((mtree->keys & SET_KEYS) == 0)
885 mtree->output_global_set = 0;/* Disalbed. */
888 mtree->entry_bytes_remaining = archive_entry_size(entry);
890 /* While directory only mode, we do not handle non directory files. */
891 if (mtree->dironly && archive_entry_filetype(entry) != AE_IFDIR)
894 r2 = mtree_entry_new(a, entry, &mtree_entry);
895 if (r2 < ARCHIVE_WARN)
897 r = mtree_entry_tree_add(a, &mtree_entry);
898 if (r < ARCHIVE_WARN) {
899 mtree_entry_free(mtree_entry);
902 mtree->mtree_entry = mtree_entry;
904 /* If the current file is a regular file, we have to
905 * compute the sum of its content.
906 * Initialize a bunch of sum check context. */
907 if (mtree_entry->reg_info)
914 write_mtree_entry(struct archive_write *a, struct mtree_entry *me)
916 struct mtree_writer *mtree = a->format_data;
917 struct archive_string *str;
921 if (mtree->classic) {
923 * Output a comment line to describe the full
924 * pathname of the entry as mtree utility does
925 * while generating classic format.
928 archive_strappend_char(&mtree->buf, '\n');
930 archive_string_sprintf(&mtree->buf,
932 me->parentdir.s, me->basename.s);
934 archive_string_sprintf(&mtree->buf,
938 if (mtree->output_global_set)
941 archive_string_empty(&mtree->ebuf);
942 str = (mtree->indent || mtree->classic)? &mtree->ebuf : &mtree->buf;
944 if (!mtree->classic && me->parentdir.s) {
946 * If generating format is not classic one(v1), output
949 mtree_quote(str, me->parentdir.s);
950 archive_strappend_char(str, '/');
952 mtree_quote(str, me->basename.s);
954 keys = get_global_set_keys(mtree, me);
955 if ((keys & F_NLINK) != 0 &&
956 me->nlink != 1 && me->filetype != AE_IFDIR)
957 archive_string_sprintf(str, " nlink=%u", me->nlink);
959 if ((keys & F_GNAME) != 0 && archive_strlen(&me->gname) > 0) {
960 archive_strcat(str, " gname=");
961 mtree_quote(str, me->gname.s);
963 if ((keys & F_UNAME) != 0 && archive_strlen(&me->uname) > 0) {
964 archive_strcat(str, " uname=");
965 mtree_quote(str, me->uname.s);
967 if ((keys & F_FLAGS) != 0) {
968 if (archive_strlen(&me->fflags_text) > 0) {
969 archive_strcat(str, " flags=");
970 mtree_quote(str, me->fflags_text.s);
971 } else if (mtree->set.processing &&
972 (mtree->set.keys & F_FLAGS) != 0)
973 /* Overwrite the global parameter. */
974 archive_strcat(str, " flags=none");
976 if ((keys & F_TIME) != 0)
977 archive_string_sprintf(str, " time=%jd.%jd",
978 (intmax_t)me->mtime, (intmax_t)me->mtime_nsec);
979 if ((keys & F_MODE) != 0)
980 archive_string_sprintf(str, " mode=%o", (unsigned int)me->mode);
981 if ((keys & F_GID) != 0)
982 archive_string_sprintf(str, " gid=%jd", (intmax_t)me->gid);
983 if ((keys & F_UID) != 0)
984 archive_string_sprintf(str, " uid=%jd", (intmax_t)me->uid);
986 switch (me->filetype) {
988 if ((keys & F_TYPE) != 0)
989 archive_strcat(str, " type=link");
990 if ((keys & F_SLINK) != 0) {
991 archive_strcat(str, " link=");
992 mtree_quote(str, me->symlink.s);
996 if ((keys & F_TYPE) != 0)
997 archive_strcat(str, " type=socket");
1000 if ((keys & F_TYPE) != 0)
1001 archive_strcat(str, " type=char");
1002 if ((keys & F_DEV) != 0) {
1003 archive_string_sprintf(str,
1004 " device=native,%ju,%ju",
1005 (uintmax_t)me->rdevmajor,
1006 (uintmax_t)me->rdevminor);
1010 if ((keys & F_TYPE) != 0)
1011 archive_strcat(str, " type=block");
1012 if ((keys & F_DEV) != 0) {
1013 archive_string_sprintf(str,
1014 " device=native,%ju,%ju",
1015 (uintmax_t)me->rdevmajor,
1016 (uintmax_t)me->rdevminor);
1020 if ((keys & F_TYPE) != 0)
1021 archive_strcat(str, " type=dir");
1024 if ((keys & F_TYPE) != 0)
1025 archive_strcat(str, " type=fifo");
1028 default: /* Handle unknown file types as regular files. */
1029 if ((keys & F_TYPE) != 0)
1030 archive_strcat(str, " type=file");
1031 if ((keys & F_SIZE) != 0)
1032 archive_string_sprintf(str, " size=%jd",
1033 (intmax_t)me->size);
1037 /* Write a bunch of sum. */
1039 sum_write(str, me->reg_info);
1041 archive_strappend_char(str, '\n');
1042 if (mtree->indent || mtree->classic)
1043 mtree_indent(mtree);
1045 if (mtree->buf.length > 32768) {
1046 ret = __archive_write_output(
1047 a, mtree->buf.s, mtree->buf.length);
1048 archive_string_empty(&mtree->buf);
1055 write_dot_dot_entry(struct archive_write *a, struct mtree_entry *n)
1057 struct mtree_writer *mtree = a->format_data;
1060 if (n->parentdir.s) {
1061 if (mtree->indent) {
1062 int i, pd = mtree->depth * 4;
1063 for (i = 0; i < pd; i++)
1064 archive_strappend_char(&mtree->buf, ' ');
1066 archive_string_sprintf(&mtree->buf, "# %s/%s\n",
1067 n->parentdir.s, n->basename.s);
1070 if (mtree->indent) {
1071 archive_string_empty(&mtree->ebuf);
1072 archive_strncat(&mtree->ebuf, "..\n\n", (mtree->dironly)?3:4);
1073 mtree_indent(mtree);
1075 archive_strncat(&mtree->buf, "..\n\n", (mtree->dironly)?3:4);
1077 if (mtree->buf.length > 32768) {
1078 ret = __archive_write_output(
1079 a, mtree->buf.s, mtree->buf.length);
1080 archive_string_empty(&mtree->buf);
1087 * Write mtree entries saved at attr_counter_set_collect() function.
1090 write_mtree_entry_tree(struct archive_write *a)
1092 struct mtree_writer *mtree = a->format_data;
1093 struct mtree_entry *np = mtree->root;
1094 struct archive_rb_node *n;
1098 if (mtree->output_global_set) {
1100 * Collect attribute infomation to know which value
1101 * is frequently used among the children.
1103 attr_counter_set_reset(mtree);
1104 ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) {
1105 struct mtree_entry *e = (struct mtree_entry *)n;
1106 if (attr_counter_set_collect(mtree, e) < 0) {
1107 archive_set_error(&a->archive, ENOMEM,
1108 "Can't allocate memory");
1109 return (ARCHIVE_FATAL);
1113 if (!np->dir_info->virtual || mtree->classic) {
1114 ret = write_mtree_entry(a, np);
1115 if (ret != ARCHIVE_OK)
1116 return (ARCHIVE_FATAL);
1118 /* Whenever output_global_set is enabled
1119 * output global value(/set keywords)
1120 * even if the directory entry is not allowd
1121 * to be written because the global values
1122 * can be used for the children. */
1123 if (mtree->output_global_set)
1124 write_global(mtree);
1127 * Output the attribute of all files except directory files.
1130 ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) {
1131 struct mtree_entry *e = (struct mtree_entry *)n;
1134 mtree_entry_add_child_tail(np, e);
1136 ret = write_mtree_entry(a, e);
1137 if (ret != ARCHIVE_OK)
1138 return (ARCHIVE_FATAL);
1143 if (np->dir_info->children.first != NULL) {
1147 np = np->dir_info->children.first;
1151 } else if (mtree->classic) {
1153 * While printing mtree classic, if there are not
1154 * any directory files(except "." and "..") in the
1155 * directory, output two dots ".." as returning
1156 * the parent directory.
1158 ret = write_dot_dot_entry(a, np);
1159 if (ret != ARCHIVE_OK)
1160 return (ARCHIVE_FATAL);
1163 while (np != np->parent) {
1164 if (np->dir_info->chnext == NULL) {
1166 * Ascend the tree; go back to the parent.
1170 if (mtree->classic) {
1171 ret = write_dot_dot_entry(a,
1173 if (ret != ARCHIVE_OK)
1174 return (ARCHIVE_FATAL);
1179 * Switch to next mtree entry in the directory.
1181 np = np->dir_info->chnext;
1185 } while (np != np->parent);
1187 return (ARCHIVE_OK);
1191 archive_write_mtree_finish_entry(struct archive_write *a)
1193 struct mtree_writer *mtree = a->format_data;
1194 struct mtree_entry *me;
1196 if ((me = mtree->mtree_entry) == NULL)
1197 return (ARCHIVE_OK);
1198 mtree->mtree_entry = NULL;
1201 sum_final(mtree, me->reg_info);
1203 return (ARCHIVE_OK);
1207 archive_write_mtree_close(struct archive_write *a)
1209 struct mtree_writer *mtree= a->format_data;
1212 if (mtree->root != NULL) {
1213 ret = write_mtree_entry_tree(a);
1214 if (ret != ARCHIVE_OK)
1215 return (ARCHIVE_FATAL);
1218 archive_write_set_bytes_in_last_block(&a->archive, 1);
1220 return __archive_write_output(a, mtree->buf.s, mtree->buf.length);
1224 archive_write_mtree_data(struct archive_write *a, const void *buff, size_t n)
1226 struct mtree_writer *mtree= a->format_data;
1228 if (n > mtree->entry_bytes_remaining)
1229 n = (size_t)mtree->entry_bytes_remaining;
1230 mtree->entry_bytes_remaining -= n;
1232 /* We don't need to compute a regular file sum */
1233 if (mtree->mtree_entry == NULL)
1236 if (mtree->mtree_entry->filetype == AE_IFREG)
1237 sum_update(mtree, buff, n);
1243 archive_write_mtree_free(struct archive_write *a)
1245 struct mtree_writer *mtree= a->format_data;
1248 return (ARCHIVE_OK);
1250 /* Make sure we dot not leave any entries. */
1251 mtree_entry_register_free(mtree);
1252 archive_string_free(&mtree->cur_dirstr);
1253 archive_string_free(&mtree->ebuf);
1254 archive_string_free(&mtree->buf);
1255 attr_counter_set_free(mtree);
1257 a->format_data = NULL;
1258 return (ARCHIVE_OK);
1262 archive_write_mtree_options(struct archive_write *a, const char *key,
1265 struct mtree_writer *mtree= a->format_data;
1270 if (strcmp(key, "all") == 0)
1274 if (strcmp(key, "cksum") == 0)
1278 if (strcmp(key, "device") == 0)
1280 else if (strcmp(key, "dironly") == 0) {
1281 mtree->dironly = (value != NULL)? 1: 0;
1282 return (ARCHIVE_OK);
1286 if (strcmp(key, "flags") == 0)
1290 if (strcmp(key, "gid") == 0)
1292 else if (strcmp(key, "gname") == 0)
1296 if (strcmp(key, "indent") == 0) {
1297 mtree->indent = (value != NULL)? 1: 0;
1298 return (ARCHIVE_OK);
1302 if (strcmp(key, "link") == 0)
1306 if (strcmp(key, "md5") == 0 ||
1307 strcmp(key, "md5digest") == 0)
1309 if (strcmp(key, "mode") == 0)
1313 if (strcmp(key, "nlink") == 0)
1317 if (strcmp(key, "ripemd160digest") == 0 ||
1318 strcmp(key, "rmd160") == 0 ||
1319 strcmp(key, "rmd160digest") == 0)
1323 if (strcmp(key, "sha1") == 0 ||
1324 strcmp(key, "sha1digest") == 0)
1326 if (strcmp(key, "sha256") == 0 ||
1327 strcmp(key, "sha256digest") == 0)
1329 if (strcmp(key, "sha384") == 0 ||
1330 strcmp(key, "sha384digest") == 0)
1332 if (strcmp(key, "sha512") == 0 ||
1333 strcmp(key, "sha512digest") == 0)
1335 if (strcmp(key, "size") == 0)
1339 if (strcmp(key, "time") == 0)
1341 else if (strcmp(key, "type") == 0)
1345 if (strcmp(key, "uid") == 0)
1347 else if (strcmp(key, "uname") == 0)
1349 else if (strcmp(key, "use-set") == 0) {
1350 mtree->output_global_set = (value != NULL)? 1: 0;
1351 return (ARCHIVE_OK);
1357 mtree->keys |= keybit;
1359 mtree->keys &= ~keybit;
1360 return (ARCHIVE_OK);
1363 /* Note: The "warn" return is just to inform the options
1364 * supervisor that we didn't handle it. It will generate
1365 * a suitable error if no one used this option. */
1366 return (ARCHIVE_WARN);
1370 archive_write_set_format_mtree_default(struct archive *_a, const char *fn)
1372 struct archive_write *a = (struct archive_write *)_a;
1373 struct mtree_writer *mtree;
1375 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, fn);
1377 if (a->format_free != NULL)
1378 (a->format_free)(a);
1380 if ((mtree = calloc(1, sizeof(*mtree))) == NULL) {
1381 archive_set_error(&a->archive, ENOMEM,
1382 "Can't allocate mtree data");
1383 return (ARCHIVE_FATAL);
1386 mtree->mtree_entry = NULL;
1388 memset(&(mtree->set), 0, sizeof(mtree->set));
1389 mtree->keys = DEFAULT_KEYS;
1392 archive_string_init(&mtree->ebuf);
1393 archive_string_init(&mtree->buf);
1394 mtree_entry_register_init(mtree);
1395 a->format_data = mtree;
1396 a->format_free = archive_write_mtree_free;
1397 a->format_name = "mtree";
1398 a->format_options = archive_write_mtree_options;
1399 a->format_write_header = archive_write_mtree_header;
1400 a->format_close = archive_write_mtree_close;
1401 a->format_write_data = archive_write_mtree_data;
1402 a->format_finish_entry = archive_write_mtree_finish_entry;
1403 a->archive.archive_format = ARCHIVE_FORMAT_MTREE;
1404 a->archive.archive_format_name = "mtree";
1406 return (ARCHIVE_OK);
1410 archive_write_set_format_mtree(struct archive *_a)
1412 return archive_write_set_format_mtree_default(_a,
1413 "archive_write_set_format_mtree");
1417 archive_write_set_format_mtree_classic(struct archive *_a)
1421 r = archive_write_set_format_mtree_default(_a,
1422 "archive_write_set_format_mtree_classic");
1423 if (r == ARCHIVE_OK) {
1424 struct archive_write *a = (struct archive_write *)_a;
1425 struct mtree_writer *mtree;
1427 mtree = (struct mtree_writer *)a->format_data;
1429 /* Set to output a mtree archive in classic format. */
1431 /* Basically, mtree classic format uses '/set' global
1433 mtree->output_global_set = 1;
1439 sum_init(struct mtree_writer *mtree)
1442 mtree->compute_sum = 0;
1444 if (mtree->keys & F_CKSUM) {
1445 mtree->compute_sum |= F_CKSUM;
1449 #ifdef ARCHIVE_HAS_MD5
1450 if (mtree->keys & F_MD5) {
1451 if (archive_md5_init(&mtree->md5ctx) == ARCHIVE_OK)
1452 mtree->compute_sum |= F_MD5;
1454 mtree->keys &= ~F_MD5;/* Not supported. */
1457 #ifdef ARCHIVE_HAS_RMD160
1458 if (mtree->keys & F_RMD160) {
1459 if (archive_rmd160_init(&mtree->rmd160ctx) == ARCHIVE_OK)
1460 mtree->compute_sum |= F_RMD160;
1462 mtree->keys &= ~F_RMD160;/* Not supported. */
1465 #ifdef ARCHIVE_HAS_SHA1
1466 if (mtree->keys & F_SHA1) {
1467 if (archive_sha1_init(&mtree->sha1ctx) == ARCHIVE_OK)
1468 mtree->compute_sum |= F_SHA1;
1470 mtree->keys &= ~F_SHA1;/* Not supported. */
1473 #ifdef ARCHIVE_HAS_SHA256
1474 if (mtree->keys & F_SHA256) {
1475 if (archive_sha256_init(&mtree->sha256ctx) == ARCHIVE_OK)
1476 mtree->compute_sum |= F_SHA256;
1478 mtree->keys &= ~F_SHA256;/* Not supported. */
1481 #ifdef ARCHIVE_HAS_SHA384
1482 if (mtree->keys & F_SHA384) {
1483 if (archive_sha384_init(&mtree->sha384ctx) == ARCHIVE_OK)
1484 mtree->compute_sum |= F_SHA384;
1486 mtree->keys &= ~F_SHA384;/* Not supported. */
1489 #ifdef ARCHIVE_HAS_SHA512
1490 if (mtree->keys & F_SHA512) {
1491 if (archive_sha512_init(&mtree->sha512ctx) == ARCHIVE_OK)
1492 mtree->compute_sum |= F_SHA512;
1494 mtree->keys &= ~F_SHA512;/* Not supported. */
1500 sum_update(struct mtree_writer *mtree, const void *buff, size_t n)
1502 if (mtree->compute_sum & F_CKSUM) {
1504 * Compute a POSIX 1003.2 checksum
1506 const unsigned char *p;
1509 for (nn = n, p = buff; nn--; ++p)
1510 COMPUTE_CRC(mtree->crc, *p);
1511 mtree->crc_len += n;
1513 #ifdef ARCHIVE_HAS_MD5
1514 if (mtree->compute_sum & F_MD5)
1515 archive_md5_update(&mtree->md5ctx, buff, n);
1517 #ifdef ARCHIVE_HAS_RMD160
1518 if (mtree->compute_sum & F_RMD160)
1519 archive_rmd160_update(&mtree->rmd160ctx, buff, n);
1521 #ifdef ARCHIVE_HAS_SHA1
1522 if (mtree->compute_sum & F_SHA1)
1523 archive_sha1_update(&mtree->sha1ctx, buff, n);
1525 #ifdef ARCHIVE_HAS_SHA256
1526 if (mtree->compute_sum & F_SHA256)
1527 archive_sha256_update(&mtree->sha256ctx, buff, n);
1529 #ifdef ARCHIVE_HAS_SHA384
1530 if (mtree->compute_sum & F_SHA384)
1531 archive_sha384_update(&mtree->sha384ctx, buff, n);
1533 #ifdef ARCHIVE_HAS_SHA512
1534 if (mtree->compute_sum & F_SHA512)
1535 archive_sha512_update(&mtree->sha512ctx, buff, n);
1540 sum_final(struct mtree_writer *mtree, struct reg_info *reg)
1543 if (mtree->compute_sum & F_CKSUM) {
1545 /* Include the length of the file. */
1546 for (len = mtree->crc_len; len != 0; len >>= 8)
1547 COMPUTE_CRC(mtree->crc, len & 0xff);
1548 reg->crc = ~mtree->crc;
1550 #ifdef ARCHIVE_HAS_MD5
1551 if (mtree->compute_sum & F_MD5)
1552 archive_md5_final(&mtree->md5ctx, reg->buf_md5);
1554 #ifdef ARCHIVE_HAS_RMD160
1555 if (mtree->compute_sum & F_RMD160)
1556 archive_rmd160_final(&mtree->rmd160ctx, reg->buf_rmd160);
1558 #ifdef ARCHIVE_HAS_SHA1
1559 if (mtree->compute_sum & F_SHA1)
1560 archive_sha1_final(&mtree->sha1ctx, reg->buf_sha1);
1562 #ifdef ARCHIVE_HAS_SHA256
1563 if (mtree->compute_sum & F_SHA256)
1564 archive_sha256_final(&mtree->sha256ctx, reg->buf_sha256);
1566 #ifdef ARCHIVE_HAS_SHA384
1567 if (mtree->compute_sum & F_SHA384)
1568 archive_sha384_final(&mtree->sha384ctx, reg->buf_sha384);
1570 #ifdef ARCHIVE_HAS_SHA512
1571 if (mtree->compute_sum & F_SHA512)
1572 archive_sha512_final(&mtree->sha512ctx, reg->buf_sha512);
1574 /* Save what types of sum are computed. */
1575 reg->compute_sum = mtree->compute_sum;
1578 #if defined(ARCHIVE_HAS_MD5) || defined(ARCHIVE_HAS_RMD160) || \
1579 defined(ARCHIVE_HAS_SHA1) || defined(ARCHIVE_HAS_SHA256) || \
1580 defined(ARCHIVE_HAS_SHA384) || defined(ARCHIVE_HAS_SHA512)
1582 strappend_bin(struct archive_string *s, const unsigned char *bin, int n)
1584 static const char hex[] = "0123456789abcdef";
1587 for (i = 0; i < n; i++) {
1588 archive_strappend_char(s, hex[bin[i] >> 4]);
1589 archive_strappend_char(s, hex[bin[i] & 0x0f]);
1595 sum_write(struct archive_string *str, struct reg_info *reg)
1598 if (reg->compute_sum & F_CKSUM) {
1599 archive_string_sprintf(str, " cksum=%ju",
1600 (uintmax_t)reg->crc);
1602 #ifdef ARCHIVE_HAS_MD5
1603 if (reg->compute_sum & F_MD5) {
1604 archive_strcat(str, " md5digest=");
1605 strappend_bin(str, reg->buf_md5, sizeof(reg->buf_md5));
1608 #ifdef ARCHIVE_HAS_RMD160
1609 if (reg->compute_sum & F_RMD160) {
1610 archive_strcat(str, " rmd160digest=");
1611 strappend_bin(str, reg->buf_rmd160, sizeof(reg->buf_rmd160));
1614 #ifdef ARCHIVE_HAS_SHA1
1615 if (reg->compute_sum & F_SHA1) {
1616 archive_strcat(str, " sha1digest=");
1617 strappend_bin(str, reg->buf_sha1, sizeof(reg->buf_sha1));
1620 #ifdef ARCHIVE_HAS_SHA256
1621 if (reg->compute_sum & F_SHA256) {
1622 archive_strcat(str, " sha256digest=");
1623 strappend_bin(str, reg->buf_sha256, sizeof(reg->buf_sha256));
1626 #ifdef ARCHIVE_HAS_SHA384
1627 if (reg->compute_sum & F_SHA384) {
1628 archive_strcat(str, " sha384digest=");
1629 strappend_bin(str, reg->buf_sha384, sizeof(reg->buf_sha384));
1632 #ifdef ARCHIVE_HAS_SHA512
1633 if (reg->compute_sum & F_SHA512) {
1634 archive_strcat(str, " sha512digest=");
1635 strappend_bin(str, reg->buf_sha512, sizeof(reg->buf_sha512));
1641 mtree_entry_cmp_node(const struct archive_rb_node *n1,
1642 const struct archive_rb_node *n2)
1644 const struct mtree_entry *e1 = (const struct mtree_entry *)n1;
1645 const struct mtree_entry *e2 = (const struct mtree_entry *)n2;
1647 return (strcmp(e2->basename.s, e1->basename.s));
1651 mtree_entry_cmp_key(const struct archive_rb_node *n, const void *key)
1653 const struct mtree_entry *e = (const struct mtree_entry *)n;
1655 return (strcmp((const char *)key, e->basename.s));
1658 #if defined(_WIN32) || defined(__CYGWIN__)
1660 cleanup_backslash_1(char *p)
1666 if (*(unsigned char *)p > 127)
1669 /* If we have not met any multi-byte characters,
1670 * we can replace '\' with '/'. */
1683 cleanup_backslash_2(wchar_t *p)
1686 /* Convert a path-separator from '\' to '/' */
1687 while (*p != L'\0') {
1696 * Generate a parent directory name and a base name from a pathname.
1699 mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file,
1700 struct archive_entry *entry)
1702 const char *pathname;
1703 char *p, *dirname, *slash;
1705 int ret = ARCHIVE_OK;
1707 archive_strcpy(&file->pathname, archive_entry_pathname(entry));
1708 #if defined(_WIN32) || defined(__CYGWIN__)
1710 * Convert a path-separator from '\' to '/'
1712 if (cleanup_backslash_1(file->pathname.s) != 0) {
1713 const wchar_t *wp = archive_entry_pathname_w(entry);
1714 struct archive_wstring ws;
1718 archive_string_init(&ws);
1719 archive_wstrcpy(&ws, wp);
1720 cleanup_backslash_2(ws.s);
1721 archive_string_empty(&(file->pathname));
1722 r = archive_string_append_from_wcs(&(file->pathname),
1724 archive_wstring_free(&ws);
1725 if (r < 0 && errno == ENOMEM) {
1726 archive_set_error(&a->archive, ENOMEM,
1727 "Can't allocate memory");
1728 return (ARCHIVE_FATAL);
1733 (void)a; /* UNUSED */
1735 pathname = file->pathname.s;
1736 if (strcmp(pathname, ".") == 0) {
1737 archive_strcpy(&file->basename, ".");
1738 return (ARCHIVE_OK);
1741 archive_strcpy(&(file->parentdir), pathname);
1743 len = file->parentdir.length;
1744 p = dirname = file->parentdir.s;
1747 * Remove leading '/' and '../' elements
1753 } else if (p[0] != '.')
1755 else if (p[1] == '.' && p[2] == '/') {
1762 memmove(dirname, p, len+1);
1766 * Remove "/","/." and "/.." elements from tail.
1771 if (len > 0 && p[len-1] == '/') {
1775 if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
1779 if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
1790 /* Convert '//' --> '/' */
1792 else if (p[1] == '.' && p[2] == '/')
1793 /* Convert '/./' --> '/' */
1795 else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
1796 /* Convert 'dir/dir1/../dir2/'
1800 while (rp >= dirname) {
1809 strcpy(dirname, p+4);
1822 * NOTE: If the pathname does not have a path separator, we have
1823 * to add "./" to the head of the pathename because mtree reader
1824 * will suppose that it is v1(a.k.a classic) mtree format and
1825 * change the directory unexpectedly and so it will make a wrong
1828 if (strcmp(p, ".") != 0 && strncmp(p, "./", 2) != 0) {
1829 struct archive_string as;
1830 archive_string_init(&as);
1831 archive_strcpy(&as, "./");
1832 archive_strncat(&as, p, len);
1833 archive_string_empty(&file->parentdir);
1834 archive_string_concat(&file->parentdir, &as);
1835 archive_string_free(&as);
1836 p = file->parentdir.s;
1837 len = archive_strlen(&file->parentdir);
1841 * Find out the position which points the last position of
1842 * path separator('/').
1845 for (; *p != '\0'; p++) {
1849 if (slash == NULL) {
1850 /* The pathname doesn't have a parent directory. */
1851 file->parentdir.length = len;
1852 archive_string_copy(&(file->basename), &(file->parentdir));
1853 archive_string_empty(&(file->parentdir));
1854 *file->parentdir.s = '\0';
1858 /* Make a basename from dirname and slash */
1860 file->parentdir.length = slash - dirname;
1861 archive_strcpy(&(file->basename), slash + 1);
1866 mtree_entry_create_virtual_dir(struct archive_write *a, const char *pathname,
1867 struct mtree_entry **m_entry)
1869 struct archive_entry *entry;
1870 struct mtree_entry *file;
1873 entry = archive_entry_new();
1874 if (entry == NULL) {
1876 archive_set_error(&a->archive, ENOMEM,
1877 "Can't allocate memory");
1878 return (ARCHIVE_FATAL);
1880 archive_entry_copy_pathname(entry, pathname);
1881 archive_entry_set_mode(entry, AE_IFDIR | 0755);
1882 archive_entry_set_mtime(entry, time(NULL), 0);
1884 r = mtree_entry_new(a, entry, &file);
1885 archive_entry_free(entry);
1886 if (r < ARCHIVE_WARN) {
1888 archive_set_error(&a->archive, ENOMEM,
1889 "Can't allocate memory");
1890 return (ARCHIVE_FATAL);
1893 file->dir_info->virtual = 1;
1896 return (ARCHIVE_OK);
1900 mtree_entry_register_add(struct mtree_writer *mtree, struct mtree_entry *file)
1903 *mtree->file_list.last = file;
1904 mtree->file_list.last = &(file->next);
1908 mtree_entry_register_init(struct mtree_writer *mtree)
1910 mtree->file_list.first = NULL;
1911 mtree->file_list.last = &(mtree->file_list.first);
1915 mtree_entry_register_free(struct mtree_writer *mtree)
1917 struct mtree_entry *file, *file_next;
1919 file = mtree->file_list.first;
1920 while (file != NULL) {
1921 file_next = file->next;
1922 mtree_entry_free(file);
1928 mtree_entry_add_child_tail(struct mtree_entry *parent,
1929 struct mtree_entry *child)
1931 child->dir_info->chnext = NULL;
1932 *parent->dir_info->children.last = child;
1933 parent->dir_info->children.last = &(child->dir_info->chnext);
1938 * Find a entry from a parent entry with the name.
1940 static struct mtree_entry *
1941 mtree_entry_find_child(struct mtree_entry *parent, const char *child_name)
1943 struct mtree_entry *np;
1947 np = (struct mtree_entry *)__archive_rb_tree_find_node(
1948 &(parent->dir_info->rbtree), child_name);
1953 get_path_component(char *name, size_t n, const char *fn)
1958 p = strchr(fn, '/');
1960 if ((l = strlen(fn)) == 0)
1966 memcpy(name, fn, l);
1973 * Add a new entry into the tree.
1976 mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep)
1978 #if defined(_WIN32) && !defined(__CYGWIN__)
1979 char name[_MAX_FNAME];/* Included null terminator size. */
1980 #elif defined(NAME_MAX) && NAME_MAX >= 255
1981 char name[NAME_MAX+1];
1985 struct mtree_writer *mtree = (struct mtree_writer *)a->format_data;
1986 struct mtree_entry *dent, *file, *np;
1991 if (file->parentdir.length == 0 && file->basename.length == 1 &&
1992 file->basename.s[0] == '.') {
1993 file->parent = file;
1994 if (mtree->root != NULL) {
1999 mtree_entry_register_add(mtree, file);
2000 return (ARCHIVE_OK);
2003 if (file->parentdir.length == 0) {
2004 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2005 "Internal programing error "
2006 "in generating canonical name for %s",
2008 return (ARCHIVE_FAILED);
2011 fn = p = file->parentdir.s;
2014 * If the path of the parent directory of `file' entry is
2015 * the same as the path of `cur_dirent', add `file' entry to
2018 if (archive_strlen(&(mtree->cur_dirstr))
2019 == archive_strlen(&(file->parentdir)) &&
2020 strcmp(mtree->cur_dirstr.s, fn) == 0) {
2021 if (!__archive_rb_tree_insert_node(
2022 &(mtree->cur_dirent->dir_info->rbtree),
2023 (struct archive_rb_node *)file)) {
2024 /* There is the same name in the tree. */
2025 np = (struct mtree_entry *)__archive_rb_tree_find_node(
2026 &(mtree->cur_dirent->dir_info->rbtree),
2030 file->parent = mtree->cur_dirent;
2031 mtree_entry_register_add(mtree, file);
2032 return (ARCHIVE_OK);
2037 l = get_path_component(name, sizeof(name), fn);
2043 archive_set_error(&a->archive,
2045 "A name buffer is too small");
2046 return (ARCHIVE_FATAL);
2048 if (l == 1 && name[0] == '.' && dent != NULL &&
2049 dent == mtree->root) {
2056 np = mtree_entry_find_child(dent, name);
2057 if (np == NULL || fn[0] == '\0')
2060 /* Find next sub directory. */
2061 if (!np->dir_info) {
2062 /* NOT Directory! */
2063 archive_set_error(&a->archive,
2065 "`%s' is not directory, we cannot insert `%s' ",
2066 np->pathname.s, file->pathname.s);
2067 return (ARCHIVE_FAILED);
2076 * Create virtual parent directories.
2078 while (fn[0] != '\0') {
2079 struct mtree_entry *vp;
2080 struct archive_string as;
2082 archive_string_init(&as);
2083 archive_strncat(&as, p, fn - p + l);
2084 if (as.s[as.length-1] == '/') {
2085 as.s[as.length-1] = '\0';
2088 r = mtree_entry_create_virtual_dir(a, as.s, &vp);
2089 archive_string_free(&as);
2090 if (r < ARCHIVE_WARN)
2093 if (strcmp(vp->pathname.s, ".") == 0) {
2097 __archive_rb_tree_insert_node(
2098 &(dent->dir_info->rbtree),
2099 (struct archive_rb_node *)vp);
2102 mtree_entry_register_add(mtree, vp);
2108 l = get_path_component(name, sizeof(name), fn);
2110 archive_string_free(&as);
2111 archive_set_error(&a->archive,
2113 "A name buffer is too small");
2114 return (ARCHIVE_FATAL);
2119 /* Found out the parent directory where `file' can be
2121 mtree->cur_dirent = dent;
2122 archive_string_empty(&(mtree->cur_dirstr));
2123 archive_string_ensure(&(mtree->cur_dirstr),
2124 archive_strlen(&(dent->parentdir)) +
2125 archive_strlen(&(dent->basename)) + 2);
2126 if (archive_strlen(&(dent->parentdir)) +
2127 archive_strlen(&(dent->basename)) == 0)
2128 mtree->cur_dirstr.s[0] = 0;
2130 if (archive_strlen(&(dent->parentdir)) > 0) {
2131 archive_string_copy(&(mtree->cur_dirstr),
2132 &(dent->parentdir));
2133 archive_strappend_char(
2134 &(mtree->cur_dirstr), '/');
2136 archive_string_concat(&(mtree->cur_dirstr),
2140 if (!__archive_rb_tree_insert_node(
2141 &(dent->dir_info->rbtree),
2142 (struct archive_rb_node *)file)) {
2143 np = (struct mtree_entry *)__archive_rb_tree_find_node(
2144 &(dent->dir_info->rbtree), file->basename.s);
2147 file->parent = dent;
2148 mtree_entry_register_add(mtree, file);
2149 return (ARCHIVE_OK);
2154 * We have already has the entry the filename of which is
2157 r = mtree_entry_exchange_same_entry(a, np, file);
2158 if (r < ARCHIVE_WARN)
2161 np->dir_info->virtual = 0;
2163 mtree_entry_free(file);
2164 return (ARCHIVE_WARN);
2168 mtree_entry_exchange_same_entry(struct archive_write *a, struct mtree_entry *np,
2169 struct mtree_entry *file)
2172 if ((np->mode & AE_IFMT) != (file->mode & AE_IFMT)) {
2173 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2174 "Found duplicate entries `%s' and its file type is "
2177 return (ARCHIVE_FAILED);
2180 /* Update the existent mtree entry's attributes by the new one's. */
2181 archive_string_empty(&np->symlink);
2182 archive_string_concat(&np->symlink, &file->symlink);
2183 archive_string_empty(&np->uname);
2184 archive_string_concat(&np->uname, &file->uname);
2185 archive_string_empty(&np->gname);
2186 archive_string_concat(&np->gname, &file->gname);
2187 archive_string_empty(&np->fflags_text);
2188 archive_string_concat(&np->fflags_text, &file->fflags_text);
2189 np->nlink = file->nlink;
2190 np->filetype = file->filetype;
2191 np->mode = file->mode;
2192 np->size = file->size;
2193 np->uid = file->uid;
2194 np->gid = file->gid;
2195 np->fflags_set = file->fflags_set;
2196 np->fflags_clear = file->fflags_clear;
2197 np->mtime = file->mtime;
2198 np->mtime_nsec = file->mtime_nsec;
2199 np->rdevmajor = file->rdevmajor;
2200 np->rdevminor = file->rdevminor;
2202 return (ARCHIVE_WARN);