1 /*- 2 * Copyright (c) 2009 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$"); 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 #ifdef HAVE_OPENSSL_MD5_H 37 #include <openssl/md5.h> 38 #else /* HAVE_OPENSSL_MD5_H */ 39 #ifdef HAVE_MD5_H 40 #include <md5.h> 41 #endif 42 #endif /* HAVE_OPENSSL_MD5_H */ 43 #ifdef HAVE_OPENSSL_RIPEMD_H 44 #include <openssl/ripemd.h> 45 #else /* HAVE_OPENSSL_RIPEMD_H */ 46 #ifdef HAVE_RIPEMD_H 47 #include <ripemd.h> 48 #endif 49 #ifdef HAVE_RMD160_H 50 #include <rmd160.h> 51 #endif 52 #endif /* HAVE_OPENSSL_RIPEMD_H */ 53 #ifdef HAVE_OPENSSL_SHA_H 54 #include <openssl/sha.h> 55 #else /* HAVE_OPENSSL_SHA_H */ 56 #ifdef HAVE_SHA_H 57 #include <sha.h> 58 #endif 59 #ifdef HAVE_SHA1_H 60 #include <sha1.h> 61 #endif 62 #ifdef HAVE_SHA2_H 63 #include <sha2.h> 64 #endif 65 #ifdef HAVE_SHA256_H 66 #include <sha256.h> 67 #endif 68 #endif /* HAVE_OPENSSL_SHA_H */ 69 70 #include "archive.h" 71 #include "archive_entry.h" 72 #include "archive_private.h" 73 #include "archive_write_private.h" 74 75 #define INDENTNAMELEN 15 76 #define MAXLINELEN 80 77 78 struct mtree_writer { 79 struct archive_entry *entry; 80 struct archive_string ebuf; 81 struct archive_string buf; 82 int first; 83 uint64_t entry_bytes_remaining; 84 struct { 85 int output; 86 int processed; 87 struct archive_string parent; 88 mode_t type; 89 int keys; 90 uid_t uid; 91 gid_t gid; 92 mode_t mode; 93 unsigned long fflags_set; 94 unsigned long fflags_clear; 95 } set; 96 /* chekc sum */ 97 int compute_sum; 98 uint32_t crc; 99 uint64_t crc_len; 100 #ifdef HAVE_MD5 101 MD5_CTX md5ctx; 102 #endif 103 #if defined(HAVE_OPENSSL_RIPEMD_H) || defined(HAVE_RIPEMD_H) 104 RIPEMD160_CTX rmd160ctx; 105 #elif defined(HAVE_RMD160_H) 106 RMD160_CTX rmd160ctx; 107 #endif 108 #ifdef HAVE_SHA1 109 #if defined(HAVE_OPENSSL_SHA_H) || defined(HAVE_SHA_H) 110 SHA_CTX sha1ctx; 111 #else 112 SHA1_CTX sha1ctx; 113 #endif 114 #endif 115 #ifdef HAVE_SHA256 116 SHA256_CTX sha256ctx; 117 #endif 118 #ifdef HAVE_SHA384 119 #if defined(HAVE_OPENSSL_SHA_H) 120 SHA512_CTX sha384ctx; 121 #else 122 SHA384_CTX sha384ctx; 123 #endif 124 #endif 125 #ifdef HAVE_SHA512 126 SHA512_CTX sha512ctx; 127 #endif 128 /* Keyword options */ 129 int keys; 130 #define F_CKSUM 0x00000001 /* check sum */ 131 #define F_DEV 0x00000002 /* device type */ 132 #define F_DONE 0x00000004 /* directory done */ 133 #define F_FLAGS 0x00000008 /* file flags */ 134 #define F_GID 0x00000010 /* gid */ 135 #define F_GNAME 0x00000020 /* group name */ 136 #define F_IGN 0x00000040 /* ignore */ 137 #define F_MAGIC 0x00000080 /* name has magic chars */ 138 #define F_MD5 0x00000100 /* MD5 digest */ 139 #define F_MODE 0x00000200 /* mode */ 140 #define F_NLINK 0x00000400 /* number of links */ 141 #define F_NOCHANGE 0x00000800 /* If owner/mode "wrong", do 142 * not change */ 143 #define F_OPT 0x00001000 /* existence optional */ 144 #define F_RMD160 0x00002000 /* RIPEMD160 digest */ 145 #define F_SHA1 0x00004000 /* SHA-1 digest */ 146 #define F_SIZE 0x00008000 /* size */ 147 #define F_SLINK 0x00010000 /* symbolic link */ 148 #define F_TAGS 0x00020000 /* tags */ 149 #define F_TIME 0x00040000 /* modification time */ 150 #define F_TYPE 0x00080000 /* file type */ 151 #define F_UID 0x00100000 /* uid */ 152 #define F_UNAME 0x00200000 /* user name */ 153 #define F_VISIT 0x00400000 /* file visited */ 154 #define F_SHA256 0x00800000 /* SHA-256 digest */ 155 #define F_SHA384 0x01000000 /* SHA-384 digest */ 156 #define F_SHA512 0x02000000 /* SHA-512 digest */ 157 158 /* Options */ 159 int dironly; /* if the dironly is 1, ignore everything except 160 * directory type files. like mtree(8) -d option. 161 */ 162 int indent; /* if the indent is 1, indent writing data. */ 163 }; 164 165 #define DEFAULT_KEYS (F_DEV | F_FLAGS | F_GID | F_GNAME | F_SLINK | F_MODE\ 166 | F_NLINK | F_SIZE | F_TIME | F_TYPE | F_UID\ 167 | F_UNAME) 168 169 #define COMPUTE_CRC(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)] 170 static const uint32_t crctab[] = { 171 0x0, 172 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 173 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 174 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 175 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 176 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, 177 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 178 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 179 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 180 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 181 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, 182 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 183 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 184 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 185 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 186 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 187 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 188 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 189 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 190 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 191 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 192 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 193 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 194 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 195 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, 196 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 197 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 198 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 199 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 200 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, 201 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 202 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 203 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 204 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 205 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 206 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 207 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 208 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 209 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 210 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 211 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 212 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 213 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, 214 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 215 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 216 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 217 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 218 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 219 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, 220 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 221 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 222 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 223 }; 224 225 static int 226 mtree_safe_char(char c) 227 { 228 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) 229 return 1; 230 if (c >= '0' && c <= '9') 231 return 1; 232 if (c == 35 || c == 61 || c == 92) 233 return 0; /* #, = and \ are always quoted */ 234 235 if (c >= 33 && c <= 47) /* !"$%&'()*+,-./ */ 236 return 1; 237 if (c >= 58 && c <= 64) /* :;<>?@ */ 238 return 1; 239 if (c >= 91 && c <= 96) /* []^_` */ 240 return 1; 241 if (c >= 123 && c <= 126) /* {|}~ */ 242 return 1; 243 return 0; 244 } 245 246 static void 247 mtree_quote(struct archive_string *s, const char *str) 248 { 249 const char *start; 250 char buf[4]; 251 unsigned char c; 252 253 for (start = str; *str != '\0'; ++str) { 254 if (mtree_safe_char(*str)) 255 continue; 256 if (start != str) 257 archive_strncat(s, start, str - start); 258 c = (unsigned char)*str; 259 buf[0] = '\\'; 260 buf[1] = (c / 64) + '0'; 261 buf[2] = (c / 8 % 8) + '0'; 262 buf[3] = (c % 8) + '0'; 263 archive_strncat(s, buf, 4); 264 start = str + 1; 265 } 266 267 if (start != str) 268 archive_strncat(s, start, str - start); 269 } 270 271 static void 272 mtree_indent(struct mtree_writer *mtree) 273 { 274 int i, fn; 275 const char *r, *s, *x; 276 277 fn = 1; 278 s = r = mtree->ebuf.s; 279 x = NULL; 280 while (*r == ' ') 281 r++; 282 while ((r = strchr(r, ' ')) != NULL) { 283 if (fn) { 284 fn = 0; 285 archive_strncat(&mtree->buf, s, r - s); 286 if (r -s > INDENTNAMELEN) { 287 archive_strncat(&mtree->buf, " \\\n", 3); 288 for (i = 0; i < (INDENTNAMELEN + 1); i++) 289 archive_strappend_char(&mtree->buf, ' '); 290 } else { 291 for (i = r -s; i < (INDENTNAMELEN + 1); i++) 292 archive_strappend_char(&mtree->buf, ' '); 293 } 294 s = ++r; 295 x = NULL; 296 continue; 297 } 298 if (r - s <= MAXLINELEN - 3 - INDENTNAMELEN) 299 x = r++; 300 else { 301 if (x == NULL) 302 x = r; 303 archive_strncat(&mtree->buf, s, x - s); 304 archive_strncat(&mtree->buf, " \\\n", 3); 305 for (i = 0; i < (INDENTNAMELEN + 1); i++) 306 archive_strappend_char(&mtree->buf, ' '); 307 s = r = ++x; 308 x = NULL; 309 } 310 } 311 if (x != NULL && strlen(s) > MAXLINELEN - 3 - INDENTNAMELEN) { 312 /* Last keyword is longer. */ 313 archive_strncat(&mtree->buf, s, x - s); 314 archive_strncat(&mtree->buf, " \\\n", 3); 315 for (i = 0; i < (INDENTNAMELEN + 1); i++) 316 archive_strappend_char(&mtree->buf, ' '); 317 s = ++x; 318 } 319 archive_strcat(&mtree->buf, s); 320 archive_string_empty(&mtree->ebuf); 321 } 322 323 #if !defined(_WIN32) || defined(__CYGWIN__) 324 static size_t 325 dir_len(struct archive_entry *entry) 326 { 327 const char *path, *r; 328 329 path = archive_entry_pathname(entry); 330 r = strrchr(path, '/'); 331 if (r == NULL) 332 return (0); 333 /* Include a separator size */ 334 return (r - path + 1); 335 } 336 337 #else /* _WIN32 && !__CYGWIN__ */ 338 /* 339 * Note: We should use wide-character for findng '\' character, 340 * a directory separator on Windows, because some character-set have 341 * been using the '\' character for a part of its multibyte character 342 * code. 343 */ 344 static size_t 345 dir_len(struct archive_entry *entry) 346 { 347 wchar_t wc; 348 const char *path; 349 const char *p, *rp; 350 size_t al, l, size; 351 352 path = archive_entry_pathname(entry); 353 al = l = -1; 354 for (p = path; *p != '\0'; ++p) { 355 if (*p == '\\') 356 al = l = p - path; 357 else if (*p == '/') 358 al = p - path; 359 } 360 if (l == -1) 361 goto alen; 362 size = p - path; 363 rp = p = path; 364 while (*p != '\0') { 365 l = mbtowc(&wc, p, size); 366 if (l == -1) 367 goto alen; 368 if (l == 1 && (wc == L'/' || wc == L'\\')) 369 rp = p; 370 p += l; 371 size -= l; 372 } 373 return (rp - path + 1); 374 alen: 375 if (al == -1) 376 return (0); 377 return (al + 1); 378 } 379 #endif /* _WIN32 && !__CYGWIN__ */ 380 381 static int 382 parent_dir_changed(struct archive_string *dir, struct archive_entry *entry) 383 { 384 const char *path; 385 size_t l; 386 387 l = dir_len(entry); 388 path = archive_entry_pathname(entry); 389 if (archive_strlen(dir) > 0) { 390 if (l == 0) { 391 archive_string_empty(dir); 392 return (1); 393 } 394 if (strncmp(dir->s, path, l) == 0) 395 return (0); /* The parent directory is the same. */ 396 } else if (l == 0) 397 return (0); /* The parent directory is the same. */ 398 archive_strncpy(dir, path, l); 399 return (1); 400 } 401 402 /* 403 * Write /set keyword. It means set global datas. 404 * [directory-only mode] 405 * - It is only once to write /set keyword. It is using values of the 406 * first entry. 407 * [normal mode] 408 * - Write /set keyword. It is using values of the first entry whose 409 * filetype is a regular file. 410 * - When a parent directory of the entry whose filetype is the regular 411 * file is changed, check the global datas and write it again if its 412 * values are different from the entry's. 413 */ 414 static void 415 set_global(struct mtree_writer *mtree, struct archive_entry *entry) 416 { 417 struct archive_string setstr; 418 struct archive_string unsetstr; 419 const char *name; 420 int keys, oldkeys, effkeys; 421 mode_t set_type = 0; 422 423 switch (archive_entry_filetype(entry)) { 424 case AE_IFLNK: case AE_IFSOCK: case AE_IFCHR: 425 case AE_IFBLK: case AE_IFIFO: 426 break; 427 case AE_IFDIR: 428 if (mtree->dironly) 429 set_type = AE_IFDIR; 430 break; 431 case AE_IFREG: 432 default: /* Handle unknown file types as regular files. */ 433 if (!mtree->dironly) 434 set_type = AE_IFREG; 435 break; 436 } 437 if (set_type == 0) 438 return; 439 if (mtree->set.processed && 440 !parent_dir_changed(&mtree->set.parent, entry)) 441 return; 442 /* At first, save a parent directory of the entry for following 443 * entries. */ 444 if (!mtree->set.processed && set_type == AE_IFREG) 445 parent_dir_changed(&mtree->set.parent, entry); 446 447 archive_string_init(&setstr); 448 archive_string_init(&unsetstr); 449 keys = mtree->keys & (F_FLAGS | F_GID | F_GNAME | F_NLINK | F_MODE 450 | F_TYPE | F_UID | F_UNAME); 451 oldkeys = mtree->set.keys; 452 effkeys = keys; 453 if (mtree->set.processed) { 454 /* 455 * Check the global datas for whether it needs updating. 456 */ 457 effkeys &= ~F_TYPE; 458 if ((oldkeys & (F_UNAME | F_UID)) != 0 && 459 mtree->set.uid == archive_entry_uid(entry)) 460 effkeys &= ~(F_UNAME | F_UID); 461 if ((oldkeys & (F_GNAME | F_GID)) != 0 && 462 mtree->set.gid == archive_entry_gid(entry)) 463 effkeys &= ~(F_GNAME | F_GID); 464 if ((oldkeys & F_MODE) != 0 && 465 mtree->set.mode == (archive_entry_mode(entry) & 07777)) 466 effkeys &= ~F_MODE; 467 if ((oldkeys & F_FLAGS) != 0) { 468 unsigned long fflags_set; 469 unsigned long fflags_clear; 470 471 archive_entry_fflags(entry, &fflags_set, &fflags_clear); 472 if (fflags_set == mtree->set.fflags_set && 473 fflags_clear == mtree->set.fflags_clear) 474 effkeys &= ~F_FLAGS; 475 } 476 } 477 if ((keys & effkeys & F_TYPE) != 0) { 478 mtree->set.type = set_type; 479 if (set_type == AE_IFDIR) 480 archive_strcat(&setstr, " type=dir"); 481 else 482 archive_strcat(&setstr, " type=file"); 483 } 484 if ((keys & effkeys & F_UNAME) != 0) { 485 if ((name = archive_entry_uname(entry)) != NULL) { 486 archive_strcat(&setstr, " uname="); 487 mtree_quote(&setstr, name); 488 } else if ((oldkeys & F_UNAME) != 0) 489 archive_strcat(&unsetstr, " uname"); 490 else 491 keys &= ~F_UNAME; 492 } 493 if ((keys & effkeys & F_UID) != 0) { 494 mtree->set.uid = archive_entry_uid(entry); 495 archive_string_sprintf(&setstr, " uid=%jd", 496 (intmax_t)mtree->set.uid); 497 } 498 if ((keys & effkeys & F_GNAME) != 0) { 499 if ((name = archive_entry_gname(entry)) != NULL) { 500 archive_strcat(&setstr, " gname="); 501 mtree_quote(&setstr, name); 502 } else if ((oldkeys & F_GNAME) != 0) 503 archive_strcat(&unsetstr, " gname"); 504 else 505 keys &= ~F_GNAME; 506 } 507 if ((keys & effkeys & F_GID) != 0) { 508 mtree->set.gid = archive_entry_gid(entry); 509 archive_string_sprintf(&setstr, " gid=%jd", 510 (intmax_t)mtree->set.gid); 511 } 512 if ((keys & effkeys & F_MODE) != 0) { 513 mtree->set.mode = archive_entry_mode(entry) & 07777; 514 archive_string_sprintf(&setstr, " mode=%o", mtree->set.mode); 515 } 516 if ((keys & effkeys & F_FLAGS) != 0) { 517 if ((name = archive_entry_fflags_text(entry)) != NULL) { 518 archive_strcat(&setstr, " flags="); 519 mtree_quote(&setstr, name); 520 archive_entry_fflags(entry, &mtree->set.fflags_set, 521 &mtree->set.fflags_clear); 522 } else if ((oldkeys & F_FLAGS) != 0) 523 archive_strcat(&unsetstr, " flags"); 524 else 525 keys &= ~F_FLAGS; 526 } 527 if (unsetstr.length > 0) 528 archive_string_sprintf(&mtree->buf, "/unset%s\n", unsetstr.s); 529 archive_string_free(&unsetstr); 530 if (setstr.length > 0) 531 archive_string_sprintf(&mtree->buf, "/set%s\n", setstr.s); 532 archive_string_free(&setstr); 533 mtree->set.keys = keys; 534 mtree->set.processed = 1; 535 /* On directory-only mode, it is only once to write /set keyword. */ 536 if (mtree->dironly) 537 mtree->set.output = 0; 538 } 539 540 static int 541 get_keys(struct mtree_writer *mtree, struct archive_entry *entry) 542 { 543 int keys; 544 545 keys = mtree->keys; 546 if (mtree->set.keys == 0) 547 return (keys); 548 if ((mtree->set.keys & (F_GNAME | F_GID)) != 0 && 549 mtree->set.gid == archive_entry_gid(entry)) 550 keys &= ~(F_GNAME | F_GID); 551 if ((mtree->set.keys & (F_UNAME | F_UID)) != 0 && 552 mtree->set.uid == archive_entry_uid(entry)) 553 keys &= ~(F_UNAME | F_UID); 554 if (mtree->set.keys & F_FLAGS) { 555 unsigned long set, clear; 556 557 archive_entry_fflags(entry, &set, &clear); 558 if (mtree->set.fflags_set == set && 559 mtree->set.fflags_clear == clear) 560 keys &= ~F_FLAGS; 561 } 562 if ((mtree->set.keys & F_MODE) != 0 && 563 mtree->set.mode == (archive_entry_mode(entry) & 07777)) 564 keys &= ~F_MODE; 565 566 switch (archive_entry_filetype(entry)) { 567 case AE_IFLNK: case AE_IFSOCK: case AE_IFCHR: 568 case AE_IFBLK: case AE_IFIFO: 569 break; 570 case AE_IFDIR: 571 if ((mtree->set.keys & F_TYPE) != 0 && 572 mtree->set.type == AE_IFDIR) 573 keys &= ~F_TYPE; 574 break; 575 case AE_IFREG: 576 default: /* Handle unknown file types as regular files. */ 577 if ((mtree->set.keys & F_TYPE) != 0 && 578 mtree->set.type == AE_IFREG) 579 keys &= ~F_TYPE; 580 break; 581 } 582 583 return (keys); 584 } 585 586 static int 587 archive_write_mtree_header(struct archive_write *a, 588 struct archive_entry *entry) 589 { 590 struct mtree_writer *mtree= a->format_data; 591 struct archive_string *str; 592 const char *path; 593 594 mtree->entry = archive_entry_clone(entry); 595 path = archive_entry_pathname(mtree->entry); 596 597 if (mtree->first) { 598 mtree->first = 0; 599 archive_strcat(&mtree->buf, "#mtree\n"); 600 } 601 if (mtree->set.output) 602 set_global(mtree, entry); 603 604 archive_string_empty(&mtree->ebuf); 605 str = (mtree->indent)? &mtree->ebuf : &mtree->buf; 606 if (!mtree->dironly || archive_entry_filetype(entry) == AE_IFDIR) 607 mtree_quote(str, path); 608 609 mtree->entry_bytes_remaining = archive_entry_size(entry); 610 if ((mtree->keys & F_CKSUM) != 0 && 611 archive_entry_filetype(entry) == AE_IFREG) { 612 mtree->compute_sum |= F_CKSUM; 613 mtree->crc = 0; 614 mtree->crc_len = 0; 615 } else 616 mtree->compute_sum &= ~F_CKSUM; 617 #ifdef HAVE_MD5 618 if ((mtree->keys & F_MD5) != 0 && 619 archive_entry_filetype(entry) == AE_IFREG) { 620 mtree->compute_sum |= F_MD5; 621 MD5_Init(&mtree->md5ctx); 622 } else 623 mtree->compute_sum &= ~F_MD5; 624 #endif 625 #ifdef HAVE_RMD160 626 if ((mtree->keys & F_RMD160) != 0 && 627 archive_entry_filetype(entry) == AE_IFREG) { 628 mtree->compute_sum |= F_RMD160; 629 RIPEMD160_Init(&mtree->rmd160ctx); 630 } else 631 mtree->compute_sum &= ~F_RMD160; 632 #endif 633 #ifdef HAVE_SHA1 634 if ((mtree->keys & F_SHA1) != 0 && 635 archive_entry_filetype(entry) == AE_IFREG) { 636 mtree->compute_sum |= F_SHA1; 637 SHA1_Init(&mtree->sha1ctx); 638 } else 639 mtree->compute_sum &= ~F_SHA1; 640 #endif 641 #ifdef HAVE_SHA256 642 if ((mtree->keys & F_SHA256) != 0 && 643 archive_entry_filetype(entry) == AE_IFREG) { 644 mtree->compute_sum |= F_SHA256; 645 SHA256_Init(&mtree->sha256ctx); 646 } else 647 mtree->compute_sum &= ~F_SHA256; 648 #endif 649 #ifdef HAVE_SHA384 650 if ((mtree->keys & F_SHA384) != 0 && 651 archive_entry_filetype(entry) == AE_IFREG) { 652 mtree->compute_sum |= F_SHA384; 653 SHA384_Init(&mtree->sha384ctx); 654 } else 655 mtree->compute_sum &= ~F_SHA384; 656 #endif 657 #ifdef HAVE_SHA512 658 if ((mtree->keys & F_SHA512) != 0 && 659 archive_entry_filetype(entry) == AE_IFREG) { 660 mtree->compute_sum |= F_SHA512; 661 SHA512_Init(&mtree->sha512ctx); 662 } else 663 mtree->compute_sum &= ~F_SHA512; 664 #endif 665 666 return (ARCHIVE_OK); 667 } 668 669 #if defined(HAVE_MD5) || defined(HAVE_RMD160) || defined(HAVE_SHA1) || defined(HAVE_SHA256) || defined(HAVE_SHA384) || defined(HAVE_SHA512) 670 static void 671 strappend_bin(struct archive_string *s, const unsigned char *bin, int n) 672 { 673 static const char hex[] = "0123456789abcdef"; 674 int i; 675 676 for (i = 0; i < n; i++) { 677 archive_strappend_char(s, hex[bin[i] >> 4]); 678 archive_strappend_char(s, hex[bin[i] & 0x0f]); 679 } 680 } 681 #endif 682 683 static int 684 archive_write_mtree_finish_entry(struct archive_write *a) 685 { 686 struct mtree_writer *mtree = a->format_data; 687 struct archive_entry *entry; 688 struct archive_string *str; 689 const char *name; 690 int keys, ret; 691 692 entry = mtree->entry; 693 if (entry == NULL) { 694 archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, 695 "Finished entry without being open first."); 696 return (ARCHIVE_FATAL); 697 } 698 mtree->entry = NULL; 699 700 if (mtree->dironly && archive_entry_filetype(entry) != AE_IFDIR) { 701 archive_entry_free(entry); 702 return (ARCHIVE_OK); 703 } 704 705 str = (mtree->indent)? &mtree->ebuf : &mtree->buf; 706 keys = get_keys(mtree, entry); 707 if ((keys & F_NLINK) != 0 && 708 archive_entry_nlink(entry) != 1 && 709 archive_entry_filetype(entry) != AE_IFDIR) 710 archive_string_sprintf(str, 711 " nlink=%u", archive_entry_nlink(entry)); 712 713 if ((keys & F_GNAME) != 0 && 714 (name = archive_entry_gname(entry)) != NULL) { 715 archive_strcat(str, " gname="); 716 mtree_quote(str, name); 717 } 718 if ((keys & F_UNAME) != 0 && 719 (name = archive_entry_uname(entry)) != NULL) { 720 archive_strcat(str, " uname="); 721 mtree_quote(str, name); 722 } 723 if ((keys & F_FLAGS) != 0 && 724 (name = archive_entry_fflags_text(entry)) != NULL) { 725 archive_strcat(str, " flags="); 726 mtree_quote(str, name); 727 } 728 if ((keys & F_TIME) != 0) 729 archive_string_sprintf(str, " time=%jd.%jd", 730 (intmax_t)archive_entry_mtime(entry), 731 (intmax_t)archive_entry_mtime_nsec(entry)); 732 if ((keys & F_MODE) != 0) 733 archive_string_sprintf(str, " mode=%o", 734 archive_entry_mode(entry) & 07777); 735 if ((keys & F_GID) != 0) 736 archive_string_sprintf(str, " gid=%jd", 737 (intmax_t)archive_entry_gid(entry)); 738 if ((keys & F_UID) != 0) 739 archive_string_sprintf(str, " uid=%jd", 740 (intmax_t)archive_entry_uid(entry)); 741 742 switch (archive_entry_filetype(entry)) { 743 case AE_IFLNK: 744 if ((keys & F_TYPE) != 0) 745 archive_strcat(str, " type=link"); 746 if ((keys & F_SLINK) != 0) { 747 archive_strcat(str, " link="); 748 mtree_quote(str, archive_entry_symlink(entry)); 749 } 750 break; 751 case AE_IFSOCK: 752 if ((keys & F_TYPE) != 0) 753 archive_strcat(str, " type=socket"); 754 break; 755 case AE_IFCHR: 756 if ((keys & F_TYPE) != 0) 757 archive_strcat(str, " type=char"); 758 if ((keys & F_DEV) != 0) { 759 archive_string_sprintf(str, 760 " device=native,%d,%d", 761 archive_entry_rdevmajor(entry), 762 archive_entry_rdevminor(entry)); 763 } 764 break; 765 case AE_IFBLK: 766 if ((keys & F_TYPE) != 0) 767 archive_strcat(str, " type=block"); 768 if ((keys & F_DEV) != 0) { 769 archive_string_sprintf(str, 770 " device=native,%d,%d", 771 archive_entry_rdevmajor(entry), 772 archive_entry_rdevminor(entry)); 773 } 774 break; 775 case AE_IFDIR: 776 if ((keys & F_TYPE) != 0) 777 archive_strcat(str, " type=dir"); 778 break; 779 case AE_IFIFO: 780 if ((keys & F_TYPE) != 0) 781 archive_strcat(str, " type=fifo"); 782 break; 783 case AE_IFREG: 784 default: /* Handle unknown file types as regular files. */ 785 if ((keys & F_TYPE) != 0) 786 archive_strcat(str, " type=file"); 787 if ((keys & F_SIZE) != 0) 788 archive_string_sprintf(str, " size=%jd", 789 (intmax_t)archive_entry_size(entry)); 790 break; 791 } 792 793 if (mtree->compute_sum & F_CKSUM) { 794 uint64_t len; 795 /* Include the length of the file. */ 796 for (len = mtree->crc_len; len != 0; len >>= 8) 797 COMPUTE_CRC(mtree->crc, len & 0xff); 798 mtree->crc = ~mtree->crc; 799 archive_string_sprintf(str, " cksum=%ju", 800 (uintmax_t)mtree->crc); 801 } 802 #ifdef HAVE_MD5 803 if (mtree->compute_sum & F_MD5) { 804 unsigned char buf[16]; 805 806 MD5_Final(buf, &mtree->md5ctx); 807 archive_strcat(str, " md5digest="); 808 strappend_bin(str, buf, sizeof(buf)); 809 } 810 #endif 811 #ifdef HAVE_RMD160 812 if (mtree->compute_sum & F_RMD160) { 813 unsigned char buf[20]; 814 815 RIPEMD160_Final(buf, &mtree->rmd160ctx); 816 archive_strcat(str, " rmd160digest="); 817 strappend_bin(str, buf, sizeof(buf)); 818 } 819 #endif 820 #ifdef HAVE_SHA1 821 if (mtree->compute_sum & F_SHA1) { 822 unsigned char buf[20]; 823 824 SHA1_Final(buf, &mtree->sha1ctx); 825 archive_strcat(str, " sha1digest="); 826 strappend_bin(str, buf, sizeof(buf)); 827 } 828 #endif 829 #ifdef HAVE_SHA256 830 if (mtree->compute_sum & F_SHA256) { 831 unsigned char buf[32]; 832 833 SHA256_Final(buf, &mtree->sha256ctx); 834 archive_strcat(str, " sha256digest="); 835 strappend_bin(str, buf, sizeof(buf)); 836 } 837 #endif 838 #ifdef HAVE_SHA384 839 if (mtree->compute_sum & F_SHA384) { 840 unsigned char buf[48]; 841 842 SHA384_Final(buf, &mtree->sha384ctx); 843 archive_strcat(str, " sha384digest="); 844 strappend_bin(str, buf, sizeof(buf)); 845 } 846 #endif 847 #ifdef HAVE_SHA512 848 if (mtree->compute_sum & F_SHA512) { 849 unsigned char buf[64]; 850 851 SHA512_Final(buf, &mtree->sha512ctx); 852 archive_strcat(str, " sha512digest="); 853 strappend_bin(str, buf, sizeof(buf)); 854 } 855 #endif 856 archive_strcat(str, "\n"); 857 if (mtree->indent) 858 mtree_indent(mtree); 859 860 archive_entry_free(entry); 861 862 if (mtree->buf.length > 32768) { 863 ret = (a->compressor.write)(a, mtree->buf.s, mtree->buf.length); 864 archive_string_empty(&mtree->buf); 865 } else 866 ret = ARCHIVE_OK; 867 868 return (ret == ARCHIVE_OK ? ret : ARCHIVE_FATAL); 869 } 870 871 static int 872 archive_write_mtree_finish(struct archive_write *a) 873 { 874 struct mtree_writer *mtree= a->format_data; 875 876 archive_write_set_bytes_in_last_block(&a->archive, 1); 877 878 return (a->compressor.write)(a, mtree->buf.s, mtree->buf.length); 879 } 880 881 static ssize_t 882 archive_write_mtree_data(struct archive_write *a, const void *buff, size_t n) 883 { 884 struct mtree_writer *mtree= a->format_data; 885 886 if (n > mtree->entry_bytes_remaining) 887 n = mtree->entry_bytes_remaining; 888 if (mtree->dironly) 889 /* We don't need compute a regular file sum */ 890 return (n); 891 if (mtree->compute_sum & F_CKSUM) { 892 /* 893 * Compute a POSIX 1003.2 checksum 894 */ 895 const unsigned char *p; 896 int nn; 897 898 for (nn = n, p = buff; nn--; ++p) 899 COMPUTE_CRC(mtree->crc, *p); 900 mtree->crc_len += n; 901 } 902 #ifdef HAVE_MD5 903 if (mtree->compute_sum & F_MD5) 904 MD5_Update(&mtree->md5ctx, buff, n); 905 #endif 906 #ifdef HAVE_RMD160 907 if (mtree->compute_sum & F_RMD160) 908 RIPEMD160_Update(&mtree->rmd160ctx, buff, n); 909 #endif 910 #ifdef HAVE_SHA1 911 if (mtree->compute_sum & F_SHA1) 912 SHA1_Update(&mtree->sha1ctx, buff, n); 913 #endif 914 #ifdef HAVE_SHA256 915 if (mtree->compute_sum & F_SHA256) 916 SHA256_Update(&mtree->sha256ctx, buff, n); 917 #endif 918 #ifdef HAVE_SHA384 919 if (mtree->compute_sum & F_SHA384) 920 SHA384_Update(&mtree->sha384ctx, buff, n); 921 #endif 922 #ifdef HAVE_SHA512 923 if (mtree->compute_sum & F_SHA512) 924 SHA512_Update(&mtree->sha512ctx, buff, n); 925 #endif 926 return (n); 927 } 928 929 static int 930 archive_write_mtree_destroy(struct archive_write *a) 931 { 932 struct mtree_writer *mtree= a->format_data; 933 934 if (mtree == NULL) 935 return (ARCHIVE_OK); 936 937 archive_entry_free(mtree->entry); 938 archive_string_free(&mtree->ebuf); 939 archive_string_free(&mtree->buf); 940 archive_string_free(&mtree->set.parent); 941 free(mtree); 942 a->format_data = NULL; 943 return (ARCHIVE_OK); 944 } 945 946 static int 947 archive_write_mtree_options(struct archive_write *a, const char *key, 948 const char *value) 949 { 950 struct mtree_writer *mtree= a->format_data; 951 int keybit = 0; 952 953 switch (key[0]) { 954 case 'a': 955 if (strcmp(key, "all") == 0) 956 keybit = ~0; 957 break; 958 case 'c': 959 if (strcmp(key, "cksum") == 0) 960 keybit = F_CKSUM; 961 break; 962 case 'd': 963 if (strcmp(key, "device") == 0) 964 keybit = F_DEV; 965 else if (strcmp(key, "dironly") == 0) { 966 mtree->dironly = (value != NULL)? 1: 0; 967 return (ARCHIVE_OK); 968 } 969 break; 970 case 'f': 971 if (strcmp(key, "flags") == 0) 972 keybit = F_FLAGS; 973 break; 974 case 'g': 975 if (strcmp(key, "gid") == 0) 976 keybit = F_GID; 977 else if (strcmp(key, "gname") == 0) 978 keybit = F_GNAME; 979 break; 980 case 'i': 981 if (strcmp(key, "indent") == 0) { 982 mtree->indent = (value != NULL)? 1: 0; 983 return (ARCHIVE_OK); 984 } 985 break; 986 case 'l': 987 if (strcmp(key, "link") == 0) 988 keybit = F_SLINK; 989 break; 990 case 'm': 991 #ifdef HAVE_MD5 992 if (strcmp(key, "md5") == 0 || 993 strcmp(key, "md5digest") == 0) 994 keybit = F_MD5; 995 #endif 996 if (strcmp(key, "mode") == 0) 997 keybit = F_MODE; 998 break; 999 case 'n': 1000 if (strcmp(key, "nlink") == 0) 1001 keybit = F_NLINK; 1002 break; 1003 #ifdef HAVE_RMD160 1004 case 'r': 1005 if (strcmp(key, "ripemd160digest") == 0 || 1006 strcmp(key, "rmd160") == 0 || 1007 strcmp(key, "rmd160digest") == 0) 1008 keybit = F_RMD160; 1009 break; 1010 #endif 1011 case 's': 1012 #ifdef HAVE_SHA1 1013 if (strcmp(key, "sha1") == 0 || 1014 strcmp(key, "sha1digest") == 0) 1015 keybit = F_SHA1; 1016 #endif 1017 #ifdef HAVE_SHA256 1018 if (strcmp(key, "sha256") == 0 || 1019 strcmp(key, "sha256digest") == 0) 1020 keybit = F_SHA256; 1021 #endif 1022 #ifdef HAVE_SHA384 1023 if (strcmp(key, "sha384") == 0 || 1024 strcmp(key, "sha384digest") == 0) 1025 keybit = F_SHA384; 1026 #endif 1027 #ifdef HAVE_SHA384 1028 if (strcmp(key, "sha512") == 0 || 1029 strcmp(key, "sha512digest") == 0) 1030 keybit = F_SHA512; 1031 #endif 1032 if (strcmp(key, "size") == 0) 1033 keybit = F_SIZE; 1034 break; 1035 case 't': 1036 if (strcmp(key, "time") == 0) 1037 keybit = F_TIME; 1038 else if (strcmp(key, "type") == 0) 1039 keybit = F_TYPE; 1040 break; 1041 case 'u': 1042 if (strcmp(key, "uid") == 0) 1043 keybit = F_UID; 1044 else if (strcmp(key, "uname") == 0) 1045 keybit = F_UNAME; 1046 else if (strcmp(key, "use-set") == 0) { 1047 mtree->set.output = (value != NULL)? 1: 0; 1048 return (ARCHIVE_OK); 1049 } 1050 break; 1051 } 1052 if (keybit != 0) { 1053 if (value != NULL) 1054 mtree->keys |= keybit; 1055 else 1056 mtree->keys &= ~keybit; 1057 return (ARCHIVE_OK); 1058 } 1059 1060 return (ARCHIVE_WARN); 1061 } 1062 1063 int 1064 archive_write_set_format_mtree(struct archive *_a) 1065 { 1066 struct archive_write *a = (struct archive_write *)_a; 1067 struct mtree_writer *mtree; 1068 1069 if (a->format_destroy != NULL) 1070 (a->format_destroy)(a); 1071 1072 if ((mtree = malloc(sizeof(*mtree))) == NULL) { 1073 archive_set_error(&a->archive, ENOMEM, 1074 "Can't allocate mtree data"); 1075 return (ARCHIVE_FATAL); 1076 } 1077 1078 mtree->entry = NULL; 1079 mtree->first = 1; 1080 memset(&(mtree->set), 0, sizeof(mtree->set)); 1081 archive_string_init(&mtree->set.parent); 1082 mtree->keys = DEFAULT_KEYS; 1083 mtree->dironly = 0; 1084 mtree->indent = 0; 1085 archive_string_init(&mtree->ebuf); 1086 archive_string_init(&mtree->buf); 1087 a->format_data = mtree; 1088 a->format_destroy = archive_write_mtree_destroy; 1089 1090 a->pad_uncompressed = 0; 1091 a->format_name = "mtree"; 1092 a->format_options = archive_write_mtree_options; 1093 a->format_write_header = archive_write_mtree_header; 1094 a->format_finish = archive_write_mtree_finish; 1095 a->format_write_data = archive_write_mtree_data; 1096 a->format_finish_entry = archive_write_mtree_finish_entry; 1097 a->archive.archive_format = ARCHIVE_FORMAT_MTREE; 1098 a->archive.archive_format_name = "mtree"; 1099 1100 return (ARCHIVE_OK); 1101 } 1102