diff options
| author | Robert Griebl <griebl@gmx.de> | 2002-07-23 22:05:47 +0000 |
|---|---|---|
| committer | Robert Griebl <griebl@gmx.de> | 2002-07-23 22:05:47 +0000 |
| commit | f2f26e7fdddfb92a8ef3654e14092dcbe3420331 (patch) | |
| tree | 04b2388564e5f3244b3a4e6d304a00a8b9caeed9 | |
| parent | 967c3d44066d3f8b290953d8896765ec1edf4ef7 (diff) | |
| download | busybox-w32-f2f26e7fdddfb92a8ef3654e14092dcbe3420331.tar.gz busybox-w32-f2f26e7fdddfb92a8ef3654e14092dcbe3420331.tar.bz2 busybox-w32-f2f26e7fdddfb92a8ef3654e14092dcbe3420331.zip | |
Added tar -cz support (creating gzipped tar files without a gzip pipe)
| -rw-r--r-- | archival/config.in | 2 | ||||
| -rw-r--r-- | archival/tar.c | 119 |
2 files changed, 95 insertions, 26 deletions
diff --git a/archival/config.in b/archival/config.in index 5a064dc89..ac90ec0a9 100644 --- a/archival/config.in +++ b/archival/config.in | |||
| @@ -18,7 +18,7 @@ bool 'tar' CONFIG_TAR | |||
| 18 | if [ "$CONFIG_TAR" = "y" ] ; then | 18 | if [ "$CONFIG_TAR" = "y" ] ; then |
| 19 | bool ' Enable archive creation' CONFIG_FEATURE_TAR_CREATE | 19 | bool ' Enable archive creation' CONFIG_FEATURE_TAR_CREATE |
| 20 | bool ' Enable -X and --exclude options (exclude files)' CONFIG_FEATURE_TAR_EXCLUDE | 20 | bool ' Enable -X and --exclude options (exclude files)' CONFIG_FEATURE_TAR_EXCLUDE |
| 21 | bool ' Enable -z option (currently only for extracting)' CONFIG_FEATURE_TAR_GZIP | 21 | bool ' Enable -z option' CONFIG_FEATURE_TAR_GZIP |
| 22 | fi | 22 | fi |
| 23 | if [ "$CONFIG_CPIO" = "y" -o "$CONFIG_TAR" = "y" ] ; then | 23 | if [ "$CONFIG_CPIO" = "y" -o "$CONFIG_TAR" = "y" ] ; then |
| 24 | bool ' Enable tape drive support' CONFIG_FEATURE_UNARCHIVE_TAPE | 24 | bool ' Enable tape drive support' CONFIG_FEATURE_UNARCHIVE_TAPE |
diff --git a/archival/tar.c b/archival/tar.c index b18f1f87f..2aa5f0788 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
| @@ -47,6 +47,9 @@ | |||
| 47 | #include <fnmatch.h> | 47 | #include <fnmatch.h> |
| 48 | #include <string.h> | 48 | #include <string.h> |
| 49 | #include <errno.h> | 49 | #include <errno.h> |
| 50 | #include <signal.h> | ||
| 51 | #include <sys/wait.h> | ||
| 52 | #include <sys/socket.h> | ||
| 50 | #include "unarchive.h" | 53 | #include "unarchive.h" |
| 51 | #include "busybox.h" | 54 | #include "busybox.h" |
| 52 | 55 | ||
| @@ -305,9 +308,10 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *header_name, | |||
| 305 | write(tbInfo->tarFd, "\0", 1); | 308 | write(tbInfo->tarFd, "\0", 1); |
| 306 | } | 309 | } |
| 307 | /* Now do the verbose thing (or not) */ | 310 | /* Now do the verbose thing (or not) */ |
| 308 | if (tbInfo->verboseFlag==TRUE) { | 311 | |
| 312 | if (tbInfo->verboseFlag) { | ||
| 309 | FILE *vbFd = stdout; | 313 | FILE *vbFd = stdout; |
| 310 | if (tbInfo->tarFd == fileno(stdout)) // If the archive goes to stdout, verbose to stderr | 314 | if (tbInfo->verboseFlag == 2) // If the archive goes to stdout, verbose to stderr |
| 311 | vbFd = stderr; | 315 | vbFd = stderr; |
| 312 | fprintf(vbFd, "%s\n", header.name); | 316 | fprintf(vbFd, "%s\n", header.name); |
| 313 | } | 317 | } |
| @@ -445,13 +449,17 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* | |||
| 445 | } | 449 | } |
| 446 | 450 | ||
| 447 | static int writeTarFile(const char* tarName, int verboseFlag, char **argv, | 451 | static int writeTarFile(const char* tarName, int verboseFlag, char **argv, |
| 448 | char** excludeList) | 452 | char** excludeList, int gzip) |
| 449 | { | 453 | { |
| 450 | int tarFd=-1; | 454 | #ifdef CONFIG_FEATURE_TAR_GZIP |
| 455 | int gzipDataPipe [2] = { -1, -1 }; | ||
| 456 | int gzipStatusPipe [2] = { -1, -1 }; | ||
| 457 | pid_t gzipPid = 0; | ||
| 458 | #endif | ||
| 459 | |||
| 451 | int errorFlag=FALSE; | 460 | int errorFlag=FALSE; |
| 452 | ssize_t size; | 461 | ssize_t size; |
| 453 | struct TarBallInfo tbInfo; | 462 | struct TarBallInfo tbInfo; |
| 454 | tbInfo.verboseFlag = verboseFlag; | ||
| 455 | tbInfo.hlInfoHead = NULL; | 463 | tbInfo.hlInfoHead = NULL; |
| 456 | 464 | ||
| 457 | /* Make sure there is at least one file to tar up. */ | 465 | /* Make sure there is at least one file to tar up. */ |
| @@ -459,21 +467,78 @@ static int writeTarFile(const char* tarName, int verboseFlag, char **argv, | |||
| 459 | error_msg_and_die("Cowardly refusing to create an empty archive"); | 467 | error_msg_and_die("Cowardly refusing to create an empty archive"); |
| 460 | 468 | ||
| 461 | /* Open the tar file for writing. */ | 469 | /* Open the tar file for writing. */ |
| 462 | if (tarName == NULL) | 470 | if (tarName == NULL) { |
| 463 | tbInfo.tarFd = fileno(stdout); | 471 | tbInfo.tarFd = fileno(stdout); |
| 464 | else | 472 | tbInfo.verboseFlag = verboseFlag ? 2 : 0; |
| 473 | } | ||
| 474 | else { | ||
| 465 | tbInfo.tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644); | 475 | tbInfo.tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644); |
| 476 | tbInfo.verboseFlag = verboseFlag ? 1 : 0; | ||
| 477 | } | ||
| 478 | |||
| 466 | if (tbInfo.tarFd < 0) { | 479 | if (tbInfo.tarFd < 0) { |
| 467 | perror_msg( "Error opening '%s'", tarName); | 480 | perror_msg( "Error opening '%s'", tarName); |
| 468 | freeHardLinkInfo(&tbInfo.hlInfoHead); | 481 | freeHardLinkInfo(&tbInfo.hlInfoHead); |
| 469 | return ( FALSE); | 482 | return ( FALSE); |
| 470 | } | 483 | } |
| 471 | tbInfo.excludeList=excludeList; | 484 | |
| 472 | /* Store the stat info for the tarball's file, so | 485 | /* Store the stat info for the tarball's file, so |
| 473 | * can avoid including the tarball into itself.... */ | 486 | * can avoid including the tarball into itself.... */ |
| 474 | if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0) | 487 | if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0) |
| 475 | error_msg_and_die(io_error, tarName, strerror(errno)); | 488 | error_msg_and_die(io_error, tarName, strerror(errno)); |
| 476 | 489 | ||
| 490 | #ifdef CONFIG_FEATURE_TAR_GZIP | ||
| 491 | if ( gzip ) { | ||
| 492 | if ( socketpair ( AF_UNIX, SOCK_STREAM, 0, gzipDataPipe ) < 0 || pipe ( gzipStatusPipe ) < 0 ) | ||
| 493 | perror_msg_and_die ( "Failed to create gzip pipe" ); | ||
| 494 | |||
| 495 | signal ( SIGPIPE, SIG_IGN ); // we only want EPIPE on errors | ||
| 496 | |||
| 497 | gzipPid = fork ( ); | ||
| 498 | |||
| 499 | if ( gzipPid == 0 ) { | ||
| 500 | dup2 ( gzipDataPipe [0], 0 ); | ||
| 501 | close ( gzipDataPipe [1] ); | ||
| 502 | |||
| 503 | if ( tbInfo. tarFd != 1 ); | ||
| 504 | dup2 ( tbInfo. tarFd, 1 ); | ||
| 505 | |||
| 506 | close ( gzipStatusPipe [0] ); | ||
| 507 | fcntl( gzipStatusPipe [1], F_SETFD, FD_CLOEXEC ); // close on exec shows sucess | ||
| 508 | |||
| 509 | execl ( "/bin/gzip", "gzip", "-f", 0 ); | ||
| 510 | |||
| 511 | write ( gzipStatusPipe [1], "", 1 ); | ||
| 512 | close ( gzipStatusPipe [1] ); | ||
| 513 | |||
| 514 | exit ( -1 ); | ||
| 515 | } | ||
| 516 | else if ( gzipPid > 0 ) { | ||
| 517 | close ( gzipDataPipe [0] ); | ||
| 518 | close ( gzipStatusPipe [1] ); | ||
| 519 | |||
| 520 | while ( 1 ) { | ||
| 521 | char buf; | ||
| 522 | |||
| 523 | int n = read ( gzipStatusPipe [0], &buf, 1 ); | ||
| 524 | if ( n == 1 ) | ||
| 525 | error_msg_and_die ( "Could not exec gzip process" ); // socket was not closed => error | ||
| 526 | else if (( n < 0 ) && ( errno==EAGAIN || errno==EINTR )) | ||
| 527 | continue; // try it again | ||
| 528 | break; | ||
| 529 | } | ||
| 530 | close ( gzipStatusPipe [0] ); | ||
| 531 | |||
| 532 | tbInfo. tarFd = gzipDataPipe [1]; | ||
| 533 | } | ||
| 534 | else { | ||
| 535 | perror_msg_and_die ( "Failed to fork gzip process" ); | ||
| 536 | } | ||
| 537 | } | ||
| 538 | #endif | ||
| 539 | |||
| 540 | tbInfo.excludeList=excludeList; | ||
| 541 | |||
| 477 | /* Read the directory/files and iterate over them one at a time */ | 542 | /* Read the directory/files and iterate over them one at a time */ |
| 478 | while (*argv != NULL) { | 543 | while (*argv != NULL) { |
| 479 | if (! recursive_action(*argv++, TRUE, FALSE, FALSE, | 544 | if (! recursive_action(*argv++, TRUE, FALSE, FALSE, |
| @@ -493,14 +558,20 @@ static int writeTarFile(const char* tarName, int verboseFlag, char **argv, | |||
| 493 | * so is considered a waste of space */ | 558 | * so is considered a waste of space */ |
| 494 | 559 | ||
| 495 | /* Hang up the tools, close up shop, head home */ | 560 | /* Hang up the tools, close up shop, head home */ |
| 496 | close(tarFd); | 561 | close(tbInfo.tarFd); |
| 497 | if (errorFlag) { | 562 | if (errorFlag) |
| 498 | error_msg("Error exit delayed from previous errors"); | 563 | error_msg("Error exit delayed from previous errors"); |
| 499 | freeHardLinkInfo(&tbInfo.hlInfoHead); | 564 | |
| 500 | return(FALSE); | ||
| 501 | } | ||
| 502 | freeHardLinkInfo(&tbInfo.hlInfoHead); | 565 | freeHardLinkInfo(&tbInfo.hlInfoHead); |
| 503 | return( TRUE); | 566 | |
| 567 | #ifdef CONFIG_FEATURE_TAR_GZIP | ||
| 568 | if ( gzip && gzipPid ) { | ||
| 569 | if ( waitpid ( gzipPid, NULL, 0 ) == -1 ) | ||
| 570 | printf ( "Couldnt wait ?" ); | ||
| 571 | } | ||
| 572 | #endif | ||
| 573 | |||
| 574 | return !errorFlag; | ||
| 504 | } | 575 | } |
| 505 | #endif //tar_create | 576 | #endif //tar_create |
| 506 | 577 | ||
| @@ -653,10 +724,7 @@ int tar_main(int argc, char **argv) | |||
| 653 | case 'p': | 724 | case 'p': |
| 654 | break; | 725 | break; |
| 655 | case 'v': | 726 | case 'v': |
| 656 | if (extract_function & extract_list) { | 727 | extract_function |= extract_verbose_list; |
| 657 | extract_function |= extract_verbose_list; | ||
| 658 | } | ||
| 659 | extract_function |= extract_list; | ||
| 660 | break; | 728 | break; |
| 661 | #ifdef CONFIG_FEATURE_TAR_GZIP | 729 | #ifdef CONFIG_FEATURE_TAR_GZIP |
| 662 | case 'z': | 730 | case 'z': |
| @@ -711,22 +779,23 @@ int tar_main(int argc, char **argv) | |||
| 711 | /* create an archive */ | 779 | /* create an archive */ |
| 712 | else if (untar_funct & untar_create) { | 780 | else if (untar_funct & untar_create) { |
| 713 | int verboseFlag = FALSE; | 781 | int verboseFlag = FALSE; |
| 782 | int gzipFlag = FALSE; | ||
| 714 | 783 | ||
| 715 | #ifdef CONFIG_FEATURE_TAR_GZIP | 784 | #ifdef CONFIG_FEATURE_TAR_GZIP |
| 716 | if (untar_funct & untar_unzip) { | 785 | if (untar_funct & untar_unzip) |
| 717 | error_msg_and_die("Creation of compressed tarfile not internally support by tar, pipe to busybox gunzip"); | 786 | gzipFlag = TRUE; |
| 718 | } | 787 | |
| 719 | #endif // CONFIG_FEATURE_TAR_GZIP | 788 | #endif // CONFIG_FEATURE_TAR_GZIP |
| 720 | if (extract_function & extract_verbose_list) { | 789 | if (extract_function & extract_verbose_list) |
| 721 | verboseFlag = TRUE; | 790 | verboseFlag = TRUE; |
| 722 | } | 791 | |
| 723 | writeTarFile(src_filename, verboseFlag, include_list, exclude_list); | 792 | writeTarFile(src_filename, verboseFlag, include_list, exclude_list, gzipFlag); |
| 724 | } | 793 | } |
| 725 | #endif // CONFIG_FEATURE_TAR_CREATE | 794 | #endif // CONFIG_FEATURE_TAR_CREATE |
| 726 | 795 | ||
| 727 | /* Cleanups */ | 796 | /* Cleanups */ |
| 728 | #ifdef CONFIG_FEATURE_TAR_GZIP | 797 | #ifdef CONFIG_FEATURE_TAR_GZIP |
| 729 | if (untar_funct & untar_unzip) { | 798 | if ( !( untar_funct & untar_create ) && ( untar_funct & untar_unzip )) { |
| 730 | fclose(src_stream); | 799 | fclose(src_stream); |
| 731 | close(gz_fd); | 800 | close(gz_fd); |
| 732 | gz_close(gunzip_pid); | 801 | gz_close(gunzip_pid); |
