1 /*- 2 * Copyright (c) 2009,2011 Michihiro NAKAJIMA 3 * Copyright (c) 2008 Joerg Sonnenberger 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 __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_mtree.c 201171 2009-12-29 06:39:07Z kientzle $"); 29 30 #ifdef HAVE_SYS_TYPES_H 31 #include <sys/types.h> 32 #endif 33 #include <errno.h> 34 #include <stdlib.h> 35 #include <string.h> 36 37 #include "archive.h" 38 #include "archive_crypto_private.h" 39 #include "archive_entry.h" 40 #include "archive_private.h" 41 #include "archive_write_private.h" 42 43 #define INDENTNAMELEN 15 44 #define MAXLINELEN 80 45 #define SET_KEYS \ 46 (F_FLAGS | F_GID | F_GNAME | F_MODE | F_TYPE | F_UID | F_UNAME) 47 48 struct mtree_entry { 49 struct mtree_entry *next; 50 51 char *pathname; 52 char *symlink; 53 unsigned int nlink; 54 mode_t filetype; 55 mode_t mode; 56 int64_t uid; 57 int64_t gid; 58 char *uname; 59 char *gname; 60 char *fflags_text; 61 unsigned long fflags_set; 62 unsigned long fflags_clear; 63 time_t mtime; 64 long mtime_nsec; 65 dev_t rdevmajor; 66 dev_t rdevminor; 67 int64_t size; 68 69 int compute_sum; 70 uint32_t crc; 71 #ifdef ARCHIVE_HAS_MD5 72 unsigned char buf_md5[16]; 73 #endif 74 #ifdef ARCHIVE_HAS_RMD160 75 unsigned char buf_rmd160[20]; 76 #endif 77 #ifdef ARCHIVE_HAS_SHA1 78 unsigned char buf_sha1[20]; 79 #endif 80 #ifdef ARCHIVE_HAS_SHA256 81 unsigned char buf_sha256[32]; 82 #endif 83 #ifdef ARCHIVE_HAS_SHA384 84 unsigned char buf_sha384[48]; 85 #endif 86 #ifdef ARCHIVE_HAS_SHA512 87 unsigned char buf_sha512[64]; 88 #endif 89 }; 90 91 struct attr_counter { 92 struct attr_counter *prev; 93 struct attr_counter *next; 94 int count; 95 struct mtree_entry *m_entry; 96 }; 97 98 struct mtree_writer { 99 struct mtree_entry *mtree_entry; 100 struct archive_string ebuf; 101 struct archive_string buf; 102 int first; 103 uint64_t entry_bytes_remaining; 104 struct { 105 int output; 106 int processed; 107 struct archive_string parent; 108 mode_t type; 109 int keys; 110 int64_t uid; 111 int64_t gid; 112 mode_t mode; 113 unsigned long fflags_set; 114 unsigned long fflags_clear; 115 116 struct attr_counter *uid_list; 117 struct attr_counter *gid_list; 118 struct attr_counter *mode_list; 119 struct attr_counter *flags_list; 120 struct mtree_entry *me_first; 121 struct mtree_entry **me_last; 122 } set; 123 /* check sum */ 124 int compute_sum; 125 uint32_t crc; 126 uint64_t crc_len; 127 #ifdef ARCHIVE_HAS_MD5 128 archive_md5_ctx md5ctx; 129 #endif 130 #ifdef ARCHIVE_HAS_RMD160 131 archive_rmd160_ctx rmd160ctx; 132 #endif 133 #ifdef ARCHIVE_HAS_SHA1 134 archive_sha1_ctx sha1ctx; 135 #endif 136 #ifdef ARCHIVE_HAS_SHA256 137 archive_sha256_ctx sha256ctx; 138 #endif 139 #ifdef ARCHIVE_HAS_SHA384 140 archive_sha384_ctx sha384ctx; 141 #endif 142 #ifdef ARCHIVE_HAS_SHA512 143 archive_sha512_ctx sha512ctx; 144 #endif 145 /* Keyword options */ 146 int keys; 147 #define F_CKSUM 0x00000001 /* check sum */ 148 #define F_DEV 0x00000002 /* device type */ 149 #define F_DONE 0x00000004 /* directory done */ 150 #define F_FLAGS 0x00000008 /* file flags */ 151 #define F_GID 0x00000010 /* gid */ 152 #define F_GNAME 0x00000020 /* group name */ 153 #define F_IGN 0x00000040 /* ignore */ 154 #define F_MAGIC 0x00000080 /* name has magic chars */ 155 #define F_MD5 0x00000100 /* MD5 digest */ 156 #define F_MODE 0x00000200 /* mode */ 157 #define F_NLINK 0x00000400 /* number of links */ 158 #define F_NOCHANGE 0x00000800 /* If owner/mode "wrong", do 159 * not change */ 160 #define F_OPT 0x00001000 /* existence optional */ 161 #define F_RMD160 0x00002000 /* RIPEMD160 digest */ 162 #define F_SHA1 0x00004000 /* SHA-1 digest */ 163 #define F_SIZE 0x00008000 /* size */ 164 #define F_SLINK 0x00010000 /* symbolic link */ 165 #define F_TAGS 0x00020000 /* tags */ 166 #define F_TIME 0x00040000 /* modification time */ 167 #define F_TYPE 0x00080000 /* file type */ 168 #define F_UID 0x00100000 /* uid */ 169 #define F_UNAME 0x00200000 /* user name */ 170 #define F_VISIT 0x00400000 /* file visited */ 171 #define F_SHA256 0x00800000 /* SHA-256 digest */ 172 #define F_SHA384 0x01000000 /* SHA-384 digest */ 173 #define F_SHA512 0x02000000 /* SHA-512 digest */ 174 175 /* Options */ 176 int dironly; /* if the dironly is 1, ignore everything except 177 * directory type files. like mtree(8) -d option. 178 */ 179 int indent; /* if the indent is 1, indent writing data. */ 180 }; 181 182 #define DEFAULT_KEYS (F_DEV | F_FLAGS | F_GID | F_GNAME | F_SLINK | F_MODE\ 183 | F_NLINK | F_SIZE | F_TIME | F_TYPE | F_UID\ 184 | F_UNAME) 185 186 static struct attr_counter * new_attr_count(struct mtree_entry *, 187 struct attr_counter *); 188 static void free_attr_count(struct attr_counter **); 189 static int inc_attr_count(struct attr_counter **, struct attr_counter *, 190 struct attr_counter *, struct mtree_entry *); 191 static int collect_set_values(struct mtree_writer *, struct mtree_entry *); 192 static int get_keys(struct mtree_writer *, struct mtree_entry *); 193 static void sum_init(struct mtree_writer *); 194 static void sum_update(struct mtree_writer *, const void *, size_t); 195 static void sum_final(struct mtree_writer *, struct mtree_entry *); 196 static void sum_write(struct archive_string *, struct mtree_entry *); 197 198 #define COMPUTE_CRC(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)] 199 static const uint32_t crctab[] = { 200 0x0, 201 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 202 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 203 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 204 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 205 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, 206 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 207 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 208 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 209 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 210 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, 211 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 212 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 213 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 214 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 215 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 216 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 217 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 218 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 219 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 220 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 221 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 222 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 223 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 224 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, 225 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 226 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 227 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 228 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 229 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, 230 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 231 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 232 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 233 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 234 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 235 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 236 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 237 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 238 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 239 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 240 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 241 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 242 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, 243 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 244 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 245 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 246 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 247 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 248 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, 249 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 250 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 251 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 252 }; 253 254 static int 255 mtree_safe_char(char c) 256 { 257 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) 258 return 1; 259 if (c >= '0' && c <= '9') 260 return 1; 261 if (c == 35 || c == 61 || c == 92) 262 return 0; /* #, = and \ are always quoted */ 263 264 if (c >= 33 && c <= 47) /* !"$%&'()*+,-./ */ 265 return 1; 266 if (c >= 58 && c <= 64) /* :;<>?@ */ 267 return 1; 268 if (c >= 91 && c <= 96) /* []^_` */ 269 return 1; 270 if (c >= 123 && c <= 126) /* {|}~ */ 271 return 1; 272 return 0; 273 } 274 275 static void 276 mtree_quote(struct archive_string *s, const char *str) 277 { 278 const char *start; 279 char buf[4]; 280 unsigned char c; 281 282 for (start = str; *str != '\0'; ++str) { 283 if (mtree_safe_char(*str)) 284 continue; 285 if (start != str) 286 archive_strncat(s, start, str - start); 287 c = (unsigned char)*str; 288 buf[0] = '\\'; 289 buf[1] = (c / 64) + '0'; 290 buf[2] = (c / 8 % 8) + '0'; 291 buf[3] = (c % 8) + '0'; 292 archive_strncat(s, buf, 4); 293 start = str + 1; 294 } 295 296 if (start != str) 297 archive_strncat(s, start, str - start); 298 } 299 300 /* 301 * Indent a line as mtree utility to be readable for people. 302 */ 303 static void 304 mtree_indent(struct mtree_writer *mtree) 305 { 306 int i, fn; 307 const char *r, *s, *x; 308 309 fn = 1; 310 s = r = mtree->ebuf.s; 311 x = NULL; 312 while (*r == ' ') 313 r++; 314 while ((r = strchr(r, ' ')) != NULL) { 315 if (fn) { 316 fn = 0; 317 archive_strncat(&mtree->buf, s, r - s); 318 if (r -s > INDENTNAMELEN) { 319 archive_strncat(&mtree->buf, " \\\n", 3); 320 for (i = 0; i < (INDENTNAMELEN + 1); i++) 321 archive_strappend_char(&mtree->buf, ' '); 322 } else { 323 for (i = r -s; i < (INDENTNAMELEN + 1); i++) 324 archive_strappend_char(&mtree->buf, ' '); 325 } 326 s = ++r; 327 x = NULL; 328 continue; 329 } 330 if (r - s <= MAXLINELEN - 3 - INDENTNAMELEN) 331 x = r++; 332 else { 333 if (x == NULL) 334 x = r; 335 archive_strncat(&mtree->buf, s, x - s); 336 archive_strncat(&mtree->buf, " \\\n", 3); 337 for (i = 0; i < (INDENTNAMELEN + 1); i++) 338 archive_strappend_char(&mtree->buf, ' '); 339 s = r = ++x; 340 x = NULL; 341 } 342 } 343 if (x != NULL && strlen(s) > MAXLINELEN - 3 - INDENTNAMELEN) { 344 /* Last keyword is longer. */ 345 archive_strncat(&mtree->buf, s, x - s); 346 archive_strncat(&mtree->buf, " \\\n", 3); 347 for (i = 0; i < (INDENTNAMELEN + 1); i++) 348 archive_strappend_char(&mtree->buf, ' '); 349 s = ++x; 350 } 351 archive_strcat(&mtree->buf, s); 352 archive_string_empty(&mtree->ebuf); 353 } 354 355 #if !defined(_WIN32) || defined(__CYGWIN__) 356 static size_t 357 dir_len(struct mtree_entry *me) 358 { 359 const char *path, *r; 360 361 path = me->pathname; 362 r = strrchr(path, '/'); 363 if (r == NULL) 364 return (0); 365 /* Include a separator size */ 366 return (r - path + 1); 367 } 368 369 #else /* _WIN32 && !__CYGWIN__ */ 370 /* 371 * Note: We should use wide-character for findng '\' character, 372 * a directory separator on Windows, because some character-set have 373 * been using the '\' character for a part of its multibyte character 374 * code. 375 */ 376 static size_t 377 dir_len(struct mtree_entry *me) 378 { 379 wchar_t wc; 380 const char *path; 381 const char *p, *rp; 382 size_t al, l, size; 383 384 path = me->pathname; 385 al = l = -1; 386 for (p = path; *p != '\0'; ++p) { 387 if (*p == '\\') 388 al = l = p - path; 389 else if (*p == '/') 390 al = p - path; 391 } 392 if (l == -1) 393 goto alen; 394 size = p - path; 395 rp = p = path; 396 while (*p != '\0') { 397 l = mbtowc(&wc, p, size); 398 if (l == -1) 399 goto alen; 400 if (l == 1 && (wc == L'/' || wc == L'\\')) 401 rp = p; 402 p += l; 403 size -= l; 404 } 405 return (rp - path + 1); 406 alen: 407 if (al == -1) 408 return (0); 409 return (al + 1); 410 } 411 #endif /* _WIN32 && !__CYGWIN__ */ 412 413 /* 414 * Test if a parent directory of the current entry is changed. 415 */ 416 static int 417 parent_dir_changed(struct archive_string *dir, struct mtree_entry *me) 418 { 419 const char *path; 420 size_t l; 421 422 l = dir_len(me); 423 path = me->pathname; 424 if (archive_strlen(dir) > 0) { 425 if (l == 0) { 426 archive_string_empty(dir); 427 return (1); 428 } 429 if (strncmp(dir->s, path, l) == 0) 430 return (0); /* The parent directory is the same. */ 431 } else if (l == 0) 432 return (0); /* The parent directory is the same. */ 433 archive_strncpy(dir, path, l); 434 return (1); 435 } 436 437 /* 438 * Write /set keyword. 439 * Set most used value of uid,gid,mode and fflags, which are 440 * collected by collect_set_values() function. 441 */ 442 static void 443 write_global(struct mtree_writer *mtree) 444 { 445 struct archive_string setstr; 446 struct archive_string unsetstr; 447 const char *name; 448 int keys, oldkeys, effkeys; 449 struct attr_counter *ac; 450 451 archive_string_init(&setstr); 452 archive_string_init(&unsetstr); 453 keys = mtree->keys & SET_KEYS; 454 oldkeys = mtree->set.keys; 455 effkeys = keys; 456 if (mtree->set.processed) { 457 /* 458 * Check if the global data needs updating. 459 */ 460 effkeys &= ~F_TYPE; 461 if (oldkeys & (F_UNAME | F_UID)) { 462 ac = mtree->set.uid_list; 463 do { 464 if (mtree->set.uid == ac->m_entry->uid) { 465 effkeys &= ~(F_UNAME | F_UID); 466 break; 467 } 468 if (ac->next != NULL && 469 ac->next->count == ac->count) 470 continue; 471 } while (0); 472 } 473 if (oldkeys & (F_GNAME | F_GID)) { 474 ac = mtree->set.gid_list; 475 do { 476 if (mtree->set.gid == ac->m_entry->gid) { 477 effkeys &= ~(F_GNAME | F_GID); 478 break; 479 } 480 if (ac->next != NULL && 481 ac->next->count == ac->count) 482 continue; 483 } while (0); 484 } 485 if (oldkeys & F_MODE) { 486 ac = mtree->set.mode_list; 487 do { 488 if (mtree->set.mode == ac->m_entry->mode) { 489 effkeys &= ~F_MODE; 490 break; 491 } 492 if (ac->next != NULL && 493 ac->next->count == ac->count) 494 continue; 495 } while (0); 496 } 497 if ((oldkeys & F_FLAGS) != 0) { 498 ac = mtree->set.flags_list; 499 do { 500 if (ac->m_entry->fflags_set == 501 mtree->set.fflags_set && 502 ac->m_entry->fflags_clear == 503 mtree->set.fflags_clear) { 504 effkeys &= ~F_FLAGS; 505 break; 506 } 507 if (ac->next != NULL && 508 ac->next->count == ac->count) 509 continue; 510 } while (0); 511 } 512 } 513 if ((keys & effkeys & F_TYPE) != 0) { 514 if (mtree->dironly) { 515 archive_strcat(&setstr, " type=dir"); 516 mtree->set.type = AE_IFDIR; 517 } else { 518 archive_strcat(&setstr, " type=file"); 519 mtree->set.type = AE_IFREG; 520 } 521 } 522 if ((keys & effkeys & F_UNAME) != 0) { 523 name = mtree->set.uid_list->m_entry->uname; 524 if (name != NULL) { 525 archive_strcat(&setstr, " uname="); 526 mtree_quote(&setstr, name); 527 } else { 528 keys &= ~F_UNAME; 529 if ((oldkeys & F_UNAME) != 0) 530 archive_strcat(&unsetstr, " uname"); 531 } 532 } 533 if ((keys & effkeys & F_UID) != 0) { 534 mtree->set.uid = mtree->set.uid_list->m_entry->uid; 535 archive_string_sprintf(&setstr, " uid=%jd", 536 (intmax_t)mtree->set.uid); 537 } 538 if ((keys & effkeys & F_GNAME) != 0) { 539 name = mtree->set.gid_list->m_entry->gname; 540 if (name != NULL) { 541 archive_strcat(&setstr, " gname="); 542 mtree_quote(&setstr, name); 543 } else { 544 keys &= ~F_GNAME; 545 if ((oldkeys & F_GNAME) != 0) 546 archive_strcat(&unsetstr, " gname"); 547 } 548 } 549 if ((keys & effkeys & F_GID) != 0) { 550 mtree->set.gid = mtree->set.gid_list->m_entry->gid; 551 archive_string_sprintf(&setstr, " gid=%jd", 552 (intmax_t)mtree->set.gid); 553 } 554 if ((keys & effkeys & F_MODE) != 0) { 555 mtree->set.mode = mtree->set.mode_list->m_entry->mode; 556 archive_string_sprintf(&setstr, " mode=%o", 557 (unsigned int)mtree->set.mode); 558 } 559 if ((keys & effkeys & F_FLAGS) != 0) { 560 name = mtree->set.flags_list->m_entry->fflags_text; 561 if (name != NULL) { 562 archive_strcat(&setstr, " flags="); 563 mtree_quote(&setstr, name); 564 mtree->set.fflags_set = 565 mtree->set.flags_list->m_entry->fflags_set; 566 mtree->set.fflags_clear = 567 mtree->set.flags_list->m_entry->fflags_clear; 568 } else { 569 keys &= ~F_FLAGS; 570 if ((oldkeys & F_FLAGS) != 0) 571 archive_strcat(&unsetstr, " flags"); 572 } 573 } 574 if (unsetstr.length > 0) 575 archive_string_sprintf(&mtree->buf, "/unset%s\n", unsetstr.s); 576 archive_string_free(&unsetstr); 577 if (setstr.length > 0) 578 archive_string_sprintf(&mtree->buf, "/set%s\n", setstr.s); 579 archive_string_free(&setstr); 580 mtree->set.keys = keys; 581 mtree->set.processed = 1; 582 583 free_attr_count(&mtree->set.uid_list); 584 free_attr_count(&mtree->set.gid_list); 585 free_attr_count(&mtree->set.mode_list); 586 free_attr_count(&mtree->set.flags_list); 587 } 588 589 static struct attr_counter * 590 new_attr_count(struct mtree_entry *me, struct attr_counter *prev) 591 { 592 struct attr_counter *ac; 593 594 ac = malloc(sizeof(*ac)); 595 if (ac != NULL) { 596 ac->prev = prev; 597 ac->next = NULL; 598 ac->count = 1; 599 ac->m_entry = me; 600 } 601 return (ac); 602 } 603 604 static void 605 free_attr_count(struct attr_counter **top) 606 { 607 struct attr_counter *ac, *tac; 608 609 if (*top == NULL) 610 return; 611 ac = *top; 612 while (ac != NULL) { 613 tac = ac->next; 614 free(ac); 615 ac = tac; 616 } 617 *top = NULL; 618 } 619 620 static int 621 inc_attr_count(struct attr_counter **top, struct attr_counter *ac, 622 struct attr_counter *last, struct mtree_entry *me) 623 { 624 struct attr_counter *pac; 625 626 if (ac != NULL) { 627 ac->count++; 628 if (*top == ac || ac->prev->count >= ac->count) 629 return (0); 630 for (pac = ac->prev; pac; pac = pac->prev) { 631 if (pac->count >= ac->count) 632 break; 633 } 634 ac->prev->next = ac->next; 635 if (ac->next != NULL) 636 ac->next->prev = ac->prev; 637 if (pac != NULL) { 638 ac->prev = pac; 639 ac->next = pac->next; 640 pac->next = ac; 641 if (ac->next != NULL) 642 ac->next->prev = ac; 643 } else { 644 ac->prev = NULL; 645 ac->next = *top; 646 *top = ac; 647 ac->next->prev = ac; 648 } 649 } else { 650 ac = new_attr_count(me, last); 651 if (ac == NULL) 652 return (-1); 653 last->next = ac; 654 } 655 return (0); 656 } 657 658 static int 659 collect_set_values(struct mtree_writer *mtree, struct mtree_entry *me) 660 { 661 int keys = mtree->keys; 662 struct attr_counter *ac, *last; 663 664 if (keys & (F_UNAME | F_UID)) { 665 if (mtree->set.uid_list == NULL) { 666 mtree->set.uid_list = new_attr_count(me, NULL); 667 if (mtree->set.uid_list == NULL) 668 return (-1); 669 } else { 670 last = NULL; 671 for (ac = mtree->set.uid_list; ac; ac = ac->next) { 672 if (ac->m_entry->uid == me->uid) 673 break; 674 last = ac; 675 } 676 if (inc_attr_count( 677 &mtree->set.uid_list, ac, last, me) < 0) 678 return (-1); 679 } 680 } 681 if (keys & (F_GNAME | F_GID)) { 682 if (mtree->set.gid_list == NULL) { 683 mtree->set.gid_list = new_attr_count(me, NULL); 684 if (mtree->set.gid_list == NULL) 685 return (-1); 686 } else { 687 last = NULL; 688 for (ac = mtree->set.gid_list; ac; ac = ac->next) { 689 if (ac->m_entry->gid == me->gid) 690 break; 691 last = ac; 692 } 693 if (inc_attr_count( 694 &mtree->set.gid_list, ac, last, me) < 0) 695 return (-1); 696 } 697 } 698 if (keys & F_MODE) { 699 if (mtree->set.mode_list == NULL) { 700 mtree->set.mode_list = new_attr_count(me, NULL); 701 if (mtree->set.mode_list == NULL) 702 return (-1); 703 } else { 704 last = NULL; 705 for (ac = mtree->set.mode_list; ac; ac = ac->next) { 706 if (ac->m_entry->mode == me->mode) 707 break; 708 last = ac; 709 } 710 if (inc_attr_count( 711 &mtree->set.mode_list, ac, last, me) < 0) 712 return (-1); 713 } 714 } 715 if (keys & F_FLAGS) { 716 if (mtree->set.flags_list == NULL) { 717 mtree->set.flags_list = new_attr_count(me, NULL); 718 if (mtree->set.flags_list == NULL) 719 return (-1); 720 } else { 721 last = NULL; 722 for (ac = mtree->set.flags_list; ac; ac = ac->next) { 723 if (ac->m_entry->fflags_set == me->fflags_set && 724 ac->m_entry->fflags_clear == me->fflags_clear) 725 break; 726 last = ac; 727 } 728 if (inc_attr_count( 729 &mtree->set.flags_list, ac, last, me) < 0) 730 return (-1); 731 } 732 } 733 734 /* 735 * Save a entry. 736 */ 737 me->next = NULL; 738 *mtree->set.me_last = me; 739 mtree->set.me_last = &me->next; 740 return (0); 741 } 742 743 static int 744 get_keys(struct mtree_writer *mtree, struct mtree_entry *me) 745 { 746 int keys; 747 748 keys = mtree->keys; 749 750 /* 751 * If a keyword has been set by /set, we do not need to 752 * output it. 753 */ 754 if (mtree->set.keys == 0) 755 return (keys);/* /set is not used. */ 756 757 if ((mtree->set.keys & (F_GNAME | F_GID)) != 0 && 758 mtree->set.gid == me->gid) 759 keys &= ~(F_GNAME | F_GID); 760 if ((mtree->set.keys & (F_UNAME | F_UID)) != 0 && 761 mtree->set.uid == me->uid) 762 keys &= ~(F_UNAME | F_UID); 763 if (mtree->set.keys & F_FLAGS) { 764 if (mtree->set.fflags_set == me->fflags_set && 765 mtree->set.fflags_clear == me->fflags_clear) 766 keys &= ~F_FLAGS; 767 } 768 if ((mtree->set.keys & F_MODE) != 0 && mtree->set.mode == me->mode) 769 keys &= ~F_MODE; 770 771 switch (me->filetype) { 772 case AE_IFLNK: case AE_IFSOCK: case AE_IFCHR: 773 case AE_IFBLK: case AE_IFIFO: 774 break; 775 case AE_IFDIR: 776 if ((mtree->set.keys & F_TYPE) != 0 && 777 mtree->set.type == AE_IFDIR) 778 keys &= ~F_TYPE; 779 break; 780 case AE_IFREG: 781 default: /* Handle unknown file types as regular files. */ 782 if ((mtree->set.keys & F_TYPE) != 0 && 783 mtree->set.type == AE_IFREG) 784 keys &= ~F_TYPE; 785 break; 786 } 787 788 return (keys); 789 } 790 791 static struct mtree_entry * 792 new_mtree_entry(struct archive_entry *entry) 793 { 794 struct mtree_entry *me; 795 const char *s; 796 797 me = calloc(1, sizeof(*me)); 798 if (me == NULL) 799 return (NULL); 800 me->pathname = strdup(archive_entry_pathname(entry)); 801 if ((s = archive_entry_symlink(entry)) != NULL) 802 me->symlink = strdup(s); 803 else 804 me->symlink = NULL; 805 me->nlink = archive_entry_nlink(entry); 806 me->filetype = archive_entry_filetype(entry); 807 me->mode = archive_entry_mode(entry) & 07777; 808 me->uid = archive_entry_uid(entry); 809 me->gid = archive_entry_gid(entry); 810 if ((s = archive_entry_uname(entry)) != NULL) 811 me->uname = strdup(s); 812 else 813 me->uname = NULL; 814 if ((s = archive_entry_gname(entry)) != NULL) 815 me->gname = strdup(s); 816 else 817 me->gname = NULL; 818 if ((s = archive_entry_fflags_text(entry)) != NULL) 819 me->fflags_text = strdup(s); 820 else 821 me->fflags_text = NULL; 822 archive_entry_fflags(entry, &me->fflags_set, &me->fflags_clear); 823 me->mtime = archive_entry_mtime(entry); 824 me->mtime_nsec = archive_entry_mtime_nsec(entry); 825 me->rdevmajor = archive_entry_rdevmajor(entry); 826 me->rdevminor = archive_entry_rdevminor(entry); 827 me->size = archive_entry_size(entry); 828 me->compute_sum = 0; 829 830 return (me); 831 } 832 833 static void 834 free_mtree_entry(struct mtree_entry *me) 835 { 836 free(me->pathname); 837 free(me->symlink); 838 free(me->uname); 839 free(me->gname); 840 free(me->fflags_text); 841 free(me); 842 } 843 844 static int 845 archive_write_mtree_header(struct archive_write *a, 846 struct archive_entry *entry) 847 { 848 struct mtree_writer *mtree= a->format_data; 849 850 if (mtree->first) { 851 mtree->first = 0; 852 archive_strcat(&mtree->buf, "#mtree\n"); 853 if ((mtree->keys & SET_KEYS) == 0) 854 mtree->set.output = 0;/* Disalbed. */ 855 } 856 857 mtree->entry_bytes_remaining = archive_entry_size(entry); 858 if (mtree->dironly && archive_entry_filetype(entry) != AE_IFDIR) 859 return (ARCHIVE_OK); 860 861 mtree->mtree_entry = new_mtree_entry(entry); 862 if (mtree->mtree_entry == NULL) { 863 archive_set_error(&a->archive, ENOMEM, 864 "Can't allocate mtree entry"); 865 return (ARCHIVE_FATAL); 866 } 867 868 mtree->compute_sum = 0; 869 870 /* If current file is not a regular file, we do not have to 871 * compute the sum of its content. */ 872 if (archive_entry_filetype(entry) != AE_IFREG) 873 return (ARCHIVE_OK); 874 875 /* Initialize a bunch of sum check context. */ 876 sum_init(mtree); 877 878 return (ARCHIVE_OK); 879 } 880 881 static int 882 write_entry(struct archive_write *a, struct mtree_entry *me) 883 { 884 struct mtree_writer *mtree = a->format_data; 885 struct archive_string *str; 886 int keys, ret; 887 888 archive_string_empty(&mtree->ebuf); 889 str = (mtree->indent)? &mtree->ebuf : &mtree->buf; 890 mtree_quote(str, me->pathname); 891 keys = get_keys(mtree, me); 892 if ((keys & F_NLINK) != 0 && 893 me->nlink != 1 && me->filetype != AE_IFDIR) 894 archive_string_sprintf(str, " nlink=%u", me->nlink); 895 896 if ((keys & F_GNAME) != 0 && me->gname != NULL) { 897 archive_strcat(str, " gname="); 898 mtree_quote(str, me->gname); 899 } 900 if ((keys & F_UNAME) != 0 && me->uname != NULL) { 901 archive_strcat(str, " uname="); 902 mtree_quote(str, me->uname); 903 } 904 if ((keys & F_FLAGS) != 0) { 905 if (me->fflags_text != NULL) { 906 archive_strcat(str, " flags="); 907 mtree_quote(str, me->fflags_text); 908 } else if (mtree->set.processed && 909 (mtree->set.keys & F_FLAGS) != 0) 910 /* Overwrite the global parameter. */ 911 archive_strcat(str, " flags=none"); 912 } 913 if ((keys & F_TIME) != 0) 914 archive_string_sprintf(str, " time=%jd.%jd", 915 (intmax_t)me->mtime, (intmax_t)me->mtime_nsec); 916 if ((keys & F_MODE) != 0) 917 archive_string_sprintf(str, " mode=%o", (unsigned int)me->mode); 918 if ((keys & F_GID) != 0) 919 archive_string_sprintf(str, " gid=%jd", (intmax_t)me->gid); 920 if ((keys & F_UID) != 0) 921 archive_string_sprintf(str, " uid=%jd", (intmax_t)me->uid); 922 923 switch (me->filetype) { 924 case AE_IFLNK: 925 if ((keys & F_TYPE) != 0) 926 archive_strcat(str, " type=link"); 927 if ((keys & F_SLINK) != 0) { 928 archive_strcat(str, " link="); 929 mtree_quote(str, me->symlink); 930 } 931 break; 932 case AE_IFSOCK: 933 if ((keys & F_TYPE) != 0) 934 archive_strcat(str, " type=socket"); 935 break; 936 case AE_IFCHR: 937 if ((keys & F_TYPE) != 0) 938 archive_strcat(str, " type=char"); 939 if ((keys & F_DEV) != 0) { 940 archive_string_sprintf(str, 941 " device=native,%ju,%ju", 942 (uintmax_t)me->rdevmajor, 943 (uintmax_t)me->rdevminor); 944 } 945 break; 946 case AE_IFBLK: 947 if ((keys & F_TYPE) != 0) 948 archive_strcat(str, " type=block"); 949 if ((keys & F_DEV) != 0) { 950 archive_string_sprintf(str, 951 " device=native,%ju,%ju", 952 (uintmax_t)me->rdevmajor, 953 (uintmax_t)me->rdevminor); 954 } 955 break; 956 case AE_IFDIR: 957 if ((keys & F_TYPE) != 0) 958 archive_strcat(str, " type=dir"); 959 break; 960 case AE_IFIFO: 961 if ((keys & F_TYPE) != 0) 962 archive_strcat(str, " type=fifo"); 963 break; 964 case AE_IFREG: 965 default: /* Handle unknown file types as regular files. */ 966 if ((keys & F_TYPE) != 0) 967 archive_strcat(str, " type=file"); 968 if ((keys & F_SIZE) != 0) 969 archive_string_sprintf(str, " size=%jd", 970 (intmax_t)me->size); 971 break; 972 } 973 974 /* Write a bunch of sum. */ 975 if (me->filetype == AE_IFREG) 976 sum_write(str, me); 977 978 archive_strcat(str, "\n"); 979 if (mtree->indent) 980 mtree_indent(mtree); 981 982 if (mtree->buf.length > 32768) { 983 ret = __archive_write_output(a, mtree->buf.s, mtree->buf.length); 984 archive_string_empty(&mtree->buf); 985 } else 986 ret = ARCHIVE_OK; 987 return (ret); 988 } 989 990 /* 991 * Write mtree entries saved at collect_set_values() function. 992 */ 993 static int 994 write_mtree_entries(struct archive_write *a) 995 { 996 struct mtree_writer *mtree = a->format_data; 997 struct mtree_entry *me, *tme; 998 int ret; 999 1000 for (me = mtree->set.me_first; me; me = me->next) { 1001 ret = write_entry(a, me); 1002 if (ret != ARCHIVE_OK) 1003 return (ARCHIVE_FATAL); 1004 } 1005 1006 me = mtree->set.me_first; 1007 while (me != NULL) { 1008 tme = me->next; 1009 free_mtree_entry(me); 1010 me = tme; 1011 } 1012 mtree->set.me_first = NULL; 1013 mtree->set.me_last = &mtree->set.me_first; 1014 return (ARCHIVE_OK); 1015 } 1016 1017 static int 1018 archive_write_mtree_finish_entry(struct archive_write *a) 1019 { 1020 struct mtree_writer *mtree = a->format_data; 1021 struct mtree_entry *me; 1022 int ret; 1023 1024 if ((me = mtree->mtree_entry) == NULL) 1025 return (ARCHIVE_OK); 1026 mtree->mtree_entry = NULL; 1027 1028 if (me->filetype == AE_IFREG) 1029 sum_final(mtree, me); 1030 1031 if (mtree->set.output) { 1032 if (!mtree->dironly) { 1033 if (archive_strlen(&mtree->set.parent) == 0) 1034 parent_dir_changed(&mtree->set.parent, me); 1035 if (parent_dir_changed(&mtree->set.parent, me)) { 1036 /* Write /set keyword */ 1037 write_global(mtree); 1038 /* Write entries saved by 1039 * collect_set_values() function. */ 1040 ret = write_mtree_entries(a); 1041 if (ret != ARCHIVE_OK) 1042 return (ARCHIVE_FATAL); 1043 } 1044 } 1045 /* Tabulate uid,gid,mode and fflags of a entry 1046 * in order to be used for /set. and, at this time 1047 * we do not write a entry. */ 1048 collect_set_values(mtree, me); 1049 return (ARCHIVE_OK); 1050 } else { 1051 /* Write the current entry and free it. */ 1052 ret = write_entry(a, me); 1053 free_mtree_entry(me); 1054 } 1055 return (ret == ARCHIVE_OK ? ret : ARCHIVE_FATAL); 1056 } 1057 1058 static int 1059 archive_write_mtree_close(struct archive_write *a) 1060 { 1061 struct mtree_writer *mtree= a->format_data; 1062 int ret; 1063 1064 if (mtree->set.output && mtree->set.me_first != NULL) { 1065 write_global(mtree); 1066 ret = write_mtree_entries(a); 1067 if (ret != ARCHIVE_OK) 1068 return (ARCHIVE_FATAL); 1069 } 1070 1071 archive_write_set_bytes_in_last_block(&a->archive, 1); 1072 1073 return __archive_write_output(a, mtree->buf.s, mtree->buf.length); 1074 } 1075 1076 static ssize_t 1077 archive_write_mtree_data(struct archive_write *a, const void *buff, size_t n) 1078 { 1079 struct mtree_writer *mtree= a->format_data; 1080 1081 if (n > mtree->entry_bytes_remaining) 1082 n = mtree->entry_bytes_remaining; 1083 mtree->entry_bytes_remaining -= n; 1084 1085 /* We don't need to compute a regular file sum */ 1086 if (mtree->mtree_entry == NULL) 1087 return (n); 1088 1089 if (mtree->mtree_entry->filetype == AE_IFREG) 1090 sum_update(mtree, buff, n); 1091 1092 return (n); 1093 } 1094 1095 static int 1096 archive_write_mtree_free(struct archive_write *a) 1097 { 1098 struct mtree_writer *mtree= a->format_data; 1099 struct mtree_entry *me, *tme; 1100 1101 if (mtree == NULL) 1102 return (ARCHIVE_OK); 1103 1104 /* Make sure we dot not leave any entries. */ 1105 me = mtree->set.me_first; 1106 while (me != NULL) { 1107 tme = me->next; 1108 free_mtree_entry(me); 1109 me = tme; 1110 } 1111 archive_string_free(&mtree->ebuf); 1112 archive_string_free(&mtree->buf); 1113 archive_string_free(&mtree->set.parent); 1114 free_attr_count(&mtree->set.uid_list); 1115 free_attr_count(&mtree->set.gid_list); 1116 free_attr_count(&mtree->set.mode_list); 1117 free_attr_count(&mtree->set.flags_list); 1118 free(mtree); 1119 a->format_data = NULL; 1120 return (ARCHIVE_OK); 1121 } 1122 1123 static int 1124 archive_write_mtree_options(struct archive_write *a, const char *key, 1125 const char *value) 1126 { 1127 struct mtree_writer *mtree= a->format_data; 1128 int keybit = 0; 1129 1130 switch (key[0]) { 1131 case 'a': 1132 if (strcmp(key, "all") == 0) 1133 keybit = ~0; 1134 break; 1135 case 'c': 1136 if (strcmp(key, "cksum") == 0) 1137 keybit = F_CKSUM; 1138 break; 1139 case 'd': 1140 if (strcmp(key, "device") == 0) 1141 keybit = F_DEV; 1142 else if (strcmp(key, "dironly") == 0) { 1143 mtree->dironly = (value != NULL)? 1: 0; 1144 return (ARCHIVE_OK); 1145 } 1146 break; 1147 case 'f': 1148 if (strcmp(key, "flags") == 0) 1149 keybit = F_FLAGS; 1150 break; 1151 case 'g': 1152 if (strcmp(key, "gid") == 0) 1153 keybit = F_GID; 1154 else if (strcmp(key, "gname") == 0) 1155 keybit = F_GNAME; 1156 break; 1157 case 'i': 1158 if (strcmp(key, "indent") == 0) { 1159 mtree->indent = (value != NULL)? 1: 0; 1160 return (ARCHIVE_OK); 1161 } 1162 break; 1163 case 'l': 1164 if (strcmp(key, "link") == 0) 1165 keybit = F_SLINK; 1166 break; 1167 case 'm': 1168 if (strcmp(key, "md5") == 0 || 1169 strcmp(key, "md5digest") == 0) 1170 keybit = F_MD5; 1171 if (strcmp(key, "mode") == 0) 1172 keybit = F_MODE; 1173 break; 1174 case 'n': 1175 if (strcmp(key, "nlink") == 0) 1176 keybit = F_NLINK; 1177 break; 1178 case 'r': 1179 if (strcmp(key, "ripemd160digest") == 0 || 1180 strcmp(key, "rmd160") == 0 || 1181 strcmp(key, "rmd160digest") == 0) 1182 keybit = F_RMD160; 1183 break; 1184 case 's': 1185 if (strcmp(key, "sha1") == 0 || 1186 strcmp(key, "sha1digest") == 0) 1187 keybit = F_SHA1; 1188 if (strcmp(key, "sha256") == 0 || 1189 strcmp(key, "sha256digest") == 0) 1190 keybit = F_SHA256; 1191 if (strcmp(key, "sha384") == 0 || 1192 strcmp(key, "sha384digest") == 0) 1193 keybit = F_SHA384; 1194 if (strcmp(key, "sha512") == 0 || 1195 strcmp(key, "sha512digest") == 0) 1196 keybit = F_SHA512; 1197 if (strcmp(key, "size") == 0) 1198 keybit = F_SIZE; 1199 break; 1200 case 't': 1201 if (strcmp(key, "time") == 0) 1202 keybit = F_TIME; 1203 else if (strcmp(key, "type") == 0) 1204 keybit = F_TYPE; 1205 break; 1206 case 'u': 1207 if (strcmp(key, "uid") == 0) 1208 keybit = F_UID; 1209 else if (strcmp(key, "uname") == 0) 1210 keybit = F_UNAME; 1211 else if (strcmp(key, "use-set") == 0) { 1212 mtree->set.output = (value != NULL)? 1: 0; 1213 return (ARCHIVE_OK); 1214 } 1215 break; 1216 } 1217 if (keybit != 0) { 1218 if (value != NULL) 1219 mtree->keys |= keybit; 1220 else 1221 mtree->keys &= ~keybit; 1222 return (ARCHIVE_OK); 1223 } 1224 1225 return (ARCHIVE_FAILED); 1226 } 1227 1228 int 1229 archive_write_set_format_mtree(struct archive *_a) 1230 { 1231 struct archive_write *a = (struct archive_write *)_a; 1232 struct mtree_writer *mtree; 1233 1234 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 1235 ARCHIVE_STATE_NEW, "archive_write_set_format_mtree"); 1236 1237 if (a->format_free != NULL) 1238 (a->format_free)(a); 1239 1240 if ((mtree = calloc(1, sizeof(*mtree))) == NULL) { 1241 archive_set_error(&a->archive, ENOMEM, 1242 "Can't allocate mtree data"); 1243 return (ARCHIVE_FATAL); 1244 } 1245 1246 mtree->mtree_entry = NULL; 1247 mtree->first = 1; 1248 memset(&(mtree->set), 0, sizeof(mtree->set)); 1249 archive_string_init(&mtree->set.parent); 1250 mtree->keys = DEFAULT_KEYS; 1251 mtree->dironly = 0; 1252 mtree->indent = 0; 1253 archive_string_init(&mtree->ebuf); 1254 archive_string_init(&mtree->buf); 1255 mtree->set.me_first = NULL; 1256 mtree->set.me_last = &mtree->set.me_first; 1257 a->format_data = mtree; 1258 a->format_free = archive_write_mtree_free; 1259 a->format_name = "mtree"; 1260 a->format_options = archive_write_mtree_options; 1261 a->format_write_header = archive_write_mtree_header; 1262 a->format_close = archive_write_mtree_close; 1263 a->format_write_data = archive_write_mtree_data; 1264 a->format_finish_entry = archive_write_mtree_finish_entry; 1265 a->archive.archive_format = ARCHIVE_FORMAT_MTREE; 1266 a->archive.archive_format_name = "mtree"; 1267 1268 return (ARCHIVE_OK); 1269 } 1270 1271 static void 1272 sum_init(struct mtree_writer *mtree) 1273 { 1274 if (mtree->keys & F_CKSUM) { 1275 mtree->compute_sum |= F_CKSUM; 1276 mtree->crc = 0; 1277 mtree->crc_len = 0; 1278 } 1279 #ifdef ARCHIVE_HAS_MD5 1280 if (mtree->keys & F_MD5) { 1281 if (archive_md5_init(&mtree->md5ctx) == ARCHIVE_OK) 1282 mtree->compute_sum |= F_MD5; 1283 else 1284 mtree->keys &= ~F_MD5;/* Not supported. */ 1285 } 1286 #endif 1287 #ifdef ARCHIVE_HAS_RMD160 1288 if (mtree->keys & F_RMD160) { 1289 if (archive_rmd160_init(&mtree->rmd160ctx) == ARCHIVE_OK) 1290 mtree->compute_sum |= F_RMD160; 1291 else 1292 mtree->keys &= ~F_RMD160;/* Not supported. */ 1293 } 1294 #endif 1295 #ifdef ARCHIVE_HAS_SHA1 1296 if (mtree->keys & F_SHA1) { 1297 if (archive_sha1_init(&mtree->sha1ctx) == ARCHIVE_OK) 1298 mtree->compute_sum |= F_SHA1; 1299 else 1300 mtree->keys &= ~F_SHA1;/* Not supported. */ 1301 } 1302 #endif 1303 #ifdef ARCHIVE_HAS_SHA256 1304 if (mtree->keys & F_SHA256) { 1305 if (archive_sha256_init(&mtree->sha256ctx) == ARCHIVE_OK) 1306 mtree->compute_sum |= F_SHA256; 1307 else 1308 mtree->keys &= ~F_SHA256;/* Not supported. */ 1309 } 1310 #endif 1311 #ifdef ARCHIVE_HAS_SHA384 1312 if (mtree->keys & F_SHA384) { 1313 if (archive_sha384_init(&mtree->sha384ctx) == ARCHIVE_OK) 1314 mtree->compute_sum |= F_SHA384; 1315 else 1316 mtree->keys &= ~F_SHA384;/* Not supported. */ 1317 } 1318 #endif 1319 #ifdef ARCHIVE_HAS_SHA512 1320 if (mtree->keys & F_SHA512) { 1321 if (archive_sha512_init(&mtree->sha512ctx) == ARCHIVE_OK) 1322 mtree->compute_sum |= F_SHA512; 1323 else 1324 mtree->keys &= ~F_SHA512;/* Not supported. */ 1325 } 1326 #endif 1327 } 1328 1329 static void 1330 sum_update(struct mtree_writer *mtree, const void *buff, size_t n) 1331 { 1332 if (mtree->compute_sum & F_CKSUM) { 1333 /* 1334 * Compute a POSIX 1003.2 checksum 1335 */ 1336 const unsigned char *p; 1337 size_t nn; 1338 1339 for (nn = n, p = buff; nn--; ++p) 1340 COMPUTE_CRC(mtree->crc, *p); 1341 mtree->crc_len += n; 1342 } 1343 #ifdef ARCHIVE_HAS_MD5 1344 if (mtree->compute_sum & F_MD5) 1345 archive_md5_update(&mtree->md5ctx, buff, n); 1346 #endif 1347 #ifdef ARCHIVE_HAS_RMD160 1348 if (mtree->compute_sum & F_RMD160) 1349 archive_rmd160_update(&mtree->rmd160ctx, buff, n); 1350 #endif 1351 #ifdef ARCHIVE_HAS_SHA1 1352 if (mtree->compute_sum & F_SHA1) 1353 archive_sha1_update(&mtree->sha1ctx, buff, n); 1354 #endif 1355 #ifdef ARCHIVE_HAS_SHA256 1356 if (mtree->compute_sum & F_SHA256) 1357 archive_sha256_update(&mtree->sha256ctx, buff, n); 1358 #endif 1359 #ifdef ARCHIVE_HAS_SHA384 1360 if (mtree->compute_sum & F_SHA384) 1361 archive_sha384_update(&mtree->sha384ctx, buff, n); 1362 #endif 1363 #ifdef ARCHIVE_HAS_SHA512 1364 if (mtree->compute_sum & F_SHA512) 1365 archive_sha512_update(&mtree->sha512ctx, buff, n); 1366 #endif 1367 } 1368 1369 static void 1370 sum_final(struct mtree_writer *mtree, struct mtree_entry *me) 1371 { 1372 1373 if (mtree->compute_sum & F_CKSUM) { 1374 uint64_t len; 1375 /* Include the length of the file. */ 1376 for (len = mtree->crc_len; len != 0; len >>= 8) 1377 COMPUTE_CRC(mtree->crc, len & 0xff); 1378 me->crc = ~mtree->crc; 1379 } 1380 #ifdef ARCHIVE_HAS_MD5 1381 if (mtree->compute_sum & F_MD5) 1382 archive_md5_final(&mtree->md5ctx, me->buf_md5); 1383 #endif 1384 #ifdef ARCHIVE_HAS_RMD160 1385 if (mtree->compute_sum & F_RMD160) 1386 archive_rmd160_final(&mtree->rmd160ctx, me->buf_rmd160); 1387 #endif 1388 #ifdef ARCHIVE_HAS_SHA1 1389 if (mtree->compute_sum & F_SHA1) 1390 archive_sha1_final(&mtree->sha1ctx, me->buf_sha1); 1391 #endif 1392 #ifdef ARCHIVE_HAS_SHA256 1393 if (mtree->compute_sum & F_SHA256) 1394 archive_sha256_final(&mtree->sha256ctx, me->buf_sha256); 1395 #endif 1396 #ifdef ARCHIVE_HAS_SHA384 1397 if (mtree->compute_sum & F_SHA384) 1398 archive_sha384_final(&mtree->sha384ctx, me->buf_sha384); 1399 #endif 1400 #ifdef ARCHIVE_HAS_SHA512 1401 if (mtree->compute_sum & F_SHA512) 1402 archive_sha512_final(&mtree->sha512ctx, me->buf_sha512); 1403 #endif 1404 /* Save what types of sum are computed. */ 1405 me->compute_sum = mtree->compute_sum; 1406 } 1407 1408 #if defined(ARCHIVE_HAS_MD5) || defined(ARCHIVE_HAS_RMD160) || \ 1409 defined(ARCHIVE_HAS_SHA1) || defined(ARCHIVE_HAS_SHA256) || \ 1410 defined(ARCHIVE_HAS_SHA384) || defined(ARCHIVE_HAS_SHA512) 1411 static void 1412 strappend_bin(struct archive_string *s, const unsigned char *bin, int n) 1413 { 1414 static const char hex[] = "0123456789abcdef"; 1415 int i; 1416 1417 for (i = 0; i < n; i++) { 1418 archive_strappend_char(s, hex[bin[i] >> 4]); 1419 archive_strappend_char(s, hex[bin[i] & 0x0f]); 1420 } 1421 } 1422 #endif 1423 1424 static void 1425 sum_write(struct archive_string *str, struct mtree_entry *me) 1426 { 1427 1428 if (me->compute_sum & F_CKSUM) { 1429 archive_string_sprintf(str, " cksum=%ju", 1430 (uintmax_t)me->crc); 1431 } 1432 #ifdef ARCHIVE_HAS_MD5 1433 if (me->compute_sum & F_MD5) { 1434 archive_strcat(str, " md5digest="); 1435 strappend_bin(str, me->buf_md5, sizeof(me->buf_md5)); 1436 } 1437 #endif 1438 #ifdef ARCHIVE_HAS_RMD160 1439 if (me->compute_sum & F_RMD160) { 1440 archive_strcat(str, " rmd160digest="); 1441 strappend_bin(str, me->buf_rmd160, sizeof(me->buf_rmd160)); 1442 } 1443 #endif 1444 #ifdef ARCHIVE_HAS_SHA1 1445 if (me->compute_sum & F_SHA1) { 1446 archive_strcat(str, " sha1digest="); 1447 strappend_bin(str, me->buf_sha1, sizeof(me->buf_sha1)); 1448 } 1449 #endif 1450 #ifdef ARCHIVE_HAS_SHA256 1451 if (me->compute_sum & F_SHA256) { 1452 archive_strcat(str, " sha256digest="); 1453 strappend_bin(str, me->buf_sha256, sizeof(me->buf_sha256)); 1454 } 1455 #endif 1456 #ifdef ARCHIVE_HAS_SHA384 1457 if (me->compute_sum & F_SHA384) { 1458 archive_strcat(str, " sha384digest="); 1459 strappend_bin(str, me->buf_sha384, sizeof(me->buf_sha384)); 1460 } 1461 #endif 1462 #ifdef ARCHIVE_HAS_SHA512 1463 if (me->compute_sum & F_SHA512) { 1464 archive_strcat(str, " sha512digest="); 1465 strappend_bin(str, me->buf_sha512, sizeof(me->buf_sha512)); 1466 } 1467 #endif 1468 } 1469