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$");
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
38 #include "archive_digest_private.h"
39 #include "archive_entry.h"
40 #include "archive_entry_private.h"
41 #include "archive_private.h"
42 #include "archive_rb.h"
43 #include "archive_string.h"
44 #include "archive_write_private.h"
46 #define INDENTNAMELEN 15
49 (F_FLAGS | F_GID | F_GNAME | F_MODE | F_TYPE | F_UID | F_UNAME)
52 struct attr_counter *prev;
53 struct attr_counter *next;
54 struct mtree_entry *m_entry;
58 struct att_counter_set {
59 struct attr_counter *uid_list;
60 struct attr_counter *gid_list;
61 struct attr_counter *mode_list;
62 struct attr_counter *flags_list;
66 struct mtree_entry *first;
67 struct mtree_entry **last;
71 * The Data only for a directory file.
74 struct archive_rb_tree rbtree;
75 struct mtree_chain children;
76 struct mtree_entry *chnext;
81 * The Data only for a regular file.
86 struct ae_digest digest;
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;
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;
111 unsigned long fflags_set;
112 unsigned long fflags_clear;
120 struct mtree_writer {
121 struct mtree_entry *mtree_entry;
122 struct mtree_entry *root;
123 struct mtree_entry *cur_dirent;
124 struct archive_string cur_dirstr;
125 struct mtree_chain file_list;
127 struct archive_string ebuf;
128 struct archive_string buf;
130 uint64_t entry_bytes_remaining;
142 unsigned long fflags_set;
143 unsigned long fflags_clear;
145 struct att_counter_set acs;
153 #ifdef ARCHIVE_HAS_MD5
154 archive_md5_ctx md5ctx;
156 #ifdef ARCHIVE_HAS_RMD160
157 archive_rmd160_ctx rmd160ctx;
159 #ifdef ARCHIVE_HAS_SHA1
160 archive_sha1_ctx sha1ctx;
162 #ifdef ARCHIVE_HAS_SHA256
163 archive_sha256_ctx sha256ctx;
165 #ifdef ARCHIVE_HAS_SHA384
166 archive_sha384_ctx sha384ctx;
168 #ifdef ARCHIVE_HAS_SHA512
169 archive_sha512_ctx sha512ctx;
171 /* Keyword options */
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
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
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. */
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\
216 #define attr_counter_set_reset attr_counter_set_free
218 static void attr_counter_free(struct attr_counter **);
219 static int attr_counter_inc(struct attr_counter **, struct attr_counter *,
220 struct attr_counter *, struct mtree_entry *);
221 static struct attr_counter * attr_counter_new(struct mtree_entry *,
222 struct attr_counter *);
223 static int attr_counter_set_collect(struct mtree_writer *,
224 struct mtree_entry *);
225 static void attr_counter_set_free(struct mtree_writer *);
226 static int get_global_set_keys(struct mtree_writer *, struct mtree_entry *);
227 static int mtree_entry_add_child_tail(struct mtree_entry *,
228 struct mtree_entry *);
229 static int mtree_entry_create_virtual_dir(struct archive_write *, const char *,
230 struct mtree_entry **);
231 static int mtree_entry_cmp_node(const struct archive_rb_node *,
232 const struct archive_rb_node *);
233 static int mtree_entry_cmp_key(const struct archive_rb_node *, const void *);
234 static int mtree_entry_exchange_same_entry(struct archive_write *,
235 struct mtree_entry *, struct mtree_entry *);
236 static void mtree_entry_free(struct mtree_entry *);
237 static int mtree_entry_new(struct archive_write *, struct archive_entry *,
238 struct mtree_entry **);
239 static void mtree_entry_register_free(struct mtree_writer *);
240 static void mtree_entry_register_init(struct mtree_writer *);
241 static int mtree_entry_setup_filenames(struct archive_write *,
242 struct mtree_entry *, struct archive_entry *);
243 static int mtree_entry_tree_add(struct archive_write *, struct mtree_entry **);
244 static void sum_init(struct mtree_writer *);
245 static void sum_update(struct mtree_writer *, const void *, size_t);
246 static void sum_final(struct mtree_writer *, struct reg_info *);
247 static void sum_write(struct archive_string *, struct reg_info *);
248 static int write_mtree_entry(struct archive_write *, struct mtree_entry *);
249 static int write_dot_dot_entry(struct archive_write *, struct mtree_entry *);
251 #define COMPUTE_CRC(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
252 static const uint32_t crctab[] = {
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
307 static const unsigned char safe_char[256] = {
308 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */
309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */
310 /* !"$%&'()*+,-./ EXCLUSION:0x20( ) 0x23(#) */
311 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
312 /* 0123456789:;<>? EXCLUSION:0x3d(=) */
313 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, /* 30 - 3F */
314 /* @ABCDEFGHIJKLMNO */
315 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
316 /* PQRSTUVWXYZ[]^_ EXCLUSION:0x5c(\) */
317 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, /* 50 - 5F */
318 /* `abcdefghijklmno */
319 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
320 /* pqrstuvwxyz{|}~ */
321 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */
322 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
323 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
324 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
325 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
326 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */
327 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */
328 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */
329 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */
333 mtree_quote(struct archive_string *s, const char *str)
339 for (start = str; *str != '\0'; ++str) {
340 if (safe_char[*(const unsigned char *)str])
343 archive_strncat(s, start, str - start);
344 c = (unsigned char)*str;
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);
354 archive_strncat(s, start, str - start);
358 * Indent a line as the mtree utility does so it is readable for people.
361 mtree_indent(struct mtree_writer *mtree)
364 const char *r, *s, *x;
366 if (mtree->classic) {
369 pd = mtree->depth * 4;
371 nd = mtree->depth?4:0;
377 s = r = mtree->ebuf.s;
381 while ((r = strchr(r, ' ')) != NULL) {
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, ' ');
392 for (i = (int)(r -s + nd);
393 i < (INDENTNAMELEN + 1); i++)
394 archive_strappend_char(&mtree->buf, ' ');
400 if (pd + (r - s) <= MAXLINELEN - 3 - INDENTNAMELEN)
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, ' ');
414 for (i = 0; i < nd + pd; i++)
415 archive_strappend_char(&mtree->buf, ' ');
416 archive_strcat(&mtree->buf, s);
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, ' ');
427 archive_strcat(&mtree->buf, s);
428 archive_string_empty(&mtree->ebuf);
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.
437 write_global(struct mtree_writer *mtree)
439 struct archive_string setstr;
440 struct archive_string unsetstr;
441 struct att_counter_set *acs;
442 int keys, oldkeys, effkeys;
444 archive_string_init(&setstr);
445 archive_string_init(&unsetstr);
446 keys = mtree->keys & SET_KEYS;
447 oldkeys = mtree->set.keys;
450 if (mtree->set.processing) {
452 * Check if the global data needs updating.
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);
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);
469 if (acs->mode_list == NULL)
471 else if (oldkeys & F_MODE) {
472 if (acs->mode_list->count < 2 ||
473 mtree->set.mode == acs->mode_list->m_entry->mode)
476 if (acs->flags_list == NULL)
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))
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)
493 if (acs->flags_list == NULL)
496 if ((keys & effkeys & F_TYPE) != 0) {
497 if (mtree->dironly) {
498 archive_strcat(&setstr, " type=dir");
499 mtree->set.type = AE_IFDIR;
501 archive_strcat(&setstr, " type=file");
502 mtree->set.type = AE_IFREG;
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);
511 if ((oldkeys & F_UNAME) != 0)
512 archive_strcat(&unsetstr, " uname");
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);
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);
526 if ((oldkeys & F_GNAME) != 0)
527 archive_strcat(&unsetstr, " gname");
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);
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);
540 if ((keys & effkeys & F_FLAGS) != 0) {
542 &(acs->flags_list->m_entry->fflags_text)) > 0) {
543 archive_strcat(&setstr, " flags=");
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;
552 if ((oldkeys & F_FLAGS) != 0)
553 archive_strcat(&unsetstr, " flags");
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;
566 static struct attr_counter *
567 attr_counter_new(struct mtree_entry *me, struct attr_counter *prev)
569 struct attr_counter *ac;
571 ac = malloc(sizeof(*ac));
582 attr_counter_free(struct attr_counter **top)
584 struct attr_counter *ac, *tac;
598 attr_counter_inc(struct attr_counter **top, struct attr_counter *ac,
599 struct attr_counter *last, struct mtree_entry *me)
601 struct attr_counter *pac;
605 if (*top == ac || ac->prev->count >= ac->count)
607 for (pac = ac->prev; pac; pac = pac->prev) {
608 if (pac->count >= ac->count)
611 ac->prev->next = ac->next;
612 if (ac->next != NULL)
613 ac->next->prev = ac->prev;
616 ac->next = pac->next;
618 if (ac->next != NULL)
626 } else if (last != NULL) {
627 ac = attr_counter_new(me, last);
636 * Tabulate uid, gid, mode and fflags of a entry in order to be used for /set.
639 attr_counter_set_collect(struct mtree_writer *mtree, struct mtree_entry *me)
641 struct attr_counter *ac, *last;
642 struct att_counter_set *acs = &mtree->acs;
643 int keys = mtree->keys;
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)
652 for (ac = acs->uid_list; ac; ac = ac->next) {
653 if (ac->m_entry->uid == me->uid)
657 if (attr_counter_inc(&acs->uid_list, ac, last, me) < 0)
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)
668 for (ac = acs->gid_list; ac; ac = ac->next) {
669 if (ac->m_entry->gid == me->gid)
673 if (attr_counter_inc(&acs->gid_list, ac, last, me) < 0)
678 if (acs->mode_list == NULL) {
679 acs->mode_list = attr_counter_new(me, NULL);
680 if (acs->mode_list == NULL)
684 for (ac = acs->mode_list; ac; ac = ac->next) {
685 if (ac->m_entry->mode == me->mode)
689 if (attr_counter_inc(&acs->mode_list, ac, last, me) < 0)
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)
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 ==
707 if (attr_counter_inc(&acs->flags_list, ac, last, me) < 0)
716 attr_counter_set_free(struct mtree_writer *mtree)
718 struct att_counter_set *acs = &mtree->acs;
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);
727 get_global_set_keys(struct mtree_writer *mtree, struct mtree_entry *me)
734 * If a keyword has been set by /set, we do not need to
737 if (mtree->set.keys == 0)
738 return (keys);/* /set is not used. */
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)
751 if ((mtree->set.keys & F_MODE) != 0 && mtree->set.mode == me->mode)
754 switch (me->filetype) {
755 case AE_IFLNK: case AE_IFSOCK: case AE_IFCHR:
756 case AE_IFBLK: case AE_IFIFO:
759 if ((mtree->set.keys & F_TYPE) != 0 &&
760 mtree->set.type == AE_IFDIR)
764 default: /* Handle unknown file types as regular files. */
765 if ((mtree->set.keys & F_TYPE) != 0 &&
766 mtree->set.type == AE_IFREG)
775 mtree_entry_new(struct archive_write *a, struct archive_entry *entry,
776 struct mtree_entry **m_entry)
778 struct mtree_entry *me;
781 static const struct archive_rb_tree_ops rb_ops = {
782 mtree_entry_cmp_node, mtree_entry_cmp_key
785 me = calloc(1, sizeof(*me));
787 archive_set_error(&a->archive, ENOMEM,
788 "Can't allocate memory for a mtree entry");
790 return (ARCHIVE_FATAL);
793 r = mtree_entry_setup_filenames(a, me, entry);
794 if (r < ARCHIVE_WARN) {
795 mtree_entry_free(me);
800 if ((s = archive_entry_symlink(entry)) != NULL)
801 archive_strcpy(&me->symlink, s);
802 me->nlink = archive_entry_nlink(entry);
803 me->filetype = archive_entry_filetype(entry);
804 me->mode = archive_entry_mode(entry) & 07777;
805 me->uid = archive_entry_uid(entry);
806 me->gid = archive_entry_gid(entry);
807 if ((s = archive_entry_uname(entry)) != NULL)
808 archive_strcpy(&me->uname, s);
809 if ((s = archive_entry_gname(entry)) != NULL)
810 archive_strcpy(&me->gname, s);
811 if ((s = archive_entry_fflags_text(entry)) != NULL)
812 archive_strcpy(&me->fflags_text, s);
813 archive_entry_fflags(entry, &me->fflags_set, &me->fflags_clear);
814 me->mtime = archive_entry_mtime(entry);
815 me->mtime_nsec = archive_entry_mtime_nsec(entry);
816 me->rdevmajor = archive_entry_rdevmajor(entry);
817 me->rdevminor = archive_entry_rdevminor(entry);
818 me->devmajor = archive_entry_devmajor(entry);
819 me->devminor = archive_entry_devminor(entry);
820 me->ino = archive_entry_ino(entry);
821 me->size = archive_entry_size(entry);
822 if (me->filetype == AE_IFDIR) {
823 me->dir_info = calloc(1, sizeof(*me->dir_info));
824 if (me->dir_info == NULL) {
825 mtree_entry_free(me);
826 archive_set_error(&a->archive, ENOMEM,
827 "Can't allocate memory for a mtree entry");
829 return (ARCHIVE_FATAL);
831 __archive_rb_tree_init(&me->dir_info->rbtree, &rb_ops);
832 me->dir_info->children.first = NULL;
833 me->dir_info->children.last = &(me->dir_info->children.first);
834 me->dir_info->chnext = NULL;
835 } else if (me->filetype == AE_IFREG) {
836 me->reg_info = calloc(1, sizeof(*me->reg_info));
837 if (me->reg_info == NULL) {
838 mtree_entry_free(me);
839 archive_set_error(&a->archive, ENOMEM,
840 "Can't allocate memory for a mtree entry");
842 return (ARCHIVE_FATAL);
844 me->reg_info->compute_sum = 0;
852 mtree_entry_free(struct mtree_entry *me)
854 archive_string_free(&me->parentdir);
855 archive_string_free(&me->basename);
856 archive_string_free(&me->pathname);
857 archive_string_free(&me->symlink);
858 archive_string_free(&me->uname);
859 archive_string_free(&me->gname);
860 archive_string_free(&me->fflags_text);
867 archive_write_mtree_header(struct archive_write *a,
868 struct archive_entry *entry)
870 struct mtree_writer *mtree= a->format_data;
871 struct mtree_entry *mtree_entry;
876 archive_strcat(&mtree->buf, "#mtree\n");
877 if ((mtree->keys & SET_KEYS) == 0)
878 mtree->output_global_set = 0;/* Disabled. */
881 mtree->entry_bytes_remaining = archive_entry_size(entry);
883 /* While directory only mode, we do not handle non directory files. */
884 if (mtree->dironly && archive_entry_filetype(entry) != AE_IFDIR)
887 r2 = mtree_entry_new(a, entry, &mtree_entry);
888 if (r2 < ARCHIVE_WARN)
890 r = mtree_entry_tree_add(a, &mtree_entry);
891 if (r < ARCHIVE_WARN) {
892 mtree_entry_free(mtree_entry);
895 mtree->mtree_entry = mtree_entry;
897 /* If the current file is a regular file, we have to
898 * compute the sum of its content.
899 * Initialize a bunch of checksum context. */
900 if (mtree_entry->reg_info)
907 write_mtree_entry(struct archive_write *a, struct mtree_entry *me)
909 struct mtree_writer *mtree = a->format_data;
910 struct archive_string *str;
914 if (mtree->classic) {
916 * Output a comment line to describe the full
917 * pathname of the entry as mtree utility does
918 * while generating classic format.
921 archive_strappend_char(&mtree->buf, '\n');
923 archive_string_sprintf(&mtree->buf,
925 me->parentdir.s, me->basename.s);
927 archive_string_sprintf(&mtree->buf,
931 if (mtree->output_global_set)
934 archive_string_empty(&mtree->ebuf);
935 str = (mtree->indent || mtree->classic)? &mtree->ebuf : &mtree->buf;
937 if (!mtree->classic && me->parentdir.s) {
939 * If generating format is not classic one(v1), output
942 mtree_quote(str, me->parentdir.s);
943 archive_strappend_char(str, '/');
945 mtree_quote(str, me->basename.s);
947 keys = get_global_set_keys(mtree, me);
948 if ((keys & F_NLINK) != 0 &&
949 me->nlink != 1 && me->filetype != AE_IFDIR)
950 archive_string_sprintf(str, " nlink=%u", me->nlink);
952 if ((keys & F_GNAME) != 0 && archive_strlen(&me->gname) > 0) {
953 archive_strcat(str, " gname=");
954 mtree_quote(str, me->gname.s);
956 if ((keys & F_UNAME) != 0 && archive_strlen(&me->uname) > 0) {
957 archive_strcat(str, " uname=");
958 mtree_quote(str, me->uname.s);
960 if ((keys & F_FLAGS) != 0) {
961 if (archive_strlen(&me->fflags_text) > 0) {
962 archive_strcat(str, " flags=");
963 mtree_quote(str, me->fflags_text.s);
964 } else if (mtree->set.processing &&
965 (mtree->set.keys & F_FLAGS) != 0)
966 /* Overwrite the global parameter. */
967 archive_strcat(str, " flags=none");
969 if ((keys & F_TIME) != 0)
970 archive_string_sprintf(str, " time=%jd.%jd",
971 (intmax_t)me->mtime, (intmax_t)me->mtime_nsec);
972 if ((keys & F_MODE) != 0)
973 archive_string_sprintf(str, " mode=%o", (unsigned int)me->mode);
974 if ((keys & F_GID) != 0)
975 archive_string_sprintf(str, " gid=%jd", (intmax_t)me->gid);
976 if ((keys & F_UID) != 0)
977 archive_string_sprintf(str, " uid=%jd", (intmax_t)me->uid);
979 if ((keys & F_INO) != 0)
980 archive_string_sprintf(str, " inode=%jd", (intmax_t)me->ino);
981 if ((keys & F_RESDEV) != 0) {
982 archive_string_sprintf(str,
983 " resdevice=native,%ju,%ju",
984 (uintmax_t)me->devmajor,
985 (uintmax_t)me->devminor);
988 switch (me->filetype) {
990 if ((keys & F_TYPE) != 0)
991 archive_strcat(str, " type=link");
992 if ((keys & F_SLINK) != 0) {
993 archive_strcat(str, " link=");
994 mtree_quote(str, me->symlink.s);
998 if ((keys & F_TYPE) != 0)
999 archive_strcat(str, " type=socket");
1002 if ((keys & F_TYPE) != 0)
1003 archive_strcat(str, " type=char");
1004 if ((keys & F_DEV) != 0) {
1005 archive_string_sprintf(str,
1006 " device=native,%ju,%ju",
1007 (uintmax_t)me->rdevmajor,
1008 (uintmax_t)me->rdevminor);
1012 if ((keys & F_TYPE) != 0)
1013 archive_strcat(str, " type=block");
1014 if ((keys & F_DEV) != 0) {
1015 archive_string_sprintf(str,
1016 " device=native,%ju,%ju",
1017 (uintmax_t)me->rdevmajor,
1018 (uintmax_t)me->rdevminor);
1022 if ((keys & F_TYPE) != 0)
1023 archive_strcat(str, " type=dir");
1026 if ((keys & F_TYPE) != 0)
1027 archive_strcat(str, " type=fifo");
1030 default: /* Handle unknown file types as regular files. */
1031 if ((keys & F_TYPE) != 0)
1032 archive_strcat(str, " type=file");
1033 if ((keys & F_SIZE) != 0)
1034 archive_string_sprintf(str, " size=%jd",
1035 (intmax_t)me->size);
1039 /* Write a bunch of sum. */
1041 sum_write(str, me->reg_info);
1043 archive_strappend_char(str, '\n');
1044 if (mtree->indent || mtree->classic)
1045 mtree_indent(mtree);
1047 if (mtree->buf.length > 32768) {
1048 ret = __archive_write_output(
1049 a, mtree->buf.s, mtree->buf.length);
1050 archive_string_empty(&mtree->buf);
1057 write_dot_dot_entry(struct archive_write *a, struct mtree_entry *n)
1059 struct mtree_writer *mtree = a->format_data;
1062 if (n->parentdir.s) {
1063 if (mtree->indent) {
1064 int i, pd = mtree->depth * 4;
1065 for (i = 0; i < pd; i++)
1066 archive_strappend_char(&mtree->buf, ' ');
1068 archive_string_sprintf(&mtree->buf, "# %s/%s\n",
1069 n->parentdir.s, n->basename.s);
1072 if (mtree->indent) {
1073 archive_string_empty(&mtree->ebuf);
1074 archive_strncat(&mtree->ebuf, "..\n\n", (mtree->dironly)?3:4);
1075 mtree_indent(mtree);
1077 archive_strncat(&mtree->buf, "..\n\n", (mtree->dironly)?3:4);
1079 if (mtree->buf.length > 32768) {
1080 ret = __archive_write_output(
1081 a, mtree->buf.s, mtree->buf.length);
1082 archive_string_empty(&mtree->buf);
1089 * Write mtree entries saved at attr_counter_set_collect() function.
1092 write_mtree_entry_tree(struct archive_write *a)
1094 struct mtree_writer *mtree = a->format_data;
1095 struct mtree_entry *np = mtree->root;
1096 struct archive_rb_node *n;
1100 if (mtree->output_global_set) {
1102 * Collect attribute information to know which value
1103 * is frequently used among the children.
1105 attr_counter_set_reset(mtree);
1106 ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) {
1107 struct mtree_entry *e = (struct mtree_entry *)n;
1108 if (attr_counter_set_collect(mtree, e) < 0) {
1109 archive_set_error(&a->archive, ENOMEM,
1110 "Can't allocate memory");
1111 return (ARCHIVE_FATAL);
1115 if (!np->dir_info->virtual || mtree->classic) {
1116 ret = write_mtree_entry(a, np);
1117 if (ret != ARCHIVE_OK)
1118 return (ARCHIVE_FATAL);
1120 /* Whenever output_global_set is enabled
1121 * output global value(/set keywords)
1122 * even if the directory entry is not allowed
1123 * to be written because the global values
1124 * can be used for the children. */
1125 if (mtree->output_global_set)
1126 write_global(mtree);
1129 * Output the attribute of all files except directory files.
1132 ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) {
1133 struct mtree_entry *e = (struct mtree_entry *)n;
1136 mtree_entry_add_child_tail(np, e);
1138 ret = write_mtree_entry(a, e);
1139 if (ret != ARCHIVE_OK)
1140 return (ARCHIVE_FATAL);
1145 if (np->dir_info->children.first != NULL) {
1149 np = np->dir_info->children.first;
1153 } else if (mtree->classic) {
1155 * While printing mtree classic, if there are not
1156 * any directory files(except "." and "..") in the
1157 * directory, output two dots ".." as returning
1158 * the parent directory.
1160 ret = write_dot_dot_entry(a, np);
1161 if (ret != ARCHIVE_OK)
1162 return (ARCHIVE_FATAL);
1165 while (np != np->parent) {
1166 if (np->dir_info->chnext == NULL) {
1168 * Ascend the tree; go back to the parent.
1172 if (mtree->classic) {
1173 ret = write_dot_dot_entry(a,
1175 if (ret != ARCHIVE_OK)
1176 return (ARCHIVE_FATAL);
1181 * Switch to next mtree entry in the directory.
1183 np = np->dir_info->chnext;
1187 } while (np != np->parent);
1189 return (ARCHIVE_OK);
1193 archive_write_mtree_finish_entry(struct archive_write *a)
1195 struct mtree_writer *mtree = a->format_data;
1196 struct mtree_entry *me;
1198 if ((me = mtree->mtree_entry) == NULL)
1199 return (ARCHIVE_OK);
1200 mtree->mtree_entry = NULL;
1203 sum_final(mtree, me->reg_info);
1205 return (ARCHIVE_OK);
1209 archive_write_mtree_close(struct archive_write *a)
1211 struct mtree_writer *mtree= a->format_data;
1214 if (mtree->root != NULL) {
1215 ret = write_mtree_entry_tree(a);
1216 if (ret != ARCHIVE_OK)
1217 return (ARCHIVE_FATAL);
1220 archive_write_set_bytes_in_last_block(&a->archive, 1);
1222 return __archive_write_output(a, mtree->buf.s, mtree->buf.length);
1226 archive_write_mtree_data(struct archive_write *a, const void *buff, size_t n)
1228 struct mtree_writer *mtree= a->format_data;
1230 if (n > mtree->entry_bytes_remaining)
1231 n = (size_t)mtree->entry_bytes_remaining;
1232 mtree->entry_bytes_remaining -= n;
1234 /* We don't need to compute a regular file sum */
1235 if (mtree->mtree_entry == NULL)
1238 if (mtree->mtree_entry->filetype == AE_IFREG)
1239 sum_update(mtree, buff, n);
1245 archive_write_mtree_free(struct archive_write *a)
1247 struct mtree_writer *mtree= a->format_data;
1250 return (ARCHIVE_OK);
1252 /* Make sure we do not leave any entries. */
1253 mtree_entry_register_free(mtree);
1254 archive_string_free(&mtree->cur_dirstr);
1255 archive_string_free(&mtree->ebuf);
1256 archive_string_free(&mtree->buf);
1257 attr_counter_set_free(mtree);
1259 a->format_data = NULL;
1260 return (ARCHIVE_OK);
1264 archive_write_mtree_options(struct archive_write *a, const char *key,
1267 struct mtree_writer *mtree= a->format_data;
1272 if (strcmp(key, "all") == 0)
1276 if (strcmp(key, "cksum") == 0)
1280 if (strcmp(key, "device") == 0)
1282 else if (strcmp(key, "dironly") == 0) {
1283 mtree->dironly = (value != NULL)? 1: 0;
1284 return (ARCHIVE_OK);
1288 if (strcmp(key, "flags") == 0)
1292 if (strcmp(key, "gid") == 0)
1294 else if (strcmp(key, "gname") == 0)
1298 if (strcmp(key, "indent") == 0) {
1299 mtree->indent = (value != NULL)? 1: 0;
1300 return (ARCHIVE_OK);
1301 } else if (strcmp(key, "inode") == 0) {
1306 if (strcmp(key, "link") == 0)
1310 if (strcmp(key, "md5") == 0 ||
1311 strcmp(key, "md5digest") == 0)
1313 if (strcmp(key, "mode") == 0)
1317 if (strcmp(key, "nlink") == 0)
1321 if (strcmp(key, "resdevice") == 0) {
1323 } else if (strcmp(key, "ripemd160digest") == 0 ||
1324 strcmp(key, "rmd160") == 0 ||
1325 strcmp(key, "rmd160digest") == 0)
1329 if (strcmp(key, "sha1") == 0 ||
1330 strcmp(key, "sha1digest") == 0)
1332 if (strcmp(key, "sha256") == 0 ||
1333 strcmp(key, "sha256digest") == 0)
1335 if (strcmp(key, "sha384") == 0 ||
1336 strcmp(key, "sha384digest") == 0)
1338 if (strcmp(key, "sha512") == 0 ||
1339 strcmp(key, "sha512digest") == 0)
1341 if (strcmp(key, "size") == 0)
1345 if (strcmp(key, "time") == 0)
1347 else if (strcmp(key, "type") == 0)
1351 if (strcmp(key, "uid") == 0)
1353 else if (strcmp(key, "uname") == 0)
1355 else if (strcmp(key, "use-set") == 0) {
1356 mtree->output_global_set = (value != NULL)? 1: 0;
1357 return (ARCHIVE_OK);
1363 mtree->keys |= keybit;
1365 mtree->keys &= ~keybit;
1366 return (ARCHIVE_OK);
1369 /* Note: The "warn" return is just to inform the options
1370 * supervisor that we didn't handle it. It will generate
1371 * a suitable error if no one used this option. */
1372 return (ARCHIVE_WARN);
1376 archive_write_set_format_mtree_default(struct archive *_a, const char *fn)
1378 struct archive_write *a = (struct archive_write *)_a;
1379 struct mtree_writer *mtree;
1381 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, fn);
1383 if (a->format_free != NULL)
1384 (a->format_free)(a);
1386 if ((mtree = calloc(1, sizeof(*mtree))) == NULL) {
1387 archive_set_error(&a->archive, ENOMEM,
1388 "Can't allocate mtree data");
1389 return (ARCHIVE_FATAL);
1392 mtree->mtree_entry = NULL;
1394 memset(&(mtree->set), 0, sizeof(mtree->set));
1395 mtree->keys = DEFAULT_KEYS;
1398 archive_string_init(&mtree->ebuf);
1399 archive_string_init(&mtree->buf);
1400 mtree_entry_register_init(mtree);
1401 a->format_data = mtree;
1402 a->format_free = archive_write_mtree_free;
1403 a->format_name = "mtree";
1404 a->format_options = archive_write_mtree_options;
1405 a->format_write_header = archive_write_mtree_header;
1406 a->format_close = archive_write_mtree_close;
1407 a->format_write_data = archive_write_mtree_data;
1408 a->format_finish_entry = archive_write_mtree_finish_entry;
1409 a->archive.archive_format = ARCHIVE_FORMAT_MTREE;
1410 a->archive.archive_format_name = "mtree";
1412 return (ARCHIVE_OK);
1416 archive_write_set_format_mtree(struct archive *_a)
1418 return archive_write_set_format_mtree_default(_a,
1419 "archive_write_set_format_mtree");
1423 archive_write_set_format_mtree_classic(struct archive *_a)
1427 r = archive_write_set_format_mtree_default(_a,
1428 "archive_write_set_format_mtree_classic");
1429 if (r == ARCHIVE_OK) {
1430 struct archive_write *a = (struct archive_write *)_a;
1431 struct mtree_writer *mtree;
1433 mtree = (struct mtree_writer *)a->format_data;
1435 /* Set to output a mtree archive in classic format. */
1437 /* Basically, mtree classic format uses '/set' global
1439 mtree->output_global_set = 1;
1445 sum_init(struct mtree_writer *mtree)
1448 mtree->compute_sum = 0;
1450 if (mtree->keys & F_CKSUM) {
1451 mtree->compute_sum |= F_CKSUM;
1455 #ifdef ARCHIVE_HAS_MD5
1456 if (mtree->keys & F_MD5) {
1457 if (archive_md5_init(&mtree->md5ctx) == ARCHIVE_OK)
1458 mtree->compute_sum |= F_MD5;
1460 mtree->keys &= ~F_MD5;/* Not supported. */
1463 #ifdef ARCHIVE_HAS_RMD160
1464 if (mtree->keys & F_RMD160) {
1465 if (archive_rmd160_init(&mtree->rmd160ctx) == ARCHIVE_OK)
1466 mtree->compute_sum |= F_RMD160;
1468 mtree->keys &= ~F_RMD160;/* Not supported. */
1471 #ifdef ARCHIVE_HAS_SHA1
1472 if (mtree->keys & F_SHA1) {
1473 if (archive_sha1_init(&mtree->sha1ctx) == ARCHIVE_OK)
1474 mtree->compute_sum |= F_SHA1;
1476 mtree->keys &= ~F_SHA1;/* Not supported. */
1479 #ifdef ARCHIVE_HAS_SHA256
1480 if (mtree->keys & F_SHA256) {
1481 if (archive_sha256_init(&mtree->sha256ctx) == ARCHIVE_OK)
1482 mtree->compute_sum |= F_SHA256;
1484 mtree->keys &= ~F_SHA256;/* Not supported. */
1487 #ifdef ARCHIVE_HAS_SHA384
1488 if (mtree->keys & F_SHA384) {
1489 if (archive_sha384_init(&mtree->sha384ctx) == ARCHIVE_OK)
1490 mtree->compute_sum |= F_SHA384;
1492 mtree->keys &= ~F_SHA384;/* Not supported. */
1495 #ifdef ARCHIVE_HAS_SHA512
1496 if (mtree->keys & F_SHA512) {
1497 if (archive_sha512_init(&mtree->sha512ctx) == ARCHIVE_OK)
1498 mtree->compute_sum |= F_SHA512;
1500 mtree->keys &= ~F_SHA512;/* Not supported. */
1506 sum_update(struct mtree_writer *mtree, const void *buff, size_t n)
1508 if (mtree->compute_sum & F_CKSUM) {
1510 * Compute a POSIX 1003.2 checksum
1512 const unsigned char *p;
1515 for (nn = n, p = buff; nn--; ++p)
1516 COMPUTE_CRC(mtree->crc, *p);
1517 mtree->crc_len += n;
1519 #ifdef ARCHIVE_HAS_MD5
1520 if (mtree->compute_sum & F_MD5)
1521 archive_md5_update(&mtree->md5ctx, buff, n);
1523 #ifdef ARCHIVE_HAS_RMD160
1524 if (mtree->compute_sum & F_RMD160)
1525 archive_rmd160_update(&mtree->rmd160ctx, buff, n);
1527 #ifdef ARCHIVE_HAS_SHA1
1528 if (mtree->compute_sum & F_SHA1)
1529 archive_sha1_update(&mtree->sha1ctx, buff, n);
1531 #ifdef ARCHIVE_HAS_SHA256
1532 if (mtree->compute_sum & F_SHA256)
1533 archive_sha256_update(&mtree->sha256ctx, buff, n);
1535 #ifdef ARCHIVE_HAS_SHA384
1536 if (mtree->compute_sum & F_SHA384)
1537 archive_sha384_update(&mtree->sha384ctx, buff, n);
1539 #ifdef ARCHIVE_HAS_SHA512
1540 if (mtree->compute_sum & F_SHA512)
1541 archive_sha512_update(&mtree->sha512ctx, buff, n);
1546 sum_final(struct mtree_writer *mtree, struct reg_info *reg)
1549 if (mtree->compute_sum & F_CKSUM) {
1551 /* Include the length of the file. */
1552 for (len = mtree->crc_len; len != 0; len >>= 8)
1553 COMPUTE_CRC(mtree->crc, len & 0xff);
1554 reg->crc = ~mtree->crc;
1556 #ifdef ARCHIVE_HAS_MD5
1557 if (mtree->compute_sum & F_MD5)
1558 archive_md5_final(&mtree->md5ctx, reg->digest.md5);
1560 #ifdef ARCHIVE_HAS_RMD160
1561 if (mtree->compute_sum & F_RMD160)
1562 archive_rmd160_final(&mtree->rmd160ctx, reg->digest.rmd160);
1564 #ifdef ARCHIVE_HAS_SHA1
1565 if (mtree->compute_sum & F_SHA1)
1566 archive_sha1_final(&mtree->sha1ctx, reg->digest.sha1);
1568 #ifdef ARCHIVE_HAS_SHA256
1569 if (mtree->compute_sum & F_SHA256)
1570 archive_sha256_final(&mtree->sha256ctx, reg->digest.sha256);
1572 #ifdef ARCHIVE_HAS_SHA384
1573 if (mtree->compute_sum & F_SHA384)
1574 archive_sha384_final(&mtree->sha384ctx, reg->digest.sha384);
1576 #ifdef ARCHIVE_HAS_SHA512
1577 if (mtree->compute_sum & F_SHA512)
1578 archive_sha512_final(&mtree->sha512ctx, reg->digest.sha512);
1580 /* Save what types of sum are computed. */
1581 reg->compute_sum = mtree->compute_sum;
1584 #if defined(ARCHIVE_HAS_MD5) || defined(ARCHIVE_HAS_RMD160) || \
1585 defined(ARCHIVE_HAS_SHA1) || defined(ARCHIVE_HAS_SHA256) || \
1586 defined(ARCHIVE_HAS_SHA384) || defined(ARCHIVE_HAS_SHA512)
1588 strappend_bin(struct archive_string *s, const unsigned char *bin, int n)
1590 static const char hex[] = "0123456789abcdef";
1593 for (i = 0; i < n; i++) {
1594 archive_strappend_char(s, hex[bin[i] >> 4]);
1595 archive_strappend_char(s, hex[bin[i] & 0x0f]);
1601 sum_write(struct archive_string *str, struct reg_info *reg)
1604 if (reg->compute_sum & F_CKSUM) {
1605 archive_string_sprintf(str, " cksum=%ju",
1606 (uintmax_t)reg->crc);
1609 #define append_digest(_s, _r, _t) \
1610 strappend_bin(_s, _r->digest._t, sizeof(_r->digest._t))
1612 #ifdef ARCHIVE_HAS_MD5
1613 if (reg->compute_sum & F_MD5) {
1614 archive_strcat(str, " md5digest=");
1615 append_digest(str, reg, md5);
1618 #ifdef ARCHIVE_HAS_RMD160
1619 if (reg->compute_sum & F_RMD160) {
1620 archive_strcat(str, " rmd160digest=");
1621 append_digest(str, reg, rmd160);
1624 #ifdef ARCHIVE_HAS_SHA1
1625 if (reg->compute_sum & F_SHA1) {
1626 archive_strcat(str, " sha1digest=");
1627 append_digest(str, reg, sha1);
1630 #ifdef ARCHIVE_HAS_SHA256
1631 if (reg->compute_sum & F_SHA256) {
1632 archive_strcat(str, " sha256digest=");
1633 append_digest(str, reg, sha256);
1636 #ifdef ARCHIVE_HAS_SHA384
1637 if (reg->compute_sum & F_SHA384) {
1638 archive_strcat(str, " sha384digest=");
1639 append_digest(str, reg, sha384);
1642 #ifdef ARCHIVE_HAS_SHA512
1643 if (reg->compute_sum & F_SHA512) {
1644 archive_strcat(str, " sha512digest=");
1645 append_digest(str, reg, sha512);
1648 #undef append_digest
1652 mtree_entry_cmp_node(const struct archive_rb_node *n1,
1653 const struct archive_rb_node *n2)
1655 const struct mtree_entry *e1 = (const struct mtree_entry *)n1;
1656 const struct mtree_entry *e2 = (const struct mtree_entry *)n2;
1658 return (strcmp(e2->basename.s, e1->basename.s));
1662 mtree_entry_cmp_key(const struct archive_rb_node *n, const void *key)
1664 const struct mtree_entry *e = (const struct mtree_entry *)n;
1666 return (strcmp((const char *)key, e->basename.s));
1669 #if defined(_WIN32) || defined(__CYGWIN__)
1671 cleanup_backslash_1(char *p)
1677 if (*(unsigned char *)p > 127)
1680 /* If we have not met any multi-byte characters,
1681 * we can replace '\' with '/'. */
1694 cleanup_backslash_2(wchar_t *p)
1697 /* Convert a path-separator from '\' to '/' */
1698 while (*p != L'\0') {
1707 * Generate a parent directory name and a base name from a pathname.
1710 mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file,
1711 struct archive_entry *entry)
1713 const char *pathname;
1714 char *p, *dirname, *slash;
1716 int ret = ARCHIVE_OK;
1718 archive_strcpy(&file->pathname, archive_entry_pathname(entry));
1719 #if defined(_WIN32) || defined(__CYGWIN__)
1721 * Convert a path-separator from '\' to '/'
1723 if (cleanup_backslash_1(file->pathname.s) != 0) {
1724 const wchar_t *wp = archive_entry_pathname_w(entry);
1725 struct archive_wstring ws;
1729 archive_string_init(&ws);
1730 archive_wstrcpy(&ws, wp);
1731 cleanup_backslash_2(ws.s);
1732 archive_string_empty(&(file->pathname));
1733 r = archive_string_append_from_wcs(&(file->pathname),
1735 archive_wstring_free(&ws);
1736 if (r < 0 && errno == ENOMEM) {
1737 archive_set_error(&a->archive, ENOMEM,
1738 "Can't allocate memory");
1739 return (ARCHIVE_FATAL);
1744 (void)a; /* UNUSED */
1746 pathname = file->pathname.s;
1747 if (strcmp(pathname, ".") == 0) {
1748 archive_strcpy(&file->basename, ".");
1749 return (ARCHIVE_OK);
1752 archive_strcpy(&(file->parentdir), pathname);
1754 len = file->parentdir.length;
1755 p = dirname = file->parentdir.s;
1758 * Remove leading '/' and '../' elements
1764 } else if (p[0] != '.')
1766 else if (p[1] == '.' && p[2] == '/') {
1773 memmove(dirname, p, len+1);
1777 * Remove "/","/." and "/.." elements from tail.
1782 if (len > 0 && p[len-1] == '/') {
1786 if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
1790 if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
1801 /* Convert '//' --> '/' */
1803 else if (p[1] == '.' && p[2] == '/')
1804 /* Convert '/./' --> '/' */
1806 else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
1807 /* Convert 'dir/dir1/../dir2/'
1811 while (rp >= dirname) {
1820 strcpy(dirname, p+4);
1833 * NOTE: If the pathname does not have a path separator, we have
1834 * to add "./" to the head of the pathname because mtree reader
1835 * will suppose that it is v1(a.k.a classic) mtree format and
1836 * change the directory unexpectedly and so it will make a wrong
1839 if (strcmp(p, ".") != 0 && strncmp(p, "./", 2) != 0) {
1840 struct archive_string as;
1841 archive_string_init(&as);
1842 archive_strcpy(&as, "./");
1843 archive_strncat(&as, p, len);
1844 archive_string_empty(&file->parentdir);
1845 archive_string_concat(&file->parentdir, &as);
1846 archive_string_free(&as);
1847 p = file->parentdir.s;
1848 len = archive_strlen(&file->parentdir);
1852 * Find out the position which points the last position of
1853 * path separator('/').
1856 for (; *p != '\0'; p++) {
1860 if (slash == NULL) {
1861 /* The pathname doesn't have a parent directory. */
1862 file->parentdir.length = len;
1863 archive_string_copy(&(file->basename), &(file->parentdir));
1864 archive_string_empty(&(file->parentdir));
1865 *file->parentdir.s = '\0';
1869 /* Make a basename from file->parentdir.s and slash */
1871 file->parentdir.length = slash - file->parentdir.s;
1872 archive_strcpy(&(file->basename), slash + 1);
1877 mtree_entry_create_virtual_dir(struct archive_write *a, const char *pathname,
1878 struct mtree_entry **m_entry)
1880 struct archive_entry *entry;
1881 struct mtree_entry *file;
1884 entry = archive_entry_new();
1885 if (entry == NULL) {
1887 archive_set_error(&a->archive, ENOMEM,
1888 "Can't allocate memory");
1889 return (ARCHIVE_FATAL);
1891 archive_entry_copy_pathname(entry, pathname);
1892 archive_entry_set_mode(entry, AE_IFDIR | 0755);
1893 archive_entry_set_mtime(entry, time(NULL), 0);
1895 r = mtree_entry_new(a, entry, &file);
1896 archive_entry_free(entry);
1897 if (r < ARCHIVE_WARN) {
1899 archive_set_error(&a->archive, ENOMEM,
1900 "Can't allocate memory");
1901 return (ARCHIVE_FATAL);
1904 file->dir_info->virtual = 1;
1907 return (ARCHIVE_OK);
1911 mtree_entry_register_add(struct mtree_writer *mtree, struct mtree_entry *file)
1914 *mtree->file_list.last = file;
1915 mtree->file_list.last = &(file->next);
1919 mtree_entry_register_init(struct mtree_writer *mtree)
1921 mtree->file_list.first = NULL;
1922 mtree->file_list.last = &(mtree->file_list.first);
1926 mtree_entry_register_free(struct mtree_writer *mtree)
1928 struct mtree_entry *file, *file_next;
1930 file = mtree->file_list.first;
1931 while (file != NULL) {
1932 file_next = file->next;
1933 mtree_entry_free(file);
1939 mtree_entry_add_child_tail(struct mtree_entry *parent,
1940 struct mtree_entry *child)
1942 child->dir_info->chnext = NULL;
1943 *parent->dir_info->children.last = child;
1944 parent->dir_info->children.last = &(child->dir_info->chnext);
1949 * Find a entry from a parent entry with the name.
1951 static struct mtree_entry *
1952 mtree_entry_find_child(struct mtree_entry *parent, const char *child_name)
1954 struct mtree_entry *np;
1958 np = (struct mtree_entry *)__archive_rb_tree_find_node(
1959 &(parent->dir_info->rbtree), child_name);
1964 get_path_component(char *name, size_t n, const char *fn)
1969 p = strchr(fn, '/');
1971 if ((l = strlen(fn)) == 0)
1977 memcpy(name, fn, l);
1984 * Add a new entry into the tree.
1987 mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep)
1989 #if defined(_WIN32) && !defined(__CYGWIN__)
1990 char name[_MAX_FNAME];/* Included null terminator size. */
1991 #elif defined(NAME_MAX) && NAME_MAX >= 255
1992 char name[NAME_MAX+1];
1996 struct mtree_writer *mtree = (struct mtree_writer *)a->format_data;
1997 struct mtree_entry *dent, *file, *np;
2002 if (file->parentdir.length == 0 && file->basename.length == 1 &&
2003 file->basename.s[0] == '.') {
2004 file->parent = file;
2005 if (mtree->root != NULL) {
2010 mtree_entry_register_add(mtree, file);
2011 return (ARCHIVE_OK);
2014 if (file->parentdir.length == 0) {
2015 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2016 "Internal programming error "
2017 "in generating canonical name for %s",
2019 return (ARCHIVE_FAILED);
2022 fn = p = file->parentdir.s;
2025 * If the path of the parent directory of `file' entry is
2026 * the same as the path of `cur_dirent', add `file' entry to
2029 if (archive_strlen(&(mtree->cur_dirstr))
2030 == archive_strlen(&(file->parentdir)) &&
2031 strcmp(mtree->cur_dirstr.s, fn) == 0) {
2032 if (!__archive_rb_tree_insert_node(
2033 &(mtree->cur_dirent->dir_info->rbtree),
2034 (struct archive_rb_node *)file)) {
2035 /* There is the same name in the tree. */
2036 np = (struct mtree_entry *)__archive_rb_tree_find_node(
2037 &(mtree->cur_dirent->dir_info->rbtree),
2041 file->parent = mtree->cur_dirent;
2042 mtree_entry_register_add(mtree, file);
2043 return (ARCHIVE_OK);
2048 l = get_path_component(name, sizeof(name), fn);
2054 archive_set_error(&a->archive,
2056 "A name buffer is too small");
2057 return (ARCHIVE_FATAL);
2059 if (l == 1 && name[0] == '.' && dent != NULL &&
2060 dent == mtree->root) {
2067 np = mtree_entry_find_child(dent, name);
2068 if (np == NULL || fn[0] == '\0')
2071 /* Find next sub directory. */
2072 if (!np->dir_info) {
2073 /* NOT Directory! */
2074 archive_set_error(&a->archive,
2076 "`%s' is not directory, we cannot insert `%s' ",
2077 np->pathname.s, file->pathname.s);
2078 return (ARCHIVE_FAILED);
2087 * Create virtual parent directories.
2089 while (fn[0] != '\0') {
2090 struct mtree_entry *vp;
2091 struct archive_string as;
2093 archive_string_init(&as);
2094 archive_strncat(&as, p, fn - p + l);
2095 if (as.s[as.length-1] == '/') {
2096 as.s[as.length-1] = '\0';
2099 r = mtree_entry_create_virtual_dir(a, as.s, &vp);
2100 archive_string_free(&as);
2101 if (r < ARCHIVE_WARN)
2104 if (strcmp(vp->pathname.s, ".") == 0) {
2108 __archive_rb_tree_insert_node(
2109 &(dent->dir_info->rbtree),
2110 (struct archive_rb_node *)vp);
2113 mtree_entry_register_add(mtree, vp);
2119 l = get_path_component(name, sizeof(name), fn);
2121 archive_string_free(&as);
2122 archive_set_error(&a->archive,
2124 "A name buffer is too small");
2125 return (ARCHIVE_FATAL);
2130 /* Found out the parent directory where `file' can be
2132 mtree->cur_dirent = dent;
2133 archive_string_empty(&(mtree->cur_dirstr));
2134 archive_string_ensure(&(mtree->cur_dirstr),
2135 archive_strlen(&(dent->parentdir)) +
2136 archive_strlen(&(dent->basename)) + 2);
2137 if (archive_strlen(&(dent->parentdir)) +
2138 archive_strlen(&(dent->basename)) == 0)
2139 mtree->cur_dirstr.s[0] = 0;
2141 if (archive_strlen(&(dent->parentdir)) > 0) {
2142 archive_string_copy(&(mtree->cur_dirstr),
2143 &(dent->parentdir));
2144 archive_strappend_char(
2145 &(mtree->cur_dirstr), '/');
2147 archive_string_concat(&(mtree->cur_dirstr),
2151 if (!__archive_rb_tree_insert_node(
2152 &(dent->dir_info->rbtree),
2153 (struct archive_rb_node *)file)) {
2154 np = (struct mtree_entry *)__archive_rb_tree_find_node(
2155 &(dent->dir_info->rbtree), file->basename.s);
2158 file->parent = dent;
2159 mtree_entry_register_add(mtree, file);
2160 return (ARCHIVE_OK);
2165 * We have already has the entry the filename of which is
2168 r = mtree_entry_exchange_same_entry(a, np, file);
2169 if (r < ARCHIVE_WARN)
2172 np->dir_info->virtual = 0;
2174 mtree_entry_free(file);
2175 return (ARCHIVE_WARN);
2179 mtree_entry_exchange_same_entry(struct archive_write *a, struct mtree_entry *np,
2180 struct mtree_entry *file)
2183 if ((np->mode & AE_IFMT) != (file->mode & AE_IFMT)) {
2184 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2185 "Found duplicate entries `%s' and its file type is "
2188 return (ARCHIVE_FAILED);
2191 /* Update the existent mtree entry's attributes by the new one's. */
2192 archive_string_empty(&np->symlink);
2193 archive_string_concat(&np->symlink, &file->symlink);
2194 archive_string_empty(&np->uname);
2195 archive_string_concat(&np->uname, &file->uname);
2196 archive_string_empty(&np->gname);
2197 archive_string_concat(&np->gname, &file->gname);
2198 archive_string_empty(&np->fflags_text);
2199 archive_string_concat(&np->fflags_text, &file->fflags_text);
2200 np->nlink = file->nlink;
2201 np->filetype = file->filetype;
2202 np->mode = file->mode;
2203 np->size = file->size;
2204 np->uid = file->uid;
2205 np->gid = file->gid;
2206 np->fflags_set = file->fflags_set;
2207 np->fflags_clear = file->fflags_clear;
2208 np->mtime = file->mtime;
2209 np->mtime_nsec = file->mtime_nsec;
2210 np->rdevmajor = file->rdevmajor;
2211 np->rdevminor = file->rdevminor;
2212 np->devmajor = file->devmajor;
2213 np->devminor = file->devminor;
2214 np->ino = file->ino;
2216 return (ARCHIVE_WARN);