switch_root: improve behavior on error; improve help text
[platform/upstream/busybox.git] / archival / libunarchive / open_transformer.c
index 578b929..47c13e6 100644 (file)
@@ -3,40 +3,62 @@
  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  */
 
-#include <stdlib.h>
-#include <unistd.h>
-
 #include "libbb.h"
-
 #include "unarchive.h"
 
 /* transformer(), more than meets the eye */
-int open_transformer(int src_fd, int (*transformer)(int src_fd, int dst_fd))
+/*
+ * On MMU machine, the transform_prog is removed by macro magic
+ * in include/unarchive.h. On NOMMU, transformer is removed.
+ */
+void FAST_FUNC open_transformer(int fd,
+       IF_DESKTOP(long long) int FAST_FUNC (*transformer)(int src_fd, int dst_fd),
+       const char *transform_prog)
 {
-       int fd_pipe[2];
+       struct fd_pair fd_pipe;
        int pid;
 
-       if (pipe(fd_pipe) != 0) {
-               bb_perror_msg_and_die("Can't create pipe");
-       }
+       xpiped_pair(fd_pipe);
 
+#if BB_MMU
        pid = fork();
-       if (pid == -1) {
-               bb_perror_msg_and_die("Fork failed");
-       }
+       if (pid == -1)
+               bb_perror_msg_and_die("vfork" + 1);
+#else
+       pid = vfork();
+       if (pid == -1)
+               bb_perror_msg_and_die("vfork");
+#endif
 
        if (pid == 0) {
                /* child process */
-           close(fd_pipe[0]); /* We don't wan't to read from the parent */
-           transformer(src_fd, fd_pipe[1]);
-           close(fd_pipe[1]); /* Send EOF */
-               close(src_fd);
-           exit(0);
-           /* notreached */
+               close(fd_pipe.rd); /* we don't want to read from the parent */
+               // FIXME: error check?
+#if BB_MMU
+               transformer(fd, fd_pipe.wr);
+               if (ENABLE_FEATURE_CLEAN_UP) {
+                       close(fd_pipe.wr); /* send EOF */
+                       close(fd);
+               }
+               /* must be _exit! bug was actually seen here */
+               _exit(EXIT_SUCCESS);
+#else
+               {
+                       char *argv[4];
+                       xmove_fd(fd, 0);
+                       xmove_fd(fd_pipe.wr, 1);
+                       argv[0] = (char*)transform_prog;
+                       argv[1] = (char*)"-cf";
+                       argv[2] = (char*)"-";
+                       argv[3] = NULL;
+                       BB_EXECVP(transform_prog, argv);
+                       bb_perror_msg_and_die("can't execute '%s'", transform_prog);
+               }
+#endif
+               /* notreached */
        }
 
        /* parent process */
-       close(fd_pipe[1]); /* Don't want to write to the child */
-
-       return(fd_pipe[0]);
+       close(fd_pipe.wr); /* don't want to write to the child */
+       xmove_fd(fd_pipe.rd, fd);
 }