1 /*- 2 * Copyright (c) 2003-2007 Tim Kientzle 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 29 #ifdef HAVE_ERRNO_H 30 #include <errno.h> 31 #endif 32 #include <stdio.h> 33 #ifdef HAVE_STDLIB_H 34 #include <stdlib.h> 35 #endif 36 #ifdef HAVE_STRING_H 37 #include <string.h> 38 #endif 39 40 #include "archive.h" 41 #include "archive_entry.h" 42 #include "archive_private.h" 43 #include "archive_write_private.h" 44 #include "archive_write_set_format_private.h" 45 46 struct shar { 47 int dump; 48 int end_of_line; 49 struct archive_entry *entry; 50 int has_data; 51 char *last_dir; 52 53 /* Line buffer for uuencoded dump format */ 54 char outbuff[45]; 55 size_t outpos; 56 57 int wrote_header; 58 struct archive_string work; 59 struct archive_string quoted_name; 60 }; 61 62 static int archive_write_shar_close(struct archive_write *); 63 static int archive_write_shar_free(struct archive_write *); 64 static int archive_write_shar_header(struct archive_write *, 65 struct archive_entry *); 66 static ssize_t archive_write_shar_data_sed(struct archive_write *, 67 const void * buff, size_t); 68 static ssize_t archive_write_shar_data_uuencode(struct archive_write *, 69 const void * buff, size_t); 70 static int archive_write_shar_finish_entry(struct archive_write *); 71 72 /* 73 * Copy the given string to the buffer, quoting all shell meta characters 74 * found. 75 */ 76 static void 77 shar_quote(struct archive_string *buf, const char *str, int in_shell) 78 { 79 static const char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~"; 80 size_t len; 81 82 while (*str != '\0') { 83 if ((len = strcspn(str, meta)) != 0) { 84 archive_strncat(buf, str, len); 85 str += len; 86 } else if (*str == '\n') { 87 if (in_shell) 88 archive_strcat(buf, "\"\n\""); 89 else 90 archive_strcat(buf, "\\n"); 91 ++str; 92 } else { 93 archive_strappend_char(buf, '\\'); 94 archive_strappend_char(buf, *str); 95 ++str; 96 } 97 } 98 } 99 100 /* 101 * Set output format to 'shar' format. 102 */ 103 int 104 archive_write_set_format_shar(struct archive *_a) 105 { 106 struct archive_write *a = (struct archive_write *)_a; 107 struct shar *shar; 108 109 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 110 ARCHIVE_STATE_NEW, "archive_write_set_format_shar"); 111 112 /* If someone else was already registered, unregister them. */ 113 if (a->format_free != NULL) 114 (a->format_free)(a); 115 116 shar = calloc(1, sizeof(*shar)); 117 if (shar == NULL) { 118 archive_set_error(&a->archive, ENOMEM, "Can't allocate shar data"); 119 return (ARCHIVE_FATAL); 120 } 121 archive_string_init(&shar->work); 122 archive_string_init(&shar->quoted_name); 123 a->format_data = shar; 124 a->format_name = "shar"; 125 a->format_write_header = archive_write_shar_header; 126 a->format_close = archive_write_shar_close; 127 a->format_free = archive_write_shar_free; 128 a->format_write_data = archive_write_shar_data_sed; 129 a->format_finish_entry = archive_write_shar_finish_entry; 130 a->archive.archive_format = ARCHIVE_FORMAT_SHAR_BASE; 131 a->archive.archive_format_name = "shar"; 132 return (ARCHIVE_OK); 133 } 134 135 /* 136 * An alternate 'shar' that uses uudecode instead of 'sed' to encode 137 * file contents and can therefore be used to archive binary files. 138 * In addition, this variant also attempts to restore ownership, file modes, 139 * and other extended file information. 140 */ 141 int 142 archive_write_set_format_shar_dump(struct archive *_a) 143 { 144 struct archive_write *a = (struct archive_write *)_a; 145 struct shar *shar; 146 147 archive_write_set_format_shar(&a->archive); 148 shar = (struct shar *)a->format_data; 149 shar->dump = 1; 150 a->format_write_data = archive_write_shar_data_uuencode; 151 a->archive.archive_format = ARCHIVE_FORMAT_SHAR_DUMP; 152 a->archive.archive_format_name = "shar dump"; 153 return (ARCHIVE_OK); 154 } 155 156 static int 157 archive_write_shar_header(struct archive_write *a, struct archive_entry *entry) 158 { 159 const char *linkname; 160 const char *name; 161 char *p, *pp; 162 struct shar *shar; 163 164 shar = (struct shar *)a->format_data; 165 if (!shar->wrote_header) { 166 archive_strcat(&shar->work, "#!/bin/sh\n"); 167 archive_strcat(&shar->work, "# This is a shell archive\n"); 168 shar->wrote_header = 1; 169 } 170 171 /* Save the entry for the closing. */ 172 archive_entry_free(shar->entry); 173 shar->entry = archive_entry_clone(entry); 174 name = archive_entry_pathname(entry); 175 176 /* Handle some preparatory issues. */ 177 switch(archive_entry_filetype(entry)) { 178 case AE_IFREG: 179 /* Only regular files have non-zero size. */ 180 break; 181 case AE_IFDIR: 182 archive_entry_set_size(entry, 0); 183 /* Don't bother trying to recreate '.' */ 184 if (strcmp(name, ".") == 0 || strcmp(name, "./") == 0) 185 return (ARCHIVE_OK); 186 break; 187 case AE_IFIFO: 188 case AE_IFCHR: 189 case AE_IFBLK: 190 /* All other file types have zero size in the archive. */ 191 archive_entry_set_size(entry, 0); 192 break; 193 default: 194 archive_entry_set_size(entry, 0); 195 if (archive_entry_hardlink(entry) == NULL && 196 archive_entry_symlink(entry) == NULL) { 197 __archive_write_entry_filetype_unsupported( 198 &a->archive, entry, "shar"); 199 return (ARCHIVE_WARN); 200 } 201 } 202 203 archive_string_empty(&shar->quoted_name); 204 shar_quote(&shar->quoted_name, name, 1); 205 206 /* Stock preparation for all file types. */ 207 archive_string_sprintf(&shar->work, "echo x %s\n", shar->quoted_name.s); 208 209 if (archive_entry_filetype(entry) != AE_IFDIR) { 210 /* Try to create the dir. */ 211 p = strdup(name); 212 if (p == NULL) { 213 archive_set_error(&a->archive, ENOMEM, "Out of memory"); 214 return (ARCHIVE_FATAL); 215 } 216 pp = strrchr(p, '/'); 217 /* If there is a / character, try to create the dir. */ 218 if (pp != NULL) { 219 *pp = '\0'; 220 221 /* Try to avoid a lot of redundant mkdir commands. */ 222 if (strcmp(p, ".") == 0) { 223 /* Don't try to "mkdir ." */ 224 free(p); 225 } else if (shar->last_dir == NULL) { 226 archive_strcat(&shar->work, "mkdir -p "); 227 shar_quote(&shar->work, p, 1); 228 archive_strcat(&shar->work, 229 " > /dev/null 2>&1\n"); 230 shar->last_dir = p; 231 } else if (strcmp(p, shar->last_dir) == 0) { 232 /* We've already created this exact dir. */ 233 free(p); 234 } else if (strlen(p) < strlen(shar->last_dir) && 235 strncmp(p, shar->last_dir, strlen(p)) == 0) { 236 /* We've already created a subdir. */ 237 free(p); 238 } else { 239 archive_strcat(&shar->work, "mkdir -p "); 240 shar_quote(&shar->work, p, 1); 241 archive_strcat(&shar->work, 242 " > /dev/null 2>&1\n"); 243 shar->last_dir = p; 244 } 245 } else { 246 free(p); 247 } 248 } 249 250 /* Handle file-type specific issues. */ 251 shar->has_data = 0; 252 if ((linkname = archive_entry_hardlink(entry)) != NULL) { 253 archive_strcat(&shar->work, "ln -f "); 254 shar_quote(&shar->work, linkname, 1); 255 archive_string_sprintf(&shar->work, " %s\n", 256 shar->quoted_name.s); 257 } else if ((linkname = archive_entry_symlink(entry)) != NULL) { 258 archive_strcat(&shar->work, "ln -fs "); 259 shar_quote(&shar->work, linkname, 1); 260 archive_string_sprintf(&shar->work, " %s\n", 261 shar->quoted_name.s); 262 } else { 263 switch(archive_entry_filetype(entry)) { 264 case AE_IFREG: 265 if (archive_entry_size(entry) == 0) { 266 /* More portable than "touch." */ 267 archive_string_sprintf(&shar->work, 268 "test -e \"%s\" || :> \"%s\"\n", 269 shar->quoted_name.s, shar->quoted_name.s); 270 } else { 271 if (shar->dump) { 272 unsigned int mode = archive_entry_mode(entry) & 0777; 273 archive_string_sprintf(&shar->work, 274 "uudecode -p > %s << 'SHAR_END'\n", 275 shar->quoted_name.s); 276 archive_string_sprintf(&shar->work, 277 "begin %o ", mode); 278 shar_quote(&shar->work, name, 0); 279 archive_strcat(&shar->work, "\n"); 280 } else { 281 archive_string_sprintf(&shar->work, 282 "sed 's/^X//' > %s << 'SHAR_END'\n", 283 shar->quoted_name.s); 284 } 285 shar->has_data = 1; 286 shar->end_of_line = 1; 287 shar->outpos = 0; 288 } 289 break; 290 case AE_IFDIR: 291 archive_string_sprintf(&shar->work, 292 "mkdir -p %s > /dev/null 2>&1\n", 293 shar->quoted_name.s); 294 /* Record that we just created this directory. */ 295 free(shar->last_dir); 296 297 shar->last_dir = strdup(name); 298 if (shar->last_dir == NULL) { 299 archive_set_error(&a->archive, ENOMEM, "Out of memory"); 300 return (ARCHIVE_FATAL); 301 } 302 /* Trim a trailing '/'. */ 303 pp = strrchr(shar->last_dir, '/'); 304 if (pp != NULL && pp[1] == '\0') 305 *pp = '\0'; 306 /* 307 * TODO: Put dir name/mode on a list to be fixed 308 * up at end of archive. 309 */ 310 break; 311 case AE_IFIFO: 312 archive_string_sprintf(&shar->work, 313 "mkfifo %s\n", shar->quoted_name.s); 314 break; 315 case AE_IFCHR: 316 archive_string_sprintf(&shar->work, 317 "mknod %s c %ju %ju\n", shar->quoted_name.s, 318 (uintmax_t)archive_entry_rdevmajor(entry), 319 (uintmax_t)archive_entry_rdevminor(entry)); 320 break; 321 case AE_IFBLK: 322 archive_string_sprintf(&shar->work, 323 "mknod %s b %ju %ju\n", shar->quoted_name.s, 324 (uintmax_t)archive_entry_rdevmajor(entry), 325 (uintmax_t)archive_entry_rdevminor(entry)); 326 break; 327 default: 328 return (ARCHIVE_WARN); 329 } 330 } 331 332 return (ARCHIVE_OK); 333 } 334 335 static ssize_t 336 archive_write_shar_data_sed(struct archive_write *a, const void *buff, size_t n) 337 { 338 static const size_t ensured = 65533; 339 struct shar *shar; 340 const char *src; 341 char *buf, *buf_end; 342 int ret; 343 size_t written = n; 344 345 shar = (struct shar *)a->format_data; 346 if (!shar->has_data || n == 0) 347 return (0); 348 349 src = (const char *)buff; 350 351 /* 352 * ensure is the number of bytes in buffer before expanding the 353 * current character. Each operation writes the current character 354 * and optionally the start-of-new-line marker. This can happen 355 * twice before entering the loop, so make sure three additional 356 * bytes can be written. 357 */ 358 if (archive_string_ensure(&shar->work, ensured + 3) == NULL) { 359 archive_set_error(&a->archive, ENOMEM, "Out of memory"); 360 return (ARCHIVE_FATAL); 361 } 362 363 if (shar->work.length > ensured) { 364 ret = __archive_write_output(a, shar->work.s, 365 shar->work.length); 366 if (ret != ARCHIVE_OK) 367 return (ARCHIVE_FATAL); 368 archive_string_empty(&shar->work); 369 } 370 buf = shar->work.s + shar->work.length; 371 buf_end = shar->work.s + ensured; 372 373 if (shar->end_of_line) { 374 *buf++ = 'X'; 375 shar->end_of_line = 0; 376 } 377 378 while (n-- != 0) { 379 if ((*buf++ = *src++) == '\n') { 380 if (n == 0) 381 shar->end_of_line = 1; 382 else 383 *buf++ = 'X'; 384 } 385 386 if (buf >= buf_end) { 387 shar->work.length = buf - shar->work.s; 388 ret = __archive_write_output(a, shar->work.s, 389 shar->work.length); 390 if (ret != ARCHIVE_OK) 391 return (ARCHIVE_FATAL); 392 archive_string_empty(&shar->work); 393 buf = shar->work.s; 394 } 395 } 396 397 shar->work.length = buf - shar->work.s; 398 399 return (written); 400 } 401 402 #define UUENC(c) (((c)!=0) ? ((c) & 077) + ' ': '`') 403 404 static void 405 uuencode_group(const char _in[3], char out[4]) 406 { 407 const unsigned char *in = (const unsigned char *)_in; 408 int t; 409 410 t = (in[0] << 16) | (in[1] << 8) | in[2]; 411 out[0] = UUENC( 0x3f & (t >> 18) ); 412 out[1] = UUENC( 0x3f & (t >> 12) ); 413 out[2] = UUENC( 0x3f & (t >> 6) ); 414 out[3] = UUENC( 0x3f & t ); 415 } 416 417 static int 418 _uuencode_line(struct archive_write *a, struct shar *shar, const char *inbuf, size_t len) 419 { 420 char *buf; 421 size_t alloc_len; 422 423 /* len <= 45 -> expanded to 60 + len byte + new line */ 424 alloc_len = shar->work.length + 62; 425 if (archive_string_ensure(&shar->work, alloc_len) == NULL) { 426 archive_set_error(&a->archive, ENOMEM, "Out of memory"); 427 return (ARCHIVE_FATAL); 428 } 429 430 buf = shar->work.s + shar->work.length; 431 *buf++ = UUENC(len); 432 while (len >= 3) { 433 uuencode_group(inbuf, buf); 434 len -= 3; 435 inbuf += 3; 436 buf += 4; 437 } 438 if (len != 0) { 439 char tmp_buf[3]; 440 tmp_buf[0] = inbuf[0]; 441 if (len == 1) 442 tmp_buf[1] = '\0'; 443 else 444 tmp_buf[1] = inbuf[1]; 445 tmp_buf[2] = '\0'; 446 uuencode_group(tmp_buf, buf); 447 buf += 4; 448 } 449 *buf++ = '\n'; 450 if ((buf - shar->work.s) > (ptrdiff_t)(shar->work.length + 62)) { 451 archive_set_error(&a->archive, 452 ARCHIVE_ERRNO_MISC, "Buffer overflow"); 453 return (ARCHIVE_FATAL); 454 } 455 shar->work.length = buf - shar->work.s; 456 return (ARCHIVE_OK); 457 } 458 459 #define uuencode_line(__a, __shar, __inbuf, __len) \ 460 do { \ 461 int r = _uuencode_line(__a, __shar, __inbuf, __len); \ 462 if (r != ARCHIVE_OK) \ 463 return (ARCHIVE_FATAL); \ 464 } while (0) 465 466 static ssize_t 467 archive_write_shar_data_uuencode(struct archive_write *a, const void *buff, 468 size_t length) 469 { 470 struct shar *shar; 471 const char *src; 472 size_t n; 473 int ret; 474 475 shar = (struct shar *)a->format_data; 476 if (!shar->has_data) 477 return (ARCHIVE_OK); 478 src = (const char *)buff; 479 480 if (shar->outpos != 0) { 481 n = 45 - shar->outpos; 482 if (n > length) 483 n = length; 484 memcpy(shar->outbuff + shar->outpos, src, n); 485 if (shar->outpos + n < 45) { 486 shar->outpos += n; 487 return length; 488 } 489 uuencode_line(a, shar, shar->outbuff, 45); 490 src += n; 491 n = length - n; 492 } else { 493 n = length; 494 } 495 496 while (n >= 45) { 497 uuencode_line(a, shar, src, 45); 498 src += 45; 499 n -= 45; 500 501 if (shar->work.length < 65536) 502 continue; 503 ret = __archive_write_output(a, shar->work.s, 504 shar->work.length); 505 if (ret != ARCHIVE_OK) 506 return (ARCHIVE_FATAL); 507 archive_string_empty(&shar->work); 508 } 509 if (n != 0) { 510 memcpy(shar->outbuff, src, n); 511 shar->outpos = n; 512 } 513 return (length); 514 } 515 516 static int 517 archive_write_shar_finish_entry(struct archive_write *a) 518 { 519 const char *g, *p, *u; 520 struct shar *shar; 521 int ret; 522 523 shar = (struct shar *)a->format_data; 524 if (shar->entry == NULL) 525 return (0); 526 527 if (shar->dump) { 528 /* Finish uuencoded data. */ 529 if (shar->has_data) { 530 if (shar->outpos > 0) 531 uuencode_line(a, shar, shar->outbuff, 532 shar->outpos); 533 archive_strcat(&shar->work, "`\nend\n"); 534 archive_strcat(&shar->work, "SHAR_END\n"); 535 } 536 /* Restore file mode, owner, flags. */ 537 /* 538 * TODO: Don't immediately restore mode for 539 * directories; defer that to end of script. 540 */ 541 archive_string_sprintf(&shar->work, "chmod %o ", 542 (unsigned int)(archive_entry_mode(shar->entry) & 07777)); 543 shar_quote(&shar->work, archive_entry_pathname(shar->entry), 1); 544 archive_strcat(&shar->work, "\n"); 545 546 u = archive_entry_uname(shar->entry); 547 g = archive_entry_gname(shar->entry); 548 if (u != NULL || g != NULL) { 549 archive_strcat(&shar->work, "chown "); 550 if (u != NULL) 551 shar_quote(&shar->work, u, 1); 552 if (g != NULL) { 553 archive_strcat(&shar->work, ":"); 554 shar_quote(&shar->work, g, 1); 555 } 556 archive_strcat(&shar->work, " "); 557 shar_quote(&shar->work, 558 archive_entry_pathname(shar->entry), 1); 559 archive_strcat(&shar->work, "\n"); 560 } 561 562 if ((p = archive_entry_fflags_text(shar->entry)) != NULL) { 563 archive_string_sprintf(&shar->work, "chflags %s ", p); 564 shar_quote(&shar->work, 565 archive_entry_pathname(shar->entry), 1); 566 archive_strcat(&shar->work, "\n"); 567 } 568 569 /* TODO: restore ACLs */ 570 571 } else { 572 if (shar->has_data) { 573 /* Finish sed-encoded data: ensure last line ends. */ 574 if (!shar->end_of_line) 575 archive_strappend_char(&shar->work, '\n'); 576 archive_strcat(&shar->work, "SHAR_END\n"); 577 } 578 } 579 580 archive_entry_free(shar->entry); 581 shar->entry = NULL; 582 583 if (shar->work.length < 65536) 584 return (ARCHIVE_OK); 585 586 ret = __archive_write_output(a, shar->work.s, shar->work.length); 587 if (ret != ARCHIVE_OK) 588 return (ARCHIVE_FATAL); 589 archive_string_empty(&shar->work); 590 591 return (ARCHIVE_OK); 592 } 593 594 static int 595 archive_write_shar_close(struct archive_write *a) 596 { 597 struct shar *shar; 598 int ret; 599 600 /* 601 * TODO: Accumulate list of directory names/modes and 602 * fix them all up at end-of-archive. 603 */ 604 605 shar = (struct shar *)a->format_data; 606 607 /* 608 * Only write the end-of-archive markers if the archive was 609 * actually started. This avoids problems if someone sets 610 * shar format, then sets another format (which would invoke 611 * shar_finish to free the format-specific data). 612 */ 613 if (shar->wrote_header == 0) 614 return (ARCHIVE_OK); 615 616 archive_strcat(&shar->work, "exit\n"); 617 618 ret = __archive_write_output(a, shar->work.s, shar->work.length); 619 if (ret != ARCHIVE_OK) 620 return (ARCHIVE_FATAL); 621 622 /* Shar output is never padded. */ 623 archive_write_set_bytes_in_last_block(&a->archive, 1); 624 /* 625 * TODO: shar should also suppress padding of 626 * uncompressed data within gzip/bzip2 streams. 627 */ 628 629 return (ARCHIVE_OK); 630 } 631 632 static int 633 archive_write_shar_free(struct archive_write *a) 634 { 635 struct shar *shar; 636 637 shar = (struct shar *)a->format_data; 638 if (shar == NULL) 639 return (ARCHIVE_OK); 640 641 archive_entry_free(shar->entry); 642 free(shar->last_dir); 643 archive_string_free(&(shar->work)); 644 archive_string_free(&(shar->quoted_name)); 645 free(shar); 646 a->format_data = NULL; 647 return (ARCHIVE_OK); 648 } 649