aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archival/libunarchive/open_transformer.c6
-rw-r--r--archival/tar.c82
-rw-r--r--include/libbb.h3
3 files changed, 54 insertions, 37 deletions
diff --git a/archival/libunarchive/open_transformer.c b/archival/libunarchive/open_transformer.c
index 0ee080621..93f01be6f 100644
--- a/archival/libunarchive/open_transformer.c
+++ b/archival/libunarchive/open_transformer.c
@@ -25,8 +25,10 @@ int open_transformer(int src_fd,
25 close(fd_pipe[0]); /* We don't wan't to read from the parent */ 25 close(fd_pipe[0]); /* We don't wan't to read from the parent */
26 // FIXME: error check? 26 // FIXME: error check?
27 transformer(src_fd, fd_pipe[1]); 27 transformer(src_fd, fd_pipe[1]);
28 close(fd_pipe[1]); /* Send EOF */ 28 if (ENABLE_FEATURE_CLEAN_UP) {
29 close(src_fd); 29 close(fd_pipe[1]); /* Send EOF */
30 close(src_fd);
31 }
30 exit(0); 32 exit(0);
31 /* notreached */ 33 /* notreached */
32 } 34 }
diff --git a/archival/tar.c b/archival/tar.c
index 9bf9058d8..f0d397114 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -106,7 +106,7 @@ enum TarFileType {
106typedef enum TarFileType TarFileType; 106typedef enum TarFileType TarFileType;
107 107
108/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */ 108/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */
109static void addHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr, 109static void addHardLinkInfo(HardLinkInfo **hlInfoHeadPtr,
110 struct stat *statbuf, 110 struct stat *statbuf,
111 const char *fileName) 111 const char *fileName)
112{ 112{
@@ -122,7 +122,7 @@ static void addHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr,
122 strcpy(hlInfo->name, fileName); 122 strcpy(hlInfo->name, fileName);
123} 123}
124 124
125static void freeHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr) 125static void freeHardLinkInfo(HardLinkInfo **hlInfoHeadPtr)
126{ 126{
127 HardLinkInfo *hlInfo; 127 HardLinkInfo *hlInfo;
128 HardLinkInfo *hlInfoNext; 128 HardLinkInfo *hlInfoNext;
@@ -139,7 +139,7 @@ static void freeHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr)
139} 139}
140 140
141/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */ 141/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */
142static HardLinkInfo *findHardLinkInfo(HardLinkInfo * hlInfo, struct stat *statbuf) 142static HardLinkInfo *findHardLinkInfo(HardLinkInfo *hlInfo, struct stat *statbuf)
143{ 143{
144 while (hlInfo) { 144 while (hlInfo) {
145 if ((statbuf->st_ino == hlInfo->ino) && (statbuf->st_dev == hlInfo->dev)) 145 if ((statbuf->st_ino == hlInfo->ino) && (statbuf->st_dev == hlInfo->dev))
@@ -504,13 +504,21 @@ static int writeTarFile(const int tar_fd, const int verboseFlag,
504 bb_perror_msg_and_die("cannot stat tar file"); 504 bb_perror_msg_and_die("cannot stat tar file");
505 505
506 if ((ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2) && gzip) { 506 if ((ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2) && gzip) {
507 int gzipDataPipe[2] = { -1, -1 }; 507// On Linux, vfork never unpauses parent early, although standard
508 int gzipStatusPipe[2] = { -1, -1 }; 508// allows for that. Do we want to waste bytes checking for it?
509#define WAIT_FOR_CHILD 0
510
509 volatile int vfork_exec_errno = 0; 511 volatile int vfork_exec_errno = 0;
512#if WAIT_FOR_CHILD
513 struct { int rd; int wr; } gzipStatusPipe;
514#endif
515 struct { int rd; int wr; } gzipDataPipe;
510 const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2"; 516 const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2";
511 517
512 xpipe(gzipDataPipe); 518 xpipe(&gzipDataPipe.rd);
513 xpipe(gzipStatusPipe); 519#if WAIT_FOR_CHILD
520 xpipe(&gzipStatusPipe.rd);
521#endif
514 522
515 signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */ 523 signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */
516 524
@@ -522,41 +530,45 @@ static int writeTarFile(const int tar_fd, const int verboseFlag,
522#endif 530#endif
523 531
524 gzipPid = vfork(); 532 gzipPid = vfork();
533 if (gzipPid < 0)
534 bb_perror_msg_and_die("vfork gzip");
525 535
526 if (gzipPid == 0) { 536 if (gzipPid == 0) {
527 dup2(gzipDataPipe[0], 0); 537 /* child */
528 close(gzipDataPipe[1]); 538 xmove_fd(tbInfo.tarFd, 1);
529 539 xmove_fd(gzipDataPipe.rd, 0);
530 dup2(tbInfo.tarFd, 1); 540 close(gzipDataPipe.wr);
531 541#if WAIT_FOR_CHILD
532 close(gzipStatusPipe[0]); 542 close(gzipStatusPipe.rd);
533 fcntl(gzipStatusPipe[1], F_SETFD, FD_CLOEXEC); /* close on exec shows success */ 543 fcntl(gzipStatusPipe.wr, F_SETFD, FD_CLOEXEC);
534 544#endif
545 /* exec gzip/bzip2 program/applet */
535 BB_EXECLP(zip_exec, zip_exec, "-f", NULL); 546 BB_EXECLP(zip_exec, zip_exec, "-f", NULL);
536 vfork_exec_errno = errno; 547 vfork_exec_errno = errno;
548 _exit(1);
549 }
537 550
538 close(gzipStatusPipe[1]); 551 /* parent */
539 exit(-1); 552 xmove_fd(gzipDataPipe.wr, tbInfo.tarFd);
540 } else if (gzipPid > 0) { 553 close(gzipDataPipe.rd);
541 close(gzipDataPipe[0]); 554#if WAIT_FOR_CHILD
542 close(gzipStatusPipe[1]); 555 close(gzipStatusPipe.wr);
543 556 while (1) {
544 while (1) { 557 char buf;
545 char buf; 558 int n;
546
547 int n = full_read(gzipStatusPipe[0], &buf, 1);
548 559
549 if (n == 0 && vfork_exec_errno != 0) { 560 /* Wait until child execs (or fails to) */
550 errno = vfork_exec_errno; 561 n = full_read(gzipStatusPipe.rd, &buf, 1);
551 bb_perror_msg_and_die("cannot exec %s", zip_exec); 562 if ((n < 0) && (/*errno == EAGAIN ||*/ errno == EINTR))
552 } else if ((n < 0) && (errno == EAGAIN || errno == EINTR)) 563 continue; /* try it again */
553 continue; /* try it again */
554 break;
555 }
556 close(gzipStatusPipe[0]);
557 564
558 tbInfo.tarFd = gzipDataPipe[1]; 565 }
559 } else bb_perror_msg_and_die("vfork gzip"); 566 close(gzipStatusPipe.rd);
567#endif
568 if (vfork_exec_errno) {
569 errno = vfork_exec_errno;
570 bb_perror_msg_and_die("cannot exec %s", zip_exec);
571 }
560 } 572 }
561 573
562 tbInfo.excludeList = exclude; 574 tbInfo.excludeList = exclude;
diff --git a/include/libbb.h b/include/libbb.h
index 6c6b4863c..cf00b5250 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -512,6 +512,9 @@ int execable_file(const char *name);
512char *find_execable(const char *filename); 512char *find_execable(const char *filename);
513int exists_execable(const char *filename); 513int exists_execable(const char *filename);
514 514
515/* BB_EXECxx always execs (it's not doing NOFORK/NOEXEC stuff),
516 * but it may exec busybox and call applet instead of searching PATH.
517 */
515#if ENABLE_FEATURE_PREFER_APPLETS 518#if ENABLE_FEATURE_PREFER_APPLETS
516int bb_execvp(const char *file, char *const argv[]); 519int bb_execvp(const char *file, char *const argv[]);
517#define BB_EXECVP(prog,cmd) bb_execvp(prog,cmd) 520#define BB_EXECVP(prog,cmd) bb_execvp(prog,cmd)