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); |