1 /*- 2 * Copyright (c) 2008 Joerg Sonnenberger 3 * Copyright (c) 2009-2012 Michihiro NAKAJIMA 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "archive_platform.h" 28 29 #ifdef HAVE_SYS_TYPES_H 30 #include <sys/types.h> 31 #endif 32 #include <errno.h> 33 #include <stdlib.h> 34 #include <string.h> 35 36 #include "archive.h" 37 #include "archive_digest_private.h" 38 #include "archive_entry.h" 39 #include "archive_entry_private.h" 40 #include "archive_private.h" 41 #include "archive_rb.h" 42 #include "archive_string.h" 43 #include "archive_write_private.h" 44 45 #define INDENTNAMELEN 15 46 #define MAXLINELEN 80 47 #define SET_KEYS \ 48 (F_FLAGS | F_GID | F_GNAME | F_MODE | F_TYPE | F_UID | F_UNAME) 49 50 struct attr_counter { 51 struct attr_counter *prev; 52 struct attr_counter *next; 53 struct mtree_entry *m_entry; 54 int count; 55 }; 56 57 struct 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; 62 }; 63 64 struct mtree_chain { 65 struct mtree_entry *first; 66 struct mtree_entry **last; 67 }; 68 69 /* 70 * The Data only for a directory file. 71 */ 72 struct dir_info { 73 struct archive_rb_tree rbtree; 74 struct mtree_chain children; 75 struct mtree_entry *chnext; 76 int virtual; 77 }; 78 79 /* 80 * The Data only for a regular file. 81 */ 82 struct reg_info { 83 int compute_sum; 84 uint32_t crc; 85 struct ae_digest digest; 86 }; 87 88 struct mtree_entry { 89 struct archive_rb_node rbnode; 90 struct mtree_entry *next; 91 struct mtree_entry *parent; 92 struct dir_info *dir_info; 93 struct reg_info *reg_info; 94 95 struct archive_string parentdir; 96 struct archive_string basename; 97 struct archive_string pathname; 98 struct archive_string symlink; 99 struct archive_string uname; 100 struct archive_string gname; 101 struct archive_string fflags_text; 102 unsigned int nlink; 103 mode_t filetype; 104 mode_t mode; 105 int64_t size; 106 int64_t uid; 107 int64_t gid; 108 time_t mtime; 109 long mtime_nsec; 110 unsigned long fflags_set; 111 unsigned long fflags_clear; 112 dev_t rdevmajor; 113 dev_t rdevminor; 114 dev_t devmajor; 115 dev_t devminor; 116 int64_t ino; 117 }; 118 119 struct mtree_writer { 120 struct mtree_entry *mtree_entry; 121 struct mtree_entry *root; 122 struct mtree_entry *cur_dirent; 123 struct archive_string cur_dirstr; 124 struct mtree_chain file_list; 125 126 struct archive_string ebuf; 127 struct archive_string buf; 128 int first; 129 uint64_t entry_bytes_remaining; 130 131 /* 132 * Set global value. 133 */ 134 struct { 135 int processing; 136 mode_t type; 137 int keys; 138 int64_t uid; 139 int64_t gid; 140 mode_t mode; 141 unsigned long fflags_set; 142 unsigned long fflags_clear; 143 } set; 144 struct att_counter_set acs; 145 int classic; 146 int depth; 147 148 /* check sum */ 149 int compute_sum; 150 uint32_t crc; 151 uint64_t crc_len; 152 #ifdef ARCHIVE_HAS_MD5 153 archive_md5_ctx md5ctx; 154 #endif 155 #ifdef ARCHIVE_HAS_RMD160 156 archive_rmd160_ctx rmd160ctx; 157 #endif 158 #ifdef ARCHIVE_HAS_SHA1 159 archive_sha1_ctx sha1ctx; 160 #endif 161 #ifdef ARCHIVE_HAS_SHA256 162 archive_sha256_ctx sha256ctx; 163 #endif 164 #ifdef ARCHIVE_HAS_SHA384 165 archive_sha384_ctx sha384ctx; 166 #endif 167 #ifdef ARCHIVE_HAS_SHA512 168 archive_sha512_ctx sha512ctx; 169 #endif 170 /* Keyword options */ 171 int keys; 172 #define F_CKSUM 0x00000001 /* checksum */ 173 #define F_DEV 0x00000002 /* device type */ 174 #define F_DONE 0x00000004 /* directory done */ 175 #define F_FLAGS 0x00000008 /* file flags */ 176 #define F_GID 0x00000010 /* gid */ 177 #define F_GNAME 0x00000020 /* group name */ 178 #define F_IGN 0x00000040 /* ignore */ 179 #define F_MAGIC 0x00000080 /* name has magic chars */ 180 #define F_MD5 0x00000100 /* MD5 digest */ 181 #define F_MODE 0x00000200 /* mode */ 182 #define F_NLINK 0x00000400 /* number of links */ 183 #define F_NOCHANGE 0x00000800 /* If owner/mode "wrong", do 184 * not change */ 185 #define F_OPT 0x00001000 /* existence optional */ 186 #define F_RMD160 0x00002000 /* RIPEMD160 digest */ 187 #define F_SHA1 0x00004000 /* SHA-1 digest */ 188 #define F_SIZE 0x00008000 /* size */ 189 #define F_SLINK 0x00010000 /* symbolic link */ 190 #define F_TAGS 0x00020000 /* tags */ 191 #define F_TIME 0x00040000 /* modification time */ 192 #define F_TYPE 0x00080000 /* file type */ 193 #define F_UID 0x00100000 /* uid */ 194 #define F_UNAME 0x00200000 /* user name */ 195 #define F_VISIT 0x00400000 /* file visited */ 196 #define F_SHA256 0x00800000 /* SHA-256 digest */ 197 #define F_SHA384 0x01000000 /* SHA-384 digest */ 198 #define F_SHA512 0x02000000 /* SHA-512 digest */ 199 #define F_INO 0x04000000 /* inode number */ 200 #define F_RESDEV 0x08000000 /* device ID on which the 201 * entry resides */ 202 203 /* Options */ 204 int dironly; /* If it is set, ignore all files except 205 * directory files, like mtree(8) -d option. */ 206 int indent; /* If it is set, indent output data. */ 207 int output_global_set; /* If it is set, use /set keyword to set 208 * global values. When generating mtree 209 * classic format, it is set by default. */ 210 }; 211 212 #define DEFAULT_KEYS (F_DEV | F_FLAGS | F_GID | F_GNAME | F_SLINK | F_MODE\ 213 | F_NLINK | F_SIZE | F_TIME | F_TYPE | F_UID\ 214 | F_UNAME) 215 #define attr_counter_set_reset attr_counter_set_free 216 217 static void attr_counter_free(struct attr_counter **); 218 static int attr_counter_inc(struct attr_counter **, struct attr_counter *, 219 struct attr_counter *, struct mtree_entry *); 220 static struct attr_counter * attr_counter_new(struct mtree_entry *, 221 struct attr_counter *); 222 static int attr_counter_set_collect(struct mtree_writer *, 223 struct mtree_entry *); 224 static void attr_counter_set_free(struct mtree_writer *); 225 static int get_global_set_keys(struct mtree_writer *, struct mtree_entry *); 226 static int mtree_entry_add_child_tail(struct mtree_entry *, 227 struct mtree_entry *); 228 static int mtree_entry_create_virtual_dir(struct archive_write *, const char *, 229 struct mtree_entry **); 230 static int mtree_entry_cmp_node(const struct archive_rb_node *, 231 const struct archive_rb_node *); 232 static int mtree_entry_cmp_key(const struct archive_rb_node *, const void *); 233 static int mtree_entry_exchange_same_entry(struct archive_write *, 234 struct mtree_entry *, struct mtree_entry *); 235 static void mtree_entry_free(struct mtree_entry *); 236 static int mtree_entry_new(struct archive_write *, struct archive_entry *, 237 struct mtree_entry **); 238 static void mtree_entry_register_free(struct mtree_writer *); 239 static void mtree_entry_register_init(struct mtree_writer *); 240 static int mtree_entry_setup_filenames(struct archive_write *, 241 struct mtree_entry *, struct archive_entry *); 242 static int mtree_entry_tree_add(struct archive_write *, struct mtree_entry **); 243 static void sum_init(struct mtree_writer *); 244 static void sum_update(struct mtree_writer *, const void *, size_t); 245 static void sum_final(struct mtree_writer *, struct reg_info *); 246 static void sum_write(struct archive_string *, struct reg_info *); 247 static int write_mtree_entry(struct archive_write *, struct mtree_entry *); 248 static int write_dot_dot_entry(struct archive_write *, struct mtree_entry *); 249 250 #define COMPUTE_CRC(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)] 251 static const uint32_t crctab[] = { 252 0x0, 253 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 254 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 255 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 256 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 257 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, 258 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 259 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 260 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 261 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 262 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, 263 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 264 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 265 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 266 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 267 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 268 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 269 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 270 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 271 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 272 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 273 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 274 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 275 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 276 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, 277 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 278 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 279 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 280 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 281 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, 282 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 283 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 284 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 285 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 286 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 287 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 288 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 289 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 290 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 291 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 292 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 293 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 294 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, 295 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 296 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 297 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 298 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 299 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 300 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, 301 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 302 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 303 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 304 }; 305 306 static const unsigned char safe_char[256] = { 307 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */ 308 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */ 309 /* !"$%&'()*+,-./ EXCLUSION:0x20( ) 0x23(#) */ 310 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */ 311 /* 0123456789:;<>? EXCLUSION:0x3d(=) */ 312 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, /* 30 - 3F */ 313 /* @ABCDEFGHIJKLMNO */ 314 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */ 315 /* PQRSTUVWXYZ[]^_ EXCLUSION:0x5c(\) */ 316 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, /* 50 - 5F */ 317 /* `abcdefghijklmno */ 318 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */ 319 /* pqrstuvwxyz{|}~ */ 320 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* 70 - 7F */ 321 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */ 322 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */ 323 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */ 324 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */ 325 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */ 326 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */ 327 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */ 328 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */ 329 }; 330 331 static void 332 mtree_quote(struct archive_string *s, const char *str) 333 { 334 const char *start; 335 char buf[4]; 336 unsigned char c; 337 338 for (start = str; *str != '\0'; ++str) { 339 if (safe_char[*(const unsigned char *)str]) 340 continue; 341 if (start != str) 342 archive_strncat(s, start, str - start); 343 c = (unsigned char)*str; 344 buf[0] = '\\'; 345 buf[1] = (c / 64) + '0'; 346 buf[2] = (c / 8 % 8) + '0'; 347 buf[3] = (c % 8) + '0'; 348 archive_strncat(s, buf, 4); 349 start = str + 1; 350 } 351 352 if (start != str) 353 archive_strncat(s, start, str - start); 354 } 355 356 /* 357 * Indent a line as the mtree utility does so it is readable for people. 358 */ 359 static void 360 mtree_indent(struct mtree_writer *mtree) 361 { 362 int i, fn, nd, pd; 363 const char *r, *s, *x; 364 365 if (mtree->classic) { 366 if (mtree->indent) { 367 nd = 0; 368 pd = mtree->depth * 4; 369 } else { 370 nd = mtree->depth?4:0; 371 pd = 0; 372 } 373 } else 374 nd = pd = 0; 375 fn = 1; 376 s = r = mtree->ebuf.s; 377 x = NULL; 378 while (*r == ' ') 379 r++; 380 while ((r = strchr(r, ' ')) != NULL) { 381 if (fn) { 382 fn = 0; 383 for (i = 0; i < nd + pd; i++) 384 archive_strappend_char(&mtree->buf, ' '); 385 archive_strncat(&mtree->buf, s, r - s); 386 if (nd + (r -s) > INDENTNAMELEN) { 387 archive_strncat(&mtree->buf, " \\\n", 3); 388 for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++) 389 archive_strappend_char(&mtree->buf, ' '); 390 } else { 391 for (i = (int)(r -s + nd); 392 i < (INDENTNAMELEN + 1); i++) 393 archive_strappend_char(&mtree->buf, ' '); 394 } 395 s = ++r; 396 x = NULL; 397 continue; 398 } 399 if (pd + (r - s) <= MAXLINELEN - 3 - INDENTNAMELEN) 400 x = r++; 401 else { 402 if (x == NULL) 403 x = r; 404 archive_strncat(&mtree->buf, s, x - s); 405 archive_strncat(&mtree->buf, " \\\n", 3); 406 for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++) 407 archive_strappend_char(&mtree->buf, ' '); 408 s = r = ++x; 409 x = NULL; 410 } 411 } 412 if (fn) { 413 for (i = 0; i < nd + pd; i++) 414 archive_strappend_char(&mtree->buf, ' '); 415 archive_strcat(&mtree->buf, s); 416 s += strlen(s); 417 } 418 if (x != NULL && pd + strlen(s) > MAXLINELEN - 3 - INDENTNAMELEN) { 419 /* Last keyword is longer. */ 420 archive_strncat(&mtree->buf, s, x - s); 421 archive_strncat(&mtree->buf, " \\\n", 3); 422 for (i = 0; i < (INDENTNAMELEN + 1 + pd); i++) 423 archive_strappend_char(&mtree->buf, ' '); 424 s = ++x; 425 } 426 archive_strcat(&mtree->buf, s); 427 archive_string_empty(&mtree->ebuf); 428 } 429 430 /* 431 * Write /set keyword. 432 * Set the most used value of uid, gid, mode and fflags, which are 433 * collected by the attr_counter_set_collect() function. 434 */ 435 static void 436 write_global(struct mtree_writer *mtree) 437 { 438 struct archive_string setstr; 439 struct archive_string unsetstr; 440 struct att_counter_set *acs; 441 int keys, oldkeys, effkeys; 442 443 archive_string_init(&setstr); 444 archive_string_init(&unsetstr); 445 keys = mtree->keys & SET_KEYS; 446 oldkeys = mtree->set.keys; 447 effkeys = keys; 448 acs = &mtree->acs; 449 if (mtree->set.processing) { 450 /* 451 * Check if the global data needs updating. 452 */ 453 effkeys &= ~F_TYPE; 454 if (acs->uid_list == NULL) 455 effkeys &= ~(F_UNAME | F_UID); 456 else if (oldkeys & (F_UNAME | F_UID)) { 457 if (acs->uid_list->count < 2 || 458 mtree->set.uid == acs->uid_list->m_entry->uid) 459 effkeys &= ~(F_UNAME | F_UID); 460 } 461 if (acs->gid_list == NULL) 462 effkeys &= ~(F_GNAME | F_GID); 463 else if (oldkeys & (F_GNAME | F_GID)) { 464 if (acs->gid_list->count < 2 || 465 mtree->set.gid == acs->gid_list->m_entry->gid) 466 effkeys &= ~(F_GNAME | F_GID); 467 } 468 if (acs->mode_list == NULL) 469 effkeys &= ~F_MODE; 470 else if (oldkeys & F_MODE) { 471 if (acs->mode_list->count < 2 || 472 mtree->set.mode == acs->mode_list->m_entry->mode) 473 effkeys &= ~F_MODE; 474 } 475 if (acs->flags_list == NULL) 476 effkeys &= ~F_FLAGS; 477 else if ((oldkeys & F_FLAGS) != 0) { 478 if (acs->flags_list->count < 2 || 479 (acs->flags_list->m_entry->fflags_set == 480 mtree->set.fflags_set && 481 acs->flags_list->m_entry->fflags_clear == 482 mtree->set.fflags_clear)) 483 effkeys &= ~F_FLAGS; 484 } 485 } else { 486 if (acs->uid_list == NULL) 487 keys &= ~(F_UNAME | F_UID); 488 if (acs->gid_list == NULL) 489 keys &= ~(F_GNAME | F_GID); 490 if (acs->mode_list == NULL) 491 keys &= ~F_MODE; 492 if (acs->flags_list == NULL) 493 keys &= ~F_FLAGS; 494 } 495 if ((keys & effkeys & F_TYPE) != 0) { 496 if (mtree->dironly) { 497 archive_strcat(&setstr, " type=dir"); 498 mtree->set.type = AE_IFDIR; 499 } else { 500 archive_strcat(&setstr, " type=file"); 501 mtree->set.type = AE_IFREG; 502 } 503 } 504 if ((keys & effkeys & F_UNAME) != 0) { 505 if (archive_strlen(&(acs->uid_list->m_entry->uname)) > 0) { 506 archive_strcat(&setstr, " uname="); 507 mtree_quote(&setstr, acs->uid_list->m_entry->uname.s); 508 } else { 509 keys &= ~F_UNAME; 510 if ((oldkeys & F_UNAME) != 0) 511 archive_strcat(&unsetstr, " uname"); 512 } 513 } 514 if ((keys & effkeys & F_UID) != 0) { 515 mtree->set.uid = acs->uid_list->m_entry->uid; 516 archive_string_sprintf(&setstr, " uid=%jd", 517 (intmax_t)mtree->set.uid); 518 } 519 if ((keys & effkeys & F_GNAME) != 0) { 520 if (archive_strlen(&(acs->gid_list->m_entry->gname)) > 0) { 521 archive_strcat(&setstr, " gname="); 522 mtree_quote(&setstr, acs->gid_list->m_entry->gname.s); 523 } else { 524 keys &= ~F_GNAME; 525 if ((oldkeys & F_GNAME) != 0) 526 archive_strcat(&unsetstr, " gname"); 527 } 528 } 529 if ((keys & effkeys & F_GID) != 0) { 530 mtree->set.gid = acs->gid_list->m_entry->gid; 531 archive_string_sprintf(&setstr, " gid=%jd", 532 (intmax_t)mtree->set.gid); 533 } 534 if ((keys & effkeys & F_MODE) != 0) { 535 mtree->set.mode = acs->mode_list->m_entry->mode; 536 archive_string_sprintf(&setstr, " mode=%o", 537 (unsigned int)mtree->set.mode); 538 } 539 if ((keys & effkeys & F_FLAGS) != 0) { 540 if (archive_strlen( 541 &(acs->flags_list->m_entry->fflags_text)) > 0) { 542 archive_strcat(&setstr, " flags="); 543 mtree_quote(&setstr, 544 acs->flags_list->m_entry->fflags_text.s); 545 mtree->set.fflags_set = 546 acs->flags_list->m_entry->fflags_set; 547 mtree->set.fflags_clear = 548 acs->flags_list->m_entry->fflags_clear; 549 } else { 550 keys &= ~F_FLAGS; 551 if ((oldkeys & F_FLAGS) != 0) 552 archive_strcat(&unsetstr, " flags"); 553 } 554 } 555 if (unsetstr.length > 0) 556 archive_string_sprintf(&mtree->buf, "/unset%s\n", unsetstr.s); 557 archive_string_free(&unsetstr); 558 if (setstr.length > 0) 559 archive_string_sprintf(&mtree->buf, "/set%s\n", setstr.s); 560 archive_string_free(&setstr); 561 mtree->set.keys = keys; 562 mtree->set.processing = 1; 563 } 564 565 static struct attr_counter * 566 attr_counter_new(struct mtree_entry *me, struct attr_counter *prev) 567 { 568 struct attr_counter *ac; 569 570 ac = malloc(sizeof(*ac)); 571 if (ac != NULL) { 572 ac->prev = prev; 573 ac->next = NULL; 574 ac->count = 1; 575 ac->m_entry = me; 576 } 577 return (ac); 578 } 579 580 static void 581 attr_counter_free(struct attr_counter **top) 582 { 583 struct attr_counter *ac, *tac; 584 585 if (*top == NULL) 586 return; 587 ac = *top; 588 while (ac != NULL) { 589 tac = ac->next; 590 free(ac); 591 ac = tac; 592 } 593 *top = NULL; 594 } 595 596 static int 597 attr_counter_inc(struct attr_counter **top, struct attr_counter *ac, 598 struct attr_counter *last, struct mtree_entry *me) 599 { 600 struct attr_counter *pac; 601 602 if (ac != NULL) { 603 ac->count++; 604 if (*top == ac || ac->prev->count >= ac->count) 605 return (0); 606 for (pac = ac->prev; pac; pac = pac->prev) { 607 if (pac->count >= ac->count) 608 break; 609 } 610 ac->prev->next = ac->next; 611 if (ac->next != NULL) 612 ac->next->prev = ac->prev; 613 if (pac != NULL) { 614 ac->prev = pac; 615 ac->next = pac->next; 616 pac->next = ac; 617 if (ac->next != NULL) 618 ac->next->prev = ac; 619 } else { 620 ac->prev = NULL; 621 ac->next = *top; 622 *top = ac; 623 ac->next->prev = ac; 624 } 625 } else if (last != NULL) { 626 ac = attr_counter_new(me, last); 627 if (ac == NULL) 628 return (-1); 629 last->next = ac; 630 } 631 return (0); 632 } 633 634 /* 635 * Tabulate uid, gid, mode and fflags of a entry in order to be used for /set. 636 */ 637 static int 638 attr_counter_set_collect(struct mtree_writer *mtree, struct mtree_entry *me) 639 { 640 struct attr_counter *ac, *last; 641 struct att_counter_set *acs = &mtree->acs; 642 int keys = mtree->keys; 643 644 if (keys & (F_UNAME | F_UID)) { 645 if (acs->uid_list == NULL) { 646 acs->uid_list = attr_counter_new(me, NULL); 647 if (acs->uid_list == NULL) 648 return (-1); 649 } else { 650 last = NULL; 651 for (ac = acs->uid_list; ac; ac = ac->next) { 652 if (ac->m_entry->uid == me->uid) 653 break; 654 last = ac; 655 } 656 if (attr_counter_inc(&acs->uid_list, ac, last, me) < 0) 657 return (-1); 658 } 659 } 660 if (keys & (F_GNAME | F_GID)) { 661 if (acs->gid_list == NULL) { 662 acs->gid_list = attr_counter_new(me, NULL); 663 if (acs->gid_list == NULL) 664 return (-1); 665 } else { 666 last = NULL; 667 for (ac = acs->gid_list; ac; ac = ac->next) { 668 if (ac->m_entry->gid == me->gid) 669 break; 670 last = ac; 671 } 672 if (attr_counter_inc(&acs->gid_list, ac, last, me) < 0) 673 return (-1); 674 } 675 } 676 if (keys & F_MODE) { 677 if (acs->mode_list == NULL) { 678 acs->mode_list = attr_counter_new(me, NULL); 679 if (acs->mode_list == NULL) 680 return (-1); 681 } else { 682 last = NULL; 683 for (ac = acs->mode_list; ac; ac = ac->next) { 684 if (ac->m_entry->mode == me->mode) 685 break; 686 last = ac; 687 } 688 if (attr_counter_inc(&acs->mode_list, ac, last, me) < 0) 689 return (-1); 690 } 691 } 692 if (keys & F_FLAGS) { 693 if (acs->flags_list == NULL) { 694 acs->flags_list = attr_counter_new(me, NULL); 695 if (acs->flags_list == NULL) 696 return (-1); 697 } else { 698 last = NULL; 699 for (ac = acs->flags_list; ac; ac = ac->next) { 700 if (ac->m_entry->fflags_set == me->fflags_set && 701 ac->m_entry->fflags_clear == 702 me->fflags_clear) 703 break; 704 last = ac; 705 } 706 if (attr_counter_inc(&acs->flags_list, ac, last, me) < 0) 707 return (-1); 708 } 709 } 710 711 return (0); 712 } 713 714 static void 715 attr_counter_set_free(struct mtree_writer *mtree) 716 { 717 struct att_counter_set *acs = &mtree->acs; 718 719 attr_counter_free(&acs->uid_list); 720 attr_counter_free(&acs->gid_list); 721 attr_counter_free(&acs->mode_list); 722 attr_counter_free(&acs->flags_list); 723 } 724 725 static int 726 get_global_set_keys(struct mtree_writer *mtree, struct mtree_entry *me) 727 { 728 int keys; 729 730 keys = mtree->keys; 731 732 /* 733 * If a keyword has been set by /set, we do not need to 734 * output it. 735 */ 736 if (mtree->set.keys == 0) 737 return (keys);/* /set is not used. */ 738 739 if ((mtree->set.keys & (F_GNAME | F_GID)) != 0 && 740 mtree->set.gid == me->gid) 741 keys &= ~(F_GNAME | F_GID); 742 if ((mtree->set.keys & (F_UNAME | F_UID)) != 0 && 743 mtree->set.uid == me->uid) 744 keys &= ~(F_UNAME | F_UID); 745 if (mtree->set.keys & F_FLAGS) { 746 if (mtree->set.fflags_set == me->fflags_set && 747 mtree->set.fflags_clear == me->fflags_clear) 748 keys &= ~F_FLAGS; 749 } 750 if ((mtree->set.keys & F_MODE) != 0 && mtree->set.mode == me->mode) 751 keys &= ~F_MODE; 752 753 switch (me->filetype) { 754 case AE_IFLNK: case AE_IFSOCK: case AE_IFCHR: 755 case AE_IFBLK: case AE_IFIFO: 756 break; 757 case AE_IFDIR: 758 if ((mtree->set.keys & F_TYPE) != 0 && 759 mtree->set.type == AE_IFDIR) 760 keys &= ~F_TYPE; 761 break; 762 case AE_IFREG: 763 default: /* Handle unknown file types as regular files. */ 764 if ((mtree->set.keys & F_TYPE) != 0 && 765 mtree->set.type == AE_IFREG) 766 keys &= ~F_TYPE; 767 break; 768 } 769 770 return (keys); 771 } 772 773 static int 774 mtree_entry_new(struct archive_write *a, struct archive_entry *entry, 775 struct mtree_entry **m_entry) 776 { 777 struct mtree_entry *me; 778 const char *s; 779 int r; 780 static const struct archive_rb_tree_ops rb_ops = { 781 mtree_entry_cmp_node, mtree_entry_cmp_key 782 }; 783 784 me = calloc(1, sizeof(*me)); 785 if (me == NULL) { 786 archive_set_error(&a->archive, ENOMEM, 787 "Can't allocate memory for a mtree entry"); 788 *m_entry = NULL; 789 return (ARCHIVE_FATAL); 790 } 791 792 r = mtree_entry_setup_filenames(a, me, entry); 793 if (r < ARCHIVE_WARN) { 794 mtree_entry_free(me); 795 *m_entry = NULL; 796 return (r); 797 } 798 799 if ((s = archive_entry_symlink(entry)) != NULL) 800 archive_strcpy(&me->symlink, s); 801 me->nlink = archive_entry_nlink(entry); 802 me->filetype = archive_entry_filetype(entry); 803 me->mode = archive_entry_mode(entry) & 07777; 804 me->uid = archive_entry_uid(entry); 805 me->gid = archive_entry_gid(entry); 806 if ((s = archive_entry_uname(entry)) != NULL) 807 archive_strcpy(&me->uname, s); 808 if ((s = archive_entry_gname(entry)) != NULL) 809 archive_strcpy(&me->gname, s); 810 if ((s = archive_entry_fflags_text(entry)) != NULL) 811 archive_strcpy(&me->fflags_text, s); 812 archive_entry_fflags(entry, &me->fflags_set, &me->fflags_clear); 813 me->mtime = archive_entry_mtime(entry); 814 me->mtime_nsec = archive_entry_mtime_nsec(entry); 815 me->rdevmajor = archive_entry_rdevmajor(entry); 816 me->rdevminor = archive_entry_rdevminor(entry); 817 me->devmajor = archive_entry_devmajor(entry); 818 me->devminor = archive_entry_devminor(entry); 819 me->ino = archive_entry_ino(entry); 820 me->size = archive_entry_size(entry); 821 if (me->filetype == AE_IFDIR) { 822 me->dir_info = calloc(1, sizeof(*me->dir_info)); 823 if (me->dir_info == NULL) { 824 mtree_entry_free(me); 825 archive_set_error(&a->archive, ENOMEM, 826 "Can't allocate memory for a mtree entry"); 827 *m_entry = NULL; 828 return (ARCHIVE_FATAL); 829 } 830 __archive_rb_tree_init(&me->dir_info->rbtree, &rb_ops); 831 me->dir_info->children.first = NULL; 832 me->dir_info->children.last = &(me->dir_info->children.first); 833 me->dir_info->chnext = NULL; 834 } else if (me->filetype == AE_IFREG) { 835 me->reg_info = calloc(1, sizeof(*me->reg_info)); 836 if (me->reg_info == NULL) { 837 mtree_entry_free(me); 838 archive_set_error(&a->archive, ENOMEM, 839 "Can't allocate memory for a mtree entry"); 840 *m_entry = NULL; 841 return (ARCHIVE_FATAL); 842 } 843 me->reg_info->compute_sum = 0; 844 } 845 846 *m_entry = me; 847 return (ARCHIVE_OK); 848 } 849 850 static void 851 mtree_entry_free(struct mtree_entry *me) 852 { 853 archive_string_free(&me->parentdir); 854 archive_string_free(&me->basename); 855 archive_string_free(&me->pathname); 856 archive_string_free(&me->symlink); 857 archive_string_free(&me->uname); 858 archive_string_free(&me->gname); 859 archive_string_free(&me->fflags_text); 860 free(me->dir_info); 861 free(me->reg_info); 862 free(me); 863 } 864 865 static int 866 archive_write_mtree_header(struct archive_write *a, 867 struct archive_entry *entry) 868 { 869 struct mtree_writer *mtree= a->format_data; 870 struct mtree_entry *mtree_entry; 871 int r, r2; 872 873 if (mtree->first) { 874 mtree->first = 0; 875 archive_strcat(&mtree->buf, "#mtree\n"); 876 if ((mtree->keys & SET_KEYS) == 0) 877 mtree->output_global_set = 0;/* Disabled. */ 878 } 879 880 mtree->entry_bytes_remaining = archive_entry_size(entry); 881 882 /* While directory only mode, we do not handle non directory files. */ 883 if (mtree->dironly && archive_entry_filetype(entry) != AE_IFDIR) 884 return (ARCHIVE_OK); 885 886 r2 = mtree_entry_new(a, entry, &mtree_entry); 887 if (r2 < ARCHIVE_WARN) 888 return (r2); 889 r = mtree_entry_tree_add(a, &mtree_entry); 890 if (r < ARCHIVE_WARN) { 891 mtree_entry_free(mtree_entry); 892 return (r); 893 } 894 mtree->mtree_entry = mtree_entry; 895 896 /* If the current file is a regular file, we have to 897 * compute the sum of its content. 898 * Initialize a bunch of checksum context. */ 899 if (mtree_entry->reg_info) 900 sum_init(mtree); 901 902 return (r2); 903 } 904 905 static int 906 write_mtree_entry(struct archive_write *a, struct mtree_entry *me) 907 { 908 struct mtree_writer *mtree = a->format_data; 909 struct archive_string *str; 910 int keys, ret; 911 912 if (me->dir_info) { 913 if (mtree->classic) { 914 /* 915 * Output a comment line to describe the full 916 * pathname of the entry as mtree utility does 917 * while generating classic format. 918 */ 919 if (!mtree->dironly) 920 archive_strappend_char(&mtree->buf, '\n'); 921 if (me->parentdir.s) 922 archive_string_sprintf(&mtree->buf, 923 "# %s/%s\n", 924 me->parentdir.s, me->basename.s); 925 else 926 archive_string_sprintf(&mtree->buf, 927 "# %s\n", 928 me->basename.s); 929 } 930 if (mtree->output_global_set) 931 write_global(mtree); 932 } 933 archive_string_empty(&mtree->ebuf); 934 str = (mtree->indent || mtree->classic)? &mtree->ebuf : &mtree->buf; 935 936 if (!mtree->classic && me->parentdir.s) { 937 /* 938 * If generating format is not classic one(v1), output 939 * a full pathname. 940 */ 941 mtree_quote(str, me->parentdir.s); 942 archive_strappend_char(str, '/'); 943 } 944 mtree_quote(str, me->basename.s); 945 946 keys = get_global_set_keys(mtree, me); 947 if ((keys & F_NLINK) != 0 && 948 me->nlink != 1 && me->filetype != AE_IFDIR) 949 archive_string_sprintf(str, " nlink=%u", me->nlink); 950 951 if ((keys & F_GNAME) != 0 && archive_strlen(&me->gname) > 0) { 952 archive_strcat(str, " gname="); 953 mtree_quote(str, me->gname.s); 954 } 955 if ((keys & F_UNAME) != 0 && archive_strlen(&me->uname) > 0) { 956 archive_strcat(str, " uname="); 957 mtree_quote(str, me->uname.s); 958 } 959 if ((keys & F_FLAGS) != 0) { 960 if (archive_strlen(&me->fflags_text) > 0) { 961 archive_strcat(str, " flags="); 962 mtree_quote(str, me->fflags_text.s); 963 } else if (mtree->set.processing && 964 (mtree->set.keys & F_FLAGS) != 0) 965 /* Overwrite the global parameter. */ 966 archive_strcat(str, " flags=none"); 967 } 968 if ((keys & F_TIME) != 0) 969 archive_string_sprintf(str, " time=%jd.%jd", 970 (intmax_t)me->mtime, (intmax_t)me->mtime_nsec); 971 if ((keys & F_MODE) != 0) 972 archive_string_sprintf(str, " mode=%o", (unsigned int)me->mode); 973 if ((keys & F_GID) != 0) 974 archive_string_sprintf(str, " gid=%jd", (intmax_t)me->gid); 975 if ((keys & F_UID) != 0) 976 archive_string_sprintf(str, " uid=%jd", (intmax_t)me->uid); 977 978 if ((keys & F_INO) != 0) 979 archive_string_sprintf(str, " inode=%jd", (intmax_t)me->ino); 980 if ((keys & F_RESDEV) != 0) { 981 archive_string_sprintf(str, 982 " resdevice=native,%ju,%ju", 983 (uintmax_t)me->devmajor, 984 (uintmax_t)me->devminor); 985 } 986 987 switch (me->filetype) { 988 case AE_IFLNK: 989 if ((keys & F_TYPE) != 0) 990 archive_strcat(str, " type=link"); 991 if ((keys & F_SLINK) != 0) { 992 archive_strcat(str, " link="); 993 mtree_quote(str, me->symlink.s); 994 } 995 break; 996 case AE_IFSOCK: 997 if ((keys & F_TYPE) != 0) 998 archive_strcat(str, " type=socket"); 999 break; 1000 case AE_IFCHR: 1001 if ((keys & F_TYPE) != 0) 1002 archive_strcat(str, " type=char"); 1003 if ((keys & F_DEV) != 0) { 1004 archive_string_sprintf(str, 1005 " device=native,%ju,%ju", 1006 (uintmax_t)me->rdevmajor, 1007 (uintmax_t)me->rdevminor); 1008 } 1009 break; 1010 case AE_IFBLK: 1011 if ((keys & F_TYPE) != 0) 1012 archive_strcat(str, " type=block"); 1013 if ((keys & F_DEV) != 0) { 1014 archive_string_sprintf(str, 1015 " device=native,%ju,%ju", 1016 (uintmax_t)me->rdevmajor, 1017 (uintmax_t)me->rdevminor); 1018 } 1019 break; 1020 case AE_IFDIR: 1021 if ((keys & F_TYPE) != 0) 1022 archive_strcat(str, " type=dir"); 1023 break; 1024 case AE_IFIFO: 1025 if ((keys & F_TYPE) != 0) 1026 archive_strcat(str, " type=fifo"); 1027 break; 1028 case AE_IFREG: 1029 default: /* Handle unknown file types as regular files. */ 1030 if ((keys & F_TYPE) != 0) 1031 archive_strcat(str, " type=file"); 1032 if ((keys & F_SIZE) != 0) 1033 archive_string_sprintf(str, " size=%jd", 1034 (intmax_t)me->size); 1035 break; 1036 } 1037 1038 /* Write a bunch of sum. */ 1039 if (me->reg_info) 1040 sum_write(str, me->reg_info); 1041 1042 archive_strappend_char(str, '\n'); 1043 if (mtree->indent || mtree->classic) 1044 mtree_indent(mtree); 1045 1046 if (mtree->buf.length > 32768) { 1047 ret = __archive_write_output( 1048 a, mtree->buf.s, mtree->buf.length); 1049 archive_string_empty(&mtree->buf); 1050 } else 1051 ret = ARCHIVE_OK; 1052 return (ret); 1053 } 1054 1055 static int 1056 write_dot_dot_entry(struct archive_write *a, struct mtree_entry *n) 1057 { 1058 struct mtree_writer *mtree = a->format_data; 1059 int ret; 1060 1061 if (n->parentdir.s) { 1062 if (mtree->indent) { 1063 int i, pd = mtree->depth * 4; 1064 for (i = 0; i < pd; i++) 1065 archive_strappend_char(&mtree->buf, ' '); 1066 } 1067 archive_string_sprintf(&mtree->buf, "# %s/%s\n", 1068 n->parentdir.s, n->basename.s); 1069 } 1070 1071 if (mtree->indent) { 1072 archive_string_empty(&mtree->ebuf); 1073 archive_strncat(&mtree->ebuf, "..\n\n", (mtree->dironly)?3:4); 1074 mtree_indent(mtree); 1075 } else 1076 archive_strncat(&mtree->buf, "..\n\n", (mtree->dironly)?3:4); 1077 1078 if (mtree->buf.length > 32768) { 1079 ret = __archive_write_output( 1080 a, mtree->buf.s, mtree->buf.length); 1081 archive_string_empty(&mtree->buf); 1082 } else 1083 ret = ARCHIVE_OK; 1084 return (ret); 1085 } 1086 1087 /* 1088 * Write mtree entries saved at attr_counter_set_collect() function. 1089 */ 1090 static int 1091 write_mtree_entry_tree(struct archive_write *a) 1092 { 1093 struct mtree_writer *mtree = a->format_data; 1094 struct mtree_entry *np = mtree->root; 1095 struct archive_rb_node *n; 1096 int ret; 1097 1098 do { 1099 if (mtree->output_global_set) { 1100 /* 1101 * Collect attribute information to know which value 1102 * is frequently used among the children. 1103 */ 1104 attr_counter_set_reset(mtree); 1105 ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) { 1106 struct mtree_entry *e = (struct mtree_entry *)n; 1107 if (attr_counter_set_collect(mtree, e) < 0) { 1108 archive_set_error(&a->archive, ENOMEM, 1109 "Can't allocate memory"); 1110 return (ARCHIVE_FATAL); 1111 } 1112 } 1113 } 1114 if (!np->dir_info->virtual || mtree->classic) { 1115 ret = write_mtree_entry(a, np); 1116 if (ret != ARCHIVE_OK) 1117 return (ARCHIVE_FATAL); 1118 } else { 1119 /* Whenever output_global_set is enabled 1120 * output global value(/set keywords) 1121 * even if the directory entry is not allowed 1122 * to be written because the global values 1123 * can be used for the children. */ 1124 if (mtree->output_global_set) 1125 write_global(mtree); 1126 } 1127 /* 1128 * Output the attribute of all files except directory files. 1129 */ 1130 mtree->depth++; 1131 ARCHIVE_RB_TREE_FOREACH(n, &(np->dir_info->rbtree)) { 1132 struct mtree_entry *e = (struct mtree_entry *)n; 1133 1134 if (e->dir_info) 1135 mtree_entry_add_child_tail(np, e); 1136 else { 1137 ret = write_mtree_entry(a, e); 1138 if (ret != ARCHIVE_OK) 1139 return (ARCHIVE_FATAL); 1140 } 1141 } 1142 mtree->depth--; 1143 1144 if (np->dir_info->children.first != NULL) { 1145 /* 1146 * Descend the tree. 1147 */ 1148 np = np->dir_info->children.first; 1149 if (mtree->indent) 1150 mtree->depth++; 1151 continue; 1152 } else if (mtree->classic) { 1153 /* 1154 * While printing mtree classic, if there are not 1155 * any directory files(except "." and "..") in the 1156 * directory, output two dots ".." as returning 1157 * the parent directory. 1158 */ 1159 ret = write_dot_dot_entry(a, np); 1160 if (ret != ARCHIVE_OK) 1161 return (ARCHIVE_FATAL); 1162 } 1163 1164 while (np != np->parent) { 1165 if (np->dir_info->chnext == NULL) { 1166 /* 1167 * Ascend the tree; go back to the parent. 1168 */ 1169 if (mtree->indent) 1170 mtree->depth--; 1171 if (mtree->classic) { 1172 ret = write_dot_dot_entry(a, 1173 np->parent); 1174 if (ret != ARCHIVE_OK) 1175 return (ARCHIVE_FATAL); 1176 } 1177 np = np->parent; 1178 } else { 1179 /* 1180 * Switch to next mtree entry in the directory. 1181 */ 1182 np = np->dir_info->chnext; 1183 break; 1184 } 1185 } 1186 } while (np != np->parent); 1187 1188 return (ARCHIVE_OK); 1189 } 1190 1191 static int 1192 archive_write_mtree_finish_entry(struct archive_write *a) 1193 { 1194 struct mtree_writer *mtree = a->format_data; 1195 struct mtree_entry *me; 1196 1197 if ((me = mtree->mtree_entry) == NULL) 1198 return (ARCHIVE_OK); 1199 mtree->mtree_entry = NULL; 1200 1201 if (me->reg_info) 1202 sum_final(mtree, me->reg_info); 1203 1204 return (ARCHIVE_OK); 1205 } 1206 1207 static int 1208 archive_write_mtree_close(struct archive_write *a) 1209 { 1210 struct mtree_writer *mtree= a->format_data; 1211 int ret; 1212 1213 if (mtree->root != NULL) { 1214 ret = write_mtree_entry_tree(a); 1215 if (ret != ARCHIVE_OK) 1216 return (ARCHIVE_FATAL); 1217 } 1218 1219 archive_write_set_bytes_in_last_block(&a->archive, 1); 1220 1221 return __archive_write_output(a, mtree->buf.s, mtree->buf.length); 1222 } 1223 1224 static ssize_t 1225 archive_write_mtree_data(struct archive_write *a, const void *buff, size_t n) 1226 { 1227 struct mtree_writer *mtree= a->format_data; 1228 1229 if (n > mtree->entry_bytes_remaining) 1230 n = (size_t)mtree->entry_bytes_remaining; 1231 mtree->entry_bytes_remaining -= n; 1232 1233 /* We don't need to compute a regular file sum */ 1234 if (mtree->mtree_entry == NULL) 1235 return (n); 1236 1237 if (mtree->mtree_entry->filetype == AE_IFREG) 1238 sum_update(mtree, buff, n); 1239 1240 return (n); 1241 } 1242 1243 static int 1244 archive_write_mtree_free(struct archive_write *a) 1245 { 1246 struct mtree_writer *mtree= a->format_data; 1247 1248 if (mtree == NULL) 1249 return (ARCHIVE_OK); 1250 1251 /* Make sure we do not leave any entries. */ 1252 mtree_entry_register_free(mtree); 1253 archive_string_free(&mtree->cur_dirstr); 1254 archive_string_free(&mtree->ebuf); 1255 archive_string_free(&mtree->buf); 1256 attr_counter_set_free(mtree); 1257 free(mtree); 1258 a->format_data = NULL; 1259 return (ARCHIVE_OK); 1260 } 1261 1262 static int 1263 archive_write_mtree_options(struct archive_write *a, const char *key, 1264 const char *value) 1265 { 1266 struct mtree_writer *mtree= a->format_data; 1267 int keybit = 0; 1268 1269 switch (key[0]) { 1270 case 'a': 1271 if (strcmp(key, "all") == 0) 1272 keybit = ~0; 1273 break; 1274 case 'c': 1275 if (strcmp(key, "cksum") == 0) 1276 keybit = F_CKSUM; 1277 break; 1278 case 'd': 1279 if (strcmp(key, "device") == 0) 1280 keybit = F_DEV; 1281 else if (strcmp(key, "dironly") == 0) { 1282 mtree->dironly = (value != NULL)? 1: 0; 1283 return (ARCHIVE_OK); 1284 } 1285 break; 1286 case 'f': 1287 if (strcmp(key, "flags") == 0) 1288 keybit = F_FLAGS; 1289 break; 1290 case 'g': 1291 if (strcmp(key, "gid") == 0) 1292 keybit = F_GID; 1293 else if (strcmp(key, "gname") == 0) 1294 keybit = F_GNAME; 1295 break; 1296 case 'i': 1297 if (strcmp(key, "indent") == 0) { 1298 mtree->indent = (value != NULL)? 1: 0; 1299 return (ARCHIVE_OK); 1300 } else if (strcmp(key, "inode") == 0) { 1301 keybit = F_INO; 1302 } 1303 break; 1304 case 'l': 1305 if (strcmp(key, "link") == 0) 1306 keybit = F_SLINK; 1307 break; 1308 case 'm': 1309 if (strcmp(key, "md5") == 0 || 1310 strcmp(key, "md5digest") == 0) 1311 keybit = F_MD5; 1312 if (strcmp(key, "mode") == 0) 1313 keybit = F_MODE; 1314 break; 1315 case 'n': 1316 if (strcmp(key, "nlink") == 0) 1317 keybit = F_NLINK; 1318 break; 1319 case 'r': 1320 if (strcmp(key, "resdevice") == 0) { 1321 keybit = F_RESDEV; 1322 } else if (strcmp(key, "ripemd160digest") == 0 || 1323 strcmp(key, "rmd160") == 0 || 1324 strcmp(key, "rmd160digest") == 0) 1325 keybit = F_RMD160; 1326 break; 1327 case 's': 1328 if (strcmp(key, "sha1") == 0 || 1329 strcmp(key, "sha1digest") == 0) 1330 keybit = F_SHA1; 1331 if (strcmp(key, "sha256") == 0 || 1332 strcmp(key, "sha256digest") == 0) 1333 keybit = F_SHA256; 1334 if (strcmp(key, "sha384") == 0 || 1335 strcmp(key, "sha384digest") == 0) 1336 keybit = F_SHA384; 1337 if (strcmp(key, "sha512") == 0 || 1338 strcmp(key, "sha512digest") == 0) 1339 keybit = F_SHA512; 1340 if (strcmp(key, "size") == 0) 1341 keybit = F_SIZE; 1342 break; 1343 case 't': 1344 if (strcmp(key, "time") == 0) 1345 keybit = F_TIME; 1346 else if (strcmp(key, "type") == 0) 1347 keybit = F_TYPE; 1348 break; 1349 case 'u': 1350 if (strcmp(key, "uid") == 0) 1351 keybit = F_UID; 1352 else if (strcmp(key, "uname") == 0) 1353 keybit = F_UNAME; 1354 else if (strcmp(key, "use-set") == 0) { 1355 mtree->output_global_set = (value != NULL)? 1: 0; 1356 return (ARCHIVE_OK); 1357 } 1358 break; 1359 } 1360 if (keybit != 0) { 1361 if (value != NULL) 1362 mtree->keys |= keybit; 1363 else 1364 mtree->keys &= ~keybit; 1365 return (ARCHIVE_OK); 1366 } 1367 1368 /* Note: The "warn" return is just to inform the options 1369 * supervisor that we didn't handle it. It will generate 1370 * a suitable error if no one used this option. */ 1371 return (ARCHIVE_WARN); 1372 } 1373 1374 static int 1375 archive_write_set_format_mtree_default(struct archive *_a, const char *fn) 1376 { 1377 struct archive_write *a = (struct archive_write *)_a; 1378 struct mtree_writer *mtree; 1379 1380 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_NEW, fn); 1381 1382 if (a->format_free != NULL) 1383 (a->format_free)(a); 1384 1385 if ((mtree = calloc(1, sizeof(*mtree))) == NULL) { 1386 archive_set_error(&a->archive, ENOMEM, 1387 "Can't allocate mtree data"); 1388 return (ARCHIVE_FATAL); 1389 } 1390 1391 mtree->mtree_entry = NULL; 1392 mtree->first = 1; 1393 memset(&(mtree->set), 0, sizeof(mtree->set)); 1394 mtree->keys = DEFAULT_KEYS; 1395 mtree->dironly = 0; 1396 mtree->indent = 0; 1397 archive_string_init(&mtree->ebuf); 1398 archive_string_init(&mtree->buf); 1399 mtree_entry_register_init(mtree); 1400 a->format_data = mtree; 1401 a->format_free = archive_write_mtree_free; 1402 a->format_name = "mtree"; 1403 a->format_options = archive_write_mtree_options; 1404 a->format_write_header = archive_write_mtree_header; 1405 a->format_close = archive_write_mtree_close; 1406 a->format_write_data = archive_write_mtree_data; 1407 a->format_finish_entry = archive_write_mtree_finish_entry; 1408 a->archive.archive_format = ARCHIVE_FORMAT_MTREE; 1409 a->archive.archive_format_name = "mtree"; 1410 1411 return (ARCHIVE_OK); 1412 } 1413 1414 int 1415 archive_write_set_format_mtree(struct archive *_a) 1416 { 1417 return archive_write_set_format_mtree_default(_a, 1418 "archive_write_set_format_mtree"); 1419 } 1420 1421 int 1422 archive_write_set_format_mtree_classic(struct archive *_a) 1423 { 1424 int r; 1425 1426 r = archive_write_set_format_mtree_default(_a, 1427 "archive_write_set_format_mtree_classic"); 1428 if (r == ARCHIVE_OK) { 1429 struct archive_write *a = (struct archive_write *)_a; 1430 struct mtree_writer *mtree; 1431 1432 mtree = (struct mtree_writer *)a->format_data; 1433 1434 /* Set to output a mtree archive in classic format. */ 1435 mtree->classic = 1; 1436 /* Basically, mtree classic format uses '/set' global 1437 * value. */ 1438 mtree->output_global_set = 1; 1439 } 1440 return (r); 1441 } 1442 1443 static void 1444 sum_init(struct mtree_writer *mtree) 1445 { 1446 1447 mtree->compute_sum = 0; 1448 1449 if (mtree->keys & F_CKSUM) { 1450 mtree->compute_sum |= F_CKSUM; 1451 mtree->crc = 0; 1452 mtree->crc_len = 0; 1453 } 1454 #ifdef ARCHIVE_HAS_MD5 1455 if (mtree->keys & F_MD5) { 1456 if (archive_md5_init(&mtree->md5ctx) == ARCHIVE_OK) 1457 mtree->compute_sum |= F_MD5; 1458 else 1459 mtree->keys &= ~F_MD5;/* Not supported. */ 1460 } 1461 #endif 1462 #ifdef ARCHIVE_HAS_RMD160 1463 if (mtree->keys & F_RMD160) { 1464 if (archive_rmd160_init(&mtree->rmd160ctx) == ARCHIVE_OK) 1465 mtree->compute_sum |= F_RMD160; 1466 else 1467 mtree->keys &= ~F_RMD160;/* Not supported. */ 1468 } 1469 #endif 1470 #ifdef ARCHIVE_HAS_SHA1 1471 if (mtree->keys & F_SHA1) { 1472 if (archive_sha1_init(&mtree->sha1ctx) == ARCHIVE_OK) 1473 mtree->compute_sum |= F_SHA1; 1474 else 1475 mtree->keys &= ~F_SHA1;/* Not supported. */ 1476 } 1477 #endif 1478 #ifdef ARCHIVE_HAS_SHA256 1479 if (mtree->keys & F_SHA256) { 1480 if (archive_sha256_init(&mtree->sha256ctx) == ARCHIVE_OK) 1481 mtree->compute_sum |= F_SHA256; 1482 else 1483 mtree->keys &= ~F_SHA256;/* Not supported. */ 1484 } 1485 #endif 1486 #ifdef ARCHIVE_HAS_SHA384 1487 if (mtree->keys & F_SHA384) { 1488 if (archive_sha384_init(&mtree->sha384ctx) == ARCHIVE_OK) 1489 mtree->compute_sum |= F_SHA384; 1490 else 1491 mtree->keys &= ~F_SHA384;/* Not supported. */ 1492 } 1493 #endif 1494 #ifdef ARCHIVE_HAS_SHA512 1495 if (mtree->keys & F_SHA512) { 1496 if (archive_sha512_init(&mtree->sha512ctx) == ARCHIVE_OK) 1497 mtree->compute_sum |= F_SHA512; 1498 else 1499 mtree->keys &= ~F_SHA512;/* Not supported. */ 1500 } 1501 #endif 1502 } 1503 1504 static void 1505 sum_update(struct mtree_writer *mtree, const void *buff, size_t n) 1506 { 1507 if (mtree->compute_sum & F_CKSUM) { 1508 /* 1509 * Compute a POSIX 1003.2 checksum 1510 */ 1511 const unsigned char *p; 1512 size_t nn; 1513 1514 for (nn = n, p = buff; nn--; ++p) 1515 COMPUTE_CRC(mtree->crc, *p); 1516 mtree->crc_len += n; 1517 } 1518 #ifdef ARCHIVE_HAS_MD5 1519 if (mtree->compute_sum & F_MD5) 1520 archive_md5_update(&mtree->md5ctx, buff, n); 1521 #endif 1522 #ifdef ARCHIVE_HAS_RMD160 1523 if (mtree->compute_sum & F_RMD160) 1524 archive_rmd160_update(&mtree->rmd160ctx, buff, n); 1525 #endif 1526 #ifdef ARCHIVE_HAS_SHA1 1527 if (mtree->compute_sum & F_SHA1) 1528 archive_sha1_update(&mtree->sha1ctx, buff, n); 1529 #endif 1530 #ifdef ARCHIVE_HAS_SHA256 1531 if (mtree->compute_sum & F_SHA256) 1532 archive_sha256_update(&mtree->sha256ctx, buff, n); 1533 #endif 1534 #ifdef ARCHIVE_HAS_SHA384 1535 if (mtree->compute_sum & F_SHA384) 1536 archive_sha384_update(&mtree->sha384ctx, buff, n); 1537 #endif 1538 #ifdef ARCHIVE_HAS_SHA512 1539 if (mtree->compute_sum & F_SHA512) 1540 archive_sha512_update(&mtree->sha512ctx, buff, n); 1541 #endif 1542 } 1543 1544 static void 1545 sum_final(struct mtree_writer *mtree, struct reg_info *reg) 1546 { 1547 1548 if (mtree->compute_sum & F_CKSUM) { 1549 uint64_t len; 1550 /* Include the length of the file. */ 1551 for (len = mtree->crc_len; len != 0; len >>= 8) 1552 COMPUTE_CRC(mtree->crc, len & 0xff); 1553 reg->crc = ~mtree->crc; 1554 } 1555 #ifdef ARCHIVE_HAS_MD5 1556 if (mtree->compute_sum & F_MD5) 1557 archive_md5_final(&mtree->md5ctx, reg->digest.md5); 1558 #endif 1559 #ifdef ARCHIVE_HAS_RMD160 1560 if (mtree->compute_sum & F_RMD160) 1561 archive_rmd160_final(&mtree->rmd160ctx, reg->digest.rmd160); 1562 #endif 1563 #ifdef ARCHIVE_HAS_SHA1 1564 if (mtree->compute_sum & F_SHA1) 1565 archive_sha1_final(&mtree->sha1ctx, reg->digest.sha1); 1566 #endif 1567 #ifdef ARCHIVE_HAS_SHA256 1568 if (mtree->compute_sum & F_SHA256) 1569 archive_sha256_final(&mtree->sha256ctx, reg->digest.sha256); 1570 #endif 1571 #ifdef ARCHIVE_HAS_SHA384 1572 if (mtree->compute_sum & F_SHA384) 1573 archive_sha384_final(&mtree->sha384ctx, reg->digest.sha384); 1574 #endif 1575 #ifdef ARCHIVE_HAS_SHA512 1576 if (mtree->compute_sum & F_SHA512) 1577 archive_sha512_final(&mtree->sha512ctx, reg->digest.sha512); 1578 #endif 1579 /* Save what types of sum are computed. */ 1580 reg->compute_sum = mtree->compute_sum; 1581 } 1582 1583 #if defined(ARCHIVE_HAS_MD5) || defined(ARCHIVE_HAS_RMD160) || \ 1584 defined(ARCHIVE_HAS_SHA1) || defined(ARCHIVE_HAS_SHA256) || \ 1585 defined(ARCHIVE_HAS_SHA384) || defined(ARCHIVE_HAS_SHA512) 1586 static void 1587 strappend_bin(struct archive_string *s, const unsigned char *bin, int n) 1588 { 1589 static const char hex[] = "0123456789abcdef"; 1590 int i; 1591 1592 for (i = 0; i < n; i++) { 1593 archive_strappend_char(s, hex[bin[i] >> 4]); 1594 archive_strappend_char(s, hex[bin[i] & 0x0f]); 1595 } 1596 } 1597 #endif 1598 1599 static void 1600 sum_write(struct archive_string *str, struct reg_info *reg) 1601 { 1602 1603 if (reg->compute_sum & F_CKSUM) { 1604 archive_string_sprintf(str, " cksum=%ju", 1605 (uintmax_t)reg->crc); 1606 } 1607 1608 #define append_digest(_s, _r, _t) \ 1609 strappend_bin(_s, _r->digest._t, sizeof(_r->digest._t)) 1610 1611 #ifdef ARCHIVE_HAS_MD5 1612 if (reg->compute_sum & F_MD5) { 1613 archive_strcat(str, " md5digest="); 1614 append_digest(str, reg, md5); 1615 } 1616 #endif 1617 #ifdef ARCHIVE_HAS_RMD160 1618 if (reg->compute_sum & F_RMD160) { 1619 archive_strcat(str, " rmd160digest="); 1620 append_digest(str, reg, rmd160); 1621 } 1622 #endif 1623 #ifdef ARCHIVE_HAS_SHA1 1624 if (reg->compute_sum & F_SHA1) { 1625 archive_strcat(str, " sha1digest="); 1626 append_digest(str, reg, sha1); 1627 } 1628 #endif 1629 #ifdef ARCHIVE_HAS_SHA256 1630 if (reg->compute_sum & F_SHA256) { 1631 archive_strcat(str, " sha256digest="); 1632 append_digest(str, reg, sha256); 1633 } 1634 #endif 1635 #ifdef ARCHIVE_HAS_SHA384 1636 if (reg->compute_sum & F_SHA384) { 1637 archive_strcat(str, " sha384digest="); 1638 append_digest(str, reg, sha384); 1639 } 1640 #endif 1641 #ifdef ARCHIVE_HAS_SHA512 1642 if (reg->compute_sum & F_SHA512) { 1643 archive_strcat(str, " sha512digest="); 1644 append_digest(str, reg, sha512); 1645 } 1646 #endif 1647 #undef append_digest 1648 } 1649 1650 static int 1651 mtree_entry_cmp_node(const struct archive_rb_node *n1, 1652 const struct archive_rb_node *n2) 1653 { 1654 const struct mtree_entry *e1 = (const struct mtree_entry *)n1; 1655 const struct mtree_entry *e2 = (const struct mtree_entry *)n2; 1656 1657 return (strcmp(e2->basename.s, e1->basename.s)); 1658 } 1659 1660 static int 1661 mtree_entry_cmp_key(const struct archive_rb_node *n, const void *key) 1662 { 1663 const struct mtree_entry *e = (const struct mtree_entry *)n; 1664 1665 return (strcmp((const char *)key, e->basename.s)); 1666 } 1667 1668 #if defined(_WIN32) || defined(__CYGWIN__) 1669 static int 1670 cleanup_backslash_1(char *p) 1671 { 1672 int mb, dos; 1673 1674 mb = dos = 0; 1675 while (*p) { 1676 if (*(unsigned char *)p > 127) 1677 mb = 1; 1678 if (*p == '\\') { 1679 /* If we have not met any multi-byte characters, 1680 * we can replace '\' with '/'. */ 1681 if (!mb) 1682 *p = '/'; 1683 dos = 1; 1684 } 1685 p++; 1686 } 1687 if (!mb || !dos) 1688 return (0); 1689 return (-1); 1690 } 1691 1692 static void 1693 cleanup_backslash_2(wchar_t *p) 1694 { 1695 1696 /* Convert a path-separator from '\' to '/' */ 1697 while (*p != L'\0') { 1698 if (*p == L'\\') 1699 *p = L'/'; 1700 p++; 1701 } 1702 } 1703 #endif 1704 1705 /* 1706 * Generate a parent directory name and a base name from a pathname. 1707 */ 1708 static int 1709 mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file, 1710 struct archive_entry *entry) 1711 { 1712 const char *pathname; 1713 char *p, *dirname, *slash; 1714 size_t len; 1715 int ret = ARCHIVE_OK; 1716 1717 archive_strcpy(&file->pathname, archive_entry_pathname(entry)); 1718 #if defined(_WIN32) || defined(__CYGWIN__) 1719 /* 1720 * Convert a path-separator from '\' to '/' 1721 */ 1722 if (cleanup_backslash_1(file->pathname.s) != 0) { 1723 const wchar_t *wp = archive_entry_pathname_w(entry); 1724 struct archive_wstring ws; 1725 1726 if (wp != NULL) { 1727 int r; 1728 archive_string_init(&ws); 1729 archive_wstrcpy(&ws, wp); 1730 cleanup_backslash_2(ws.s); 1731 archive_string_empty(&(file->pathname)); 1732 r = archive_string_append_from_wcs(&(file->pathname), 1733 ws.s, ws.length); 1734 archive_wstring_free(&ws); 1735 if (r < 0 && errno == ENOMEM) { 1736 archive_set_error(&a->archive, ENOMEM, 1737 "Can't allocate memory"); 1738 return (ARCHIVE_FATAL); 1739 } 1740 } 1741 } 1742 #else 1743 (void)a; /* UNUSED */ 1744 #endif 1745 pathname = file->pathname.s; 1746 if (strcmp(pathname, ".") == 0) { 1747 archive_strcpy(&file->basename, "."); 1748 return (ARCHIVE_OK); 1749 } 1750 1751 archive_strcpy(&(file->parentdir), pathname); 1752 1753 len = file->parentdir.length; 1754 p = dirname = file->parentdir.s; 1755 1756 /* 1757 * Remove leading '/' and '../' elements 1758 */ 1759 while (*p) { 1760 if (p[0] == '/') { 1761 p++; 1762 len--; 1763 } else if (p[0] != '.') 1764 break; 1765 else if (p[1] == '.' && p[2] == '/') { 1766 p += 3; 1767 len -= 3; 1768 } else 1769 break; 1770 } 1771 if (p != dirname) { 1772 memmove(dirname, p, len+1); 1773 p = dirname; 1774 } 1775 /* 1776 * Remove "/","/." and "/.." elements from tail. 1777 */ 1778 while (len > 0) { 1779 size_t ll = len; 1780 1781 if (len > 0 && p[len-1] == '/') { 1782 p[len-1] = '\0'; 1783 len--; 1784 } 1785 if (len > 1 && p[len-2] == '/' && p[len-1] == '.') { 1786 p[len-2] = '\0'; 1787 len -= 2; 1788 } 1789 if (len > 2 && p[len-3] == '/' && p[len-2] == '.' && 1790 p[len-1] == '.') { 1791 p[len-3] = '\0'; 1792 len -= 3; 1793 } 1794 if (ll == len) 1795 break; 1796 } 1797 while (*p) { 1798 if (p[0] == '/') { 1799 if (p[1] == '/') 1800 /* Convert '//' --> '/' */ 1801 memmove(p, p+1, strlen(p+1) + 1); 1802 else if (p[1] == '.' && p[2] == '/') 1803 /* Convert '/./' --> '/' */ 1804 memmove(p, p+2, strlen(p+2) + 1); 1805 else if (p[1] == '.' && p[2] == '.' && p[3] == '/') { 1806 /* Convert 'dir/dir1/../dir2/' 1807 * --> 'dir/dir2/' 1808 */ 1809 char *rp = p -1; 1810 while (rp >= dirname) { 1811 if (*rp == '/') 1812 break; 1813 --rp; 1814 } 1815 if (rp > dirname) { 1816 strcpy(rp, p+3); 1817 p = rp; 1818 } else { 1819 strcpy(dirname, p+4); 1820 p = dirname; 1821 } 1822 } else 1823 p++; 1824 } else 1825 p++; 1826 } 1827 p = dirname; 1828 len = strlen(p); 1829 1830 /* 1831 * Add "./" prefix. 1832 * NOTE: If the pathname does not have a path separator, we have 1833 * to add "./" to the head of the pathname because mtree reader 1834 * will suppose that it is v1(a.k.a classic) mtree format and 1835 * change the directory unexpectedly and so it will make a wrong 1836 * path. 1837 */ 1838 if (strcmp(p, ".") != 0 && strncmp(p, "./", 2) != 0) { 1839 struct archive_string as; 1840 archive_string_init(&as); 1841 archive_strcpy(&as, "./"); 1842 archive_strncat(&as, p, len); 1843 archive_string_empty(&file->parentdir); 1844 archive_string_concat(&file->parentdir, &as); 1845 archive_string_free(&as); 1846 p = file->parentdir.s; 1847 len = archive_strlen(&file->parentdir); 1848 } 1849 1850 /* 1851 * Find out the position which points the last position of 1852 * path separator('/'). 1853 */ 1854 slash = NULL; 1855 for (; *p != '\0'; p++) { 1856 if (*p == '/') 1857 slash = p; 1858 } 1859 if (slash == NULL) { 1860 /* The pathname doesn't have a parent directory. */ 1861 file->parentdir.length = len; 1862 archive_string_copy(&(file->basename), &(file->parentdir)); 1863 archive_string_empty(&(file->parentdir)); 1864 *file->parentdir.s = '\0'; 1865 return (ret); 1866 } 1867 1868 /* Make a basename from file->parentdir.s and slash */ 1869 *slash = '\0'; 1870 file->parentdir.length = slash - file->parentdir.s; 1871 archive_strcpy(&(file->basename), slash + 1); 1872 return (ret); 1873 } 1874 1875 static int 1876 mtree_entry_create_virtual_dir(struct archive_write *a, const char *pathname, 1877 struct mtree_entry **m_entry) 1878 { 1879 struct archive_entry *entry; 1880 struct mtree_entry *file; 1881 int r; 1882 1883 entry = archive_entry_new(); 1884 if (entry == NULL) { 1885 *m_entry = NULL; 1886 archive_set_error(&a->archive, ENOMEM, 1887 "Can't allocate memory"); 1888 return (ARCHIVE_FATAL); 1889 } 1890 archive_entry_copy_pathname(entry, pathname); 1891 archive_entry_set_mode(entry, AE_IFDIR | 0755); 1892 archive_entry_set_mtime(entry, time(NULL), 0); 1893 1894 r = mtree_entry_new(a, entry, &file); 1895 archive_entry_free(entry); 1896 if (r < ARCHIVE_WARN) { 1897 *m_entry = NULL; 1898 archive_set_error(&a->archive, ENOMEM, 1899 "Can't allocate memory"); 1900 return (ARCHIVE_FATAL); 1901 } 1902 1903 file->dir_info->virtual = 1; 1904 1905 *m_entry = file; 1906 return (ARCHIVE_OK); 1907 } 1908 1909 static void 1910 mtree_entry_register_add(struct mtree_writer *mtree, struct mtree_entry *file) 1911 { 1912 file->next = NULL; 1913 *mtree->file_list.last = file; 1914 mtree->file_list.last = &(file->next); 1915 } 1916 1917 static void 1918 mtree_entry_register_init(struct mtree_writer *mtree) 1919 { 1920 mtree->file_list.first = NULL; 1921 mtree->file_list.last = &(mtree->file_list.first); 1922 } 1923 1924 static void 1925 mtree_entry_register_free(struct mtree_writer *mtree) 1926 { 1927 struct mtree_entry *file, *file_next; 1928 1929 file = mtree->file_list.first; 1930 while (file != NULL) { 1931 file_next = file->next; 1932 mtree_entry_free(file); 1933 file = file_next; 1934 } 1935 } 1936 1937 static int 1938 mtree_entry_add_child_tail(struct mtree_entry *parent, 1939 struct mtree_entry *child) 1940 { 1941 child->dir_info->chnext = NULL; 1942 *parent->dir_info->children.last = child; 1943 parent->dir_info->children.last = &(child->dir_info->chnext); 1944 return (1); 1945 } 1946 1947 /* 1948 * Find a entry from a parent entry with the name. 1949 */ 1950 static struct mtree_entry * 1951 mtree_entry_find_child(struct mtree_entry *parent, const char *child_name) 1952 { 1953 struct mtree_entry *np; 1954 1955 if (parent == NULL) 1956 return (NULL); 1957 np = (struct mtree_entry *)__archive_rb_tree_find_node( 1958 &(parent->dir_info->rbtree), child_name); 1959 return (np); 1960 } 1961 1962 static int 1963 get_path_component(char *name, size_t n, const char *fn) 1964 { 1965 char *p; 1966 size_t l; 1967 1968 p = strchr(fn, '/'); 1969 if (p == NULL) { 1970 if ((l = strlen(fn)) == 0) 1971 return (0); 1972 } else 1973 l = p - fn; 1974 if (l > n -1) 1975 return (-1); 1976 memcpy(name, fn, l); 1977 name[l] = '\0'; 1978 1979 return ((int)l); 1980 } 1981 1982 /* 1983 * Add a new entry into the tree. 1984 */ 1985 static int 1986 mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep) 1987 { 1988 #if defined(_WIN32) && !defined(__CYGWIN__) 1989 char name[_MAX_FNAME];/* Included null terminator size. */ 1990 #elif defined(NAME_MAX) && NAME_MAX >= 255 1991 char name[NAME_MAX+1]; 1992 #else 1993 char name[256]; 1994 #endif 1995 struct mtree_writer *mtree = (struct mtree_writer *)a->format_data; 1996 struct mtree_entry *dent, *file, *np; 1997 const char *fn, *p; 1998 int l, r; 1999 2000 file = *filep; 2001 if (file->parentdir.length == 0 && file->basename.length == 1 && 2002 file->basename.s[0] == '.') { 2003 file->parent = file; 2004 if (mtree->root != NULL) { 2005 np = mtree->root; 2006 goto same_entry; 2007 } 2008 mtree->root = file; 2009 mtree_entry_register_add(mtree, file); 2010 return (ARCHIVE_OK); 2011 } 2012 2013 if (file->parentdir.length == 0) { 2014 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 2015 "Internal programming error " 2016 "in generating canonical name for %s", 2017 file->pathname.s); 2018 return (ARCHIVE_FAILED); 2019 } 2020 2021 fn = p = file->parentdir.s; 2022 2023 /* 2024 * If the path of the parent directory of `file' entry is 2025 * the same as the path of `cur_dirent', add `file' entry to 2026 * `cur_dirent'. 2027 */ 2028 if (archive_strlen(&(mtree->cur_dirstr)) 2029 == archive_strlen(&(file->parentdir)) && 2030 strcmp(mtree->cur_dirstr.s, fn) == 0) { 2031 if (!__archive_rb_tree_insert_node( 2032 &(mtree->cur_dirent->dir_info->rbtree), 2033 (struct archive_rb_node *)file)) { 2034 /* There is the same name in the tree. */ 2035 np = (struct mtree_entry *)__archive_rb_tree_find_node( 2036 &(mtree->cur_dirent->dir_info->rbtree), 2037 file->basename.s); 2038 goto same_entry; 2039 } 2040 file->parent = mtree->cur_dirent; 2041 mtree_entry_register_add(mtree, file); 2042 return (ARCHIVE_OK); 2043 } 2044 2045 dent = mtree->root; 2046 for (;;) { 2047 l = get_path_component(name, sizeof(name), fn); 2048 if (l == 0) { 2049 np = NULL; 2050 break; 2051 } 2052 if (l < 0) { 2053 archive_set_error(&a->archive, 2054 ARCHIVE_ERRNO_MISC, 2055 "A name buffer is too small"); 2056 return (ARCHIVE_FATAL); 2057 } 2058 if (l == 1 && name[0] == '.' && dent != NULL && 2059 dent == mtree->root) { 2060 fn += l; 2061 if (fn[0] == '/') 2062 fn++; 2063 continue; 2064 } 2065 2066 np = mtree_entry_find_child(dent, name); 2067 if (np == NULL || fn[0] == '\0') 2068 break; 2069 2070 /* Find next sub directory. */ 2071 if (!np->dir_info) { 2072 /* NOT Directory! */ 2073 archive_set_error(&a->archive, 2074 ARCHIVE_ERRNO_MISC, 2075 "`%s' is not directory, we cannot insert `%s' ", 2076 np->pathname.s, file->pathname.s); 2077 return (ARCHIVE_FAILED); 2078 } 2079 fn += l; 2080 if (fn[0] == '/') 2081 fn++; 2082 dent = np; 2083 } 2084 if (np == NULL) { 2085 /* 2086 * Create virtual parent directories. 2087 */ 2088 while (fn[0] != '\0') { 2089 struct mtree_entry *vp; 2090 struct archive_string as; 2091 2092 archive_string_init(&as); 2093 archive_strncat(&as, p, fn - p + l); 2094 if (as.s[as.length-1] == '/') { 2095 as.s[as.length-1] = '\0'; 2096 as.length--; 2097 } 2098 r = mtree_entry_create_virtual_dir(a, as.s, &vp); 2099 archive_string_free(&as); 2100 if (r < ARCHIVE_WARN) 2101 return (r); 2102 2103 if (strcmp(vp->pathname.s, ".") == 0) { 2104 vp->parent = vp; 2105 mtree->root = vp; 2106 } else { 2107 __archive_rb_tree_insert_node( 2108 &(dent->dir_info->rbtree), 2109 (struct archive_rb_node *)vp); 2110 vp->parent = dent; 2111 } 2112 mtree_entry_register_add(mtree, vp); 2113 np = vp; 2114 2115 fn += l; 2116 if (fn[0] == '/') 2117 fn++; 2118 l = get_path_component(name, sizeof(name), fn); 2119 if (l < 0) { 2120 archive_string_free(&as); 2121 archive_set_error(&a->archive, 2122 ARCHIVE_ERRNO_MISC, 2123 "A name buffer is too small"); 2124 return (ARCHIVE_FATAL); 2125 } 2126 dent = np; 2127 } 2128 2129 /* Found out the parent directory where `file' can be 2130 * inserted. */ 2131 mtree->cur_dirent = dent; 2132 archive_string_empty(&(mtree->cur_dirstr)); 2133 archive_string_ensure(&(mtree->cur_dirstr), 2134 archive_strlen(&(dent->parentdir)) + 2135 archive_strlen(&(dent->basename)) + 2); 2136 if (archive_strlen(&(dent->parentdir)) + 2137 archive_strlen(&(dent->basename)) == 0) 2138 mtree->cur_dirstr.s[0] = 0; 2139 else { 2140 if (archive_strlen(&(dent->parentdir)) > 0) { 2141 archive_string_copy(&(mtree->cur_dirstr), 2142 &(dent->parentdir)); 2143 archive_strappend_char( 2144 &(mtree->cur_dirstr), '/'); 2145 } 2146 archive_string_concat(&(mtree->cur_dirstr), 2147 &(dent->basename)); 2148 } 2149 2150 if (!__archive_rb_tree_insert_node( 2151 &(dent->dir_info->rbtree), 2152 (struct archive_rb_node *)file)) { 2153 np = (struct mtree_entry *)__archive_rb_tree_find_node( 2154 &(dent->dir_info->rbtree), file->basename.s); 2155 goto same_entry; 2156 } 2157 file->parent = dent; 2158 mtree_entry_register_add(mtree, file); 2159 return (ARCHIVE_OK); 2160 } 2161 2162 same_entry: 2163 /* 2164 * We have already has the entry the filename of which is 2165 * the same. 2166 */ 2167 r = mtree_entry_exchange_same_entry(a, np, file); 2168 if (r < ARCHIVE_WARN) 2169 return (r); 2170 if (np->dir_info) 2171 np->dir_info->virtual = 0; 2172 *filep = np; 2173 mtree_entry_free(file); 2174 return (ARCHIVE_WARN); 2175 } 2176 2177 static int 2178 mtree_entry_exchange_same_entry(struct archive_write *a, struct mtree_entry *np, 2179 struct mtree_entry *file) 2180 { 2181 2182 if ((np->mode & AE_IFMT) != (file->mode & AE_IFMT)) { 2183 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 2184 "Found duplicate entries `%s' and its file type is " 2185 "different", 2186 np->pathname.s); 2187 return (ARCHIVE_FAILED); 2188 } 2189 2190 /* Update the existent mtree entry's attributes by the new one's. */ 2191 archive_string_empty(&np->symlink); 2192 archive_string_concat(&np->symlink, &file->symlink); 2193 archive_string_empty(&np->uname); 2194 archive_string_concat(&np->uname, &file->uname); 2195 archive_string_empty(&np->gname); 2196 archive_string_concat(&np->gname, &file->gname); 2197 archive_string_empty(&np->fflags_text); 2198 archive_string_concat(&np->fflags_text, &file->fflags_text); 2199 np->nlink = file->nlink; 2200 np->filetype = file->filetype; 2201 np->mode = file->mode; 2202 np->size = file->size; 2203 np->uid = file->uid; 2204 np->gid = file->gid; 2205 np->fflags_set = file->fflags_set; 2206 np->fflags_clear = file->fflags_clear; 2207 np->mtime = file->mtime; 2208 np->mtime_nsec = file->mtime_nsec; 2209 np->rdevmajor = file->rdevmajor; 2210 np->rdevminor = file->rdevminor; 2211 np->devmajor = file->devmajor; 2212 np->devminor = file->devminor; 2213 np->ino = file->ino; 2214 2215 return (ARCHIVE_WARN); 2216 } 2217