From 4a045c6d6255629f8a50c741c59caac1e2e6b94f Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 21 Apr 2019 03:56:25 -0500 Subject: Switch --to-command to use xsetenv() and fix a typo with -J --- toys/pending/tar.c | 68 ++++++++++++++++++------------------------------------ 1 file changed, 23 insertions(+), 45 deletions(-) diff --git a/toys/pending/tar.c b/toys/pending/tar.c index 8a901270..f31b5f2b 100644 --- a/toys/pending/tar.c +++ b/toys/pending/tar.c @@ -18,7 +18,7 @@ * Extract into dir same as filename, --restrict? "Tarball is splodey" * -USE_TAR(NEWTOY(tar, "&(restrict)(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)J(xz)j(bzip2)z(gzip)O(to-stdout)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):[!txc][!jzJa]", TOYFLAG_USR|TOYFLAG_BIN)) +USE_TAR(NEWTOY(tar, "&(restrict)(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)J(xz)j(bzip2)z(gzip)O(to-stdout)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):a[!txc][!jzJa]", TOYFLAG_USR|TOYFLAG_BIN)) config TAR bool "tar" @@ -317,47 +317,6 @@ done: return (DIRTREE_RECURSE|(FLAG(h)?DIRTREE_SYMFOLLOW:0))*!FLAG(no_recursion); } -// Does anybody actually use this? -static void extract_to_command(void) -{ - int pipefd[2], status = 0; - pid_t cpid; - - if (!S_ISREG(TT.hdr.mode)) return; //only regular files are supported. - - xpipe(pipefd); - if (!(cpid = xfork())) { // Child reads from pipe - char buf[64], *argv[4] = {"sh", "-c", TT.to_command, NULL}; - - setenv("TAR_FILETYPE", "f", 1); - sprintf(buf, "%0o", TT.hdr.mode); - setenv("TAR_MODE", buf, 1); - sprintf(buf, "%lld", (long long)TT.hdr.size); - setenv("TAR_SIZE", buf, 1); - setenv("TAR_FILENAME", TT.hdr.name, 1); - setenv("TAR_UNAME", TT.hdr.uname, 1); - setenv("TAR_GNAME", TT.hdr.gname, 1); - sprintf(buf, "%0llo", (long long)TT.hdr.mtime); - setenv("TAR_MTIME", buf, 1); - sprintf(buf, "%0o", TT.hdr.uid); - setenv("TAR_UID", buf, 1); - sprintf(buf, "%0o", TT.hdr.gid); - setenv("TAR_GID", buf, 1); - - xclose(pipefd[1]); // Close unused write - dup2(pipefd[0], 0); - signal(SIGPIPE, SIG_DFL); - xexec(argv); - } else { - xclose(pipefd[0]); // Close unused read end - xsendfile_len(TT.fd, pipefd[1], TT.hdr.size); - xclose(pipefd[1]); - waitpid(cpid, &status, 0); - if (WIFSIGNALED(status)) - xprintf("tar : %d: child returned %d\n", cpid, WTERMSIG(status)); - } -} - static void wsettime(char *s, long long sec) { struct timespec times[2] = {{sec, 0},{sec, 0}}; @@ -638,8 +597,27 @@ static void unpack_tar(struct tar_hdr *first) } else { if (FLAG(v)) printf("%s\n", TT.hdr.name); if (FLAG(O)) xsendfile_len(TT.fd, 1, TT.hdr.size); - else if (FLAG(to_command)) extract_to_command(); - else extract_to_disk(); + else if (FLAG(to_command)) { + if (S_ISREG(TT.hdr.mode)) { + int fd, pid; + + xsetenv("TAR_FILETYPE", "f"); + xsetenv(xmprintf("TAR_MODE=%o", TT.hdr.mode), 0); + xsetenv(xmprintf("TAR_SIZE=%lld", TT.hdr.size), 0); + xsetenv("TAR_FILENAME", TT.hdr.name); + xsetenv("TAR_UNAME", TT.hdr.uname); + xsetenv("TAR_GNAME", TT.hdr.gname); + xsetenv(xmprintf("TAR_MTIME=%llo", (long long)TT.hdr.mtime), 0); + xsetenv(xmprintf("TAR_UID=%o", TT.hdr.uid), 0); + xsetenv(xmprintf("TAR_GID=%o", TT.hdr.gid), 0); + + pid = xpopen((char *[]){"sh", "-c", TT.to_command, NULL}, &fd, 0); + // todo: short write exits tar here, other skips data. + xsendfile_len(TT.fd, fd, TT.hdr.size); + fd = xpclose(pid, fd); + if (fd) error_msg("%d: Child returned %d", pid, fd); + } + } else extract_to_disk(); } free(TT.hdr.name); @@ -804,7 +782,7 @@ void tar_main(void) if (strend(TT.f, ".tgz") || strend(TT.f, ".tar.gz")) toys.optflags |= FLAG_z; if (strend(TT.f, ".txz") || strend(TT.f, ".tar.xz")) - toys.optflags | FLAG_J; + toys.optflags |= FLAG_J; else for (len = 0; len