diff options
-rw-r--r-- | archival/libunarchive/open_transformer.c | 6 | ||||
-rw-r--r-- | archival/tar.c | 82 | ||||
-rw-r--r-- | include/libbb.h | 3 |
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 { | |||
106 | typedef enum TarFileType TarFileType; | 106 | typedef 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;) */ |
109 | static void addHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr, | 109 | static 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 | ||
125 | static void freeHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr) | 125 | static 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;) */ |
142 | static HardLinkInfo *findHardLinkInfo(HardLinkInfo * hlInfo, struct stat *statbuf) | 142 | static 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); | |||
512 | char *find_execable(const char *filename); | 512 | char *find_execable(const char *filename); |
513 | int exists_execable(const char *filename); | 513 | int 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 |
516 | int bb_execvp(const char *file, char *const argv[]); | 519 | int 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) |