summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLadislav Michl <Ladislav.Michl@seznam.cz>2010-06-25 01:33:00 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-06-25 01:33:00 +0200
commit2b46fd49b14b2ac30e0c767c65ac2b29f6922a45 (patch)
tree184e89b5922c87c866c7ae02ca4a87a61d0ac384
parent51fa147c9bab41cc1f7bf5b2e3bbeddf0fdaf5ca (diff)
downloadbusybox-w32-2b46fd49b14b2ac30e0c767c65ac2b29f6922a45.tar.gz
busybox-w32-2b46fd49b14b2ac30e0c767c65ac2b29f6922a45.tar.bz2
busybox-w32-2b46fd49b14b2ac30e0c767c65ac2b29f6922a45.zip
tar: optional support for --to-command
function old new delta data_extract_to_command - 430 +430 dec2env - 44 +44 tar_main 778 819 +41 str2env - 37 +37 tar_var - 32 +32 xputenv - 22 +22 tar_longopts 257 270 +13 ------------------------------------------------------------------------------ (add/remove: 6/0 grow/shrink: 2/0 up/down: 619/0) Total: 619 bytes Signed-off-by: Ladislav Michl <Ladislav.Michl@seznam.cz> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--archival/Config.src9
-rw-r--r--archival/libunarchive/Kbuild.src1
-rw-r--r--archival/libunarchive/data_extract_to_command.c137
-rw-r--r--archival/tar.c12
-rw-r--r--include/unarchive.h4
5 files changed, 163 insertions, 0 deletions
diff --git a/archival/Config.src b/archival/Config.src
index 3dbd3aea1..f64b3347b 100644
--- a/archival/Config.src
+++ b/archival/Config.src
@@ -280,6 +280,15 @@ config FEATURE_TAR_LONG_OPTIONS
280 help 280 help
281 Enable use of long options, increases size by about 400 Bytes 281 Enable use of long options, increases size by about 400 Bytes
282 282
283config FEATURE_TAR_TO_COMMAND
284 bool "Support for writing to an external program"
285 default y
286 depends on TAR && FEATURE_TAR_LONG_OPTIONS
287 help
288 If you enable this option you'll be able to instruct tar to send
289 the contents of each extracted file to the standard input of an
290 external program.
291
283config FEATURE_TAR_UNAME_GNAME 292config FEATURE_TAR_UNAME_GNAME
284 bool "Enable use of user and group names" 293 bool "Enable use of user and group names"
285 default y 294 default y
diff --git a/archival/libunarchive/Kbuild.src b/archival/libunarchive/Kbuild.src
index 81854558b..6ad1d7a65 100644
--- a/archival/libunarchive/Kbuild.src
+++ b/archival/libunarchive/Kbuild.src
@@ -53,6 +53,7 @@ lib-$(CONFIG_FEATURE_SEAMLESS_BZ2) += open_transformer.o decompress_bunzip2
53lib-$(CONFIG_FEATURE_SEAMLESS_LZMA) += open_transformer.o decompress_unlzma.o get_header_tar_lzma.o 53lib-$(CONFIG_FEATURE_SEAMLESS_LZMA) += open_transformer.o decompress_unlzma.o get_header_tar_lzma.o
54lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o 54lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o
55lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += decompress_bunzip2.o 55lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += decompress_bunzip2.o
56lib-$(CONFIG_FEATURE_TAR_TO_COMMAND) += data_extract_to_command.o
56 57
57ifneq ($(lib-y),) 58ifneq ($(lib-y),)
58lib-y += $(COMMON_FILES) 59lib-y += $(COMMON_FILES)
diff --git a/archival/libunarchive/data_extract_to_command.c b/archival/libunarchive/data_extract_to_command.c
new file mode 100644
index 000000000..983c5301d
--- /dev/null
+++ b/archival/libunarchive/data_extract_to_command.c
@@ -0,0 +1,137 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
4 */
5
6#include "libbb.h"
7#include "unarchive.h"
8
9enum {
10 //TAR_FILETYPE,
11 TAR_MODE,
12 TAR_FILENAME,
13 TAR_REALNAME,
14#if ENABLE_FEATURE_TAR_UNAME_GNAME
15 TAR_UNAME,
16 TAR_GNAME,
17#endif
18 TAR_SIZE,
19 TAR_UID,
20 TAR_GID,
21 TAR_MAX,
22};
23
24static const char *const tar_var[] = {
25 // "FILETYPE",
26 "MODE",
27 "FILENAME",
28 "REALNAME",
29#if ENABLE_FEATURE_TAR_UNAME_GNAME
30 "UNAME",
31 "GNAME",
32#endif
33 "SIZE",
34 "UID",
35 "GID",
36};
37
38static void xputenv(char *str)
39{
40 if (putenv(str))
41 bb_error_msg_and_die(bb_msg_memory_exhausted);
42}
43
44static void str2env(char *env[], int idx, const char *str)
45{
46 env[idx] = xasprintf("TAR_%s=%s", tar_var[idx], str);
47 xputenv(env[idx]);
48}
49
50static void dec2env(char *env[], int idx, unsigned long long val)
51{
52 env[idx] = xasprintf("TAR_%s=%llu", tar_var[idx], val);
53 xputenv(env[idx]);
54}
55
56static void oct2env(char *env[], int idx, unsigned long val)
57{
58 env[idx] = xasprintf("TAR_%s=%lo", tar_var[idx], val);
59 xputenv(env[idx]);
60}
61
62void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle)
63{
64 file_header_t *file_header = archive_handle->file_header;
65
66#if 0 /* do we need this? ENABLE_FEATURE_TAR_SELINUX */
67 char *sctx = archive_handle->tar__next_file_sctx;
68 if (!sctx)
69 sctx = archive_handle->tar__global_sctx;
70 if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
71 setfscreatecon(sctx);
72 free(archive_handle->tar__next_file_sctx);
73 archive_handle->tar__next_file_sctx = NULL;
74 }
75#endif
76
77 if ((file_header->mode & S_IFMT) == S_IFREG) {
78 pid_t pid;
79 int p[2], status;
80 char *tar_env[TAR_MAX];
81
82 memset(tar_env, 0, sizeof(tar_env));
83
84 xpipe(p);
85 pid = BB_MMU ? fork() : vfork();
86 switch (pid) {
87 case -1:
88 bb_perror_msg_and_die(BB_MMU ? "fork" : "vfork");
89 case 0:
90 /* Child */
91 /* str2env(tar_env, TAR_FILETYPE, "f"); - parent should do it once */
92 oct2env(tar_env, TAR_MODE, file_header->mode);
93 str2env(tar_env, TAR_FILENAME, file_header->name);
94 str2env(tar_env, TAR_REALNAME, file_header->name);
95#if ENABLE_FEATURE_TAR_UNAME_GNAME
96 str2env(tar_env, TAR_UNAME, file_header->tar__uname);
97 str2env(tar_env, TAR_GNAME, file_header->tar__gname);
98#endif
99 dec2env(tar_env, TAR_SIZE, file_header->size);
100 dec2env(tar_env, TAR_UID, file_header->uid);
101 dec2env(tar_env, TAR_GID, file_header->gid);
102 close(p[1]);
103 xdup2(p[0], STDIN_FILENO);
104 signal(SIGPIPE, SIG_DFL);
105 execl("/bin/sh", "/bin/sh" + 5, "-c", archive_handle->tar__to_command, NULL);
106 bb_perror_msg_and_die("can't execute '%s'", "/bin/sh");
107 }
108 close(p[0]);
109 /* Our caller is expected to do signal(SIGPIPE, SIG_IGN)
110 * so that we don't die if child don't read all the input: */
111 bb_copyfd_exact_size(archive_handle->src_fd, p[1], file_header->size);
112 close(p[1]);
113
114 if (safe_waitpid(pid, &status, 0) == -1)
115 bb_perror_msg_and_die("waitpid");
116 if (WIFEXITED(status) && WEXITSTATUS(status))
117 bb_error_msg_and_die("'%s' returned status %d",
118 archive_handle->tar__to_command, WEXITSTATUS(status));
119 if (WIFSIGNALED(status))
120 bb_error_msg_and_die("'%s' terminated on signal %d",
121 archive_handle->tar__to_command, WTERMSIG(status));
122
123 if (!BB_MMU) {
124 int i;
125 for (i = 0; i < TAR_MAX; i++) {
126 if (tar_env[i])
127 bb_unsetenv_and_free(tar_env[i]);
128 }
129 }
130 }
131
132#if 0 /* ENABLE_FEATURE_TAR_SELINUX */
133 if (sctx)
134 /* reset the context after creating an entry */
135 setfscreatecon(NULL);
136#endif
137}
diff --git a/archival/tar.c b/archival/tar.c
index 3a940128b..344c9dea4 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -750,6 +750,7 @@ enum {
750 IF_FEATURE_SEAMLESS_Z( OPTBIT_COMPRESS ,) // 16th bit 750 IF_FEATURE_SEAMLESS_Z( OPTBIT_COMPRESS ,) // 16th bit
751 IF_FEATURE_TAR_NOPRESERVE_TIME(OPTBIT_NOPRESERVE_TIME,) 751 IF_FEATURE_TAR_NOPRESERVE_TIME(OPTBIT_NOPRESERVE_TIME,)
752#if ENABLE_FEATURE_TAR_LONG_OPTIONS 752#if ENABLE_FEATURE_TAR_LONG_OPTIONS
753 IF_FEATURE_TAR_TO_COMMAND(OPTBIT_2COMMAND ,)
753 OPTBIT_NUMERIC_OWNER, 754 OPTBIT_NUMERIC_OWNER,
754 OPTBIT_NOPRESERVE_PERM, 755 OPTBIT_NOPRESERVE_PERM,
755 OPTBIT_OVERWRITE, 756 OPTBIT_OVERWRITE,
@@ -772,6 +773,7 @@ enum {
772 OPT_GZIP = IF_FEATURE_SEAMLESS_GZ( (1 << OPTBIT_GZIP )) + 0, // z 773 OPT_GZIP = IF_FEATURE_SEAMLESS_GZ( (1 << OPTBIT_GZIP )) + 0, // z
773 OPT_COMPRESS = IF_FEATURE_SEAMLESS_Z( (1 << OPTBIT_COMPRESS )) + 0, // Z 774 OPT_COMPRESS = IF_FEATURE_SEAMLESS_Z( (1 << OPTBIT_COMPRESS )) + 0, // Z
774 OPT_NOPRESERVE_TIME = IF_FEATURE_TAR_NOPRESERVE_TIME((1 << OPTBIT_NOPRESERVE_TIME)) + 0, // m 775 OPT_NOPRESERVE_TIME = IF_FEATURE_TAR_NOPRESERVE_TIME((1 << OPTBIT_NOPRESERVE_TIME)) + 0, // m
776 OPT_2COMMAND = IF_FEATURE_TAR_TO_COMMAND( (1 << OPTBIT_2COMMAND )) + 0, // to-command
775 OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner 777 OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner
776 OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions 778 OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions
777 OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite 779 OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite
@@ -813,6 +815,9 @@ static const char tar_longopts[] ALIGN1 =
813# if ENABLE_FEATURE_TAR_NOPRESERVE_TIME 815# if ENABLE_FEATURE_TAR_NOPRESERVE_TIME
814 "touch\0" No_argument "m" 816 "touch\0" No_argument "m"
815# endif 817# endif
818# if ENABLE_FEATURE_TAR_TO_COMMAND
819 "to-command\0" Required_argument "\xfb"
820# endif
816 /* use numeric uid/gid from tar header, not textual */ 821 /* use numeric uid/gid from tar header, not textual */
817 "numeric-owner\0" No_argument "\xfc" 822 "numeric-owner\0" No_argument "\xfc"
818 /* do not restore mode */ 823 /* do not restore mode */
@@ -904,6 +909,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
904 , &tar_filename // -f filename 909 , &tar_filename // -f filename
905 IF_FEATURE_TAR_FROM(, &(tar_handle->accept)) // T 910 IF_FEATURE_TAR_FROM(, &(tar_handle->accept)) // T
906 IF_FEATURE_TAR_FROM(, &(tar_handle->reject)) // X 911 IF_FEATURE_TAR_FROM(, &(tar_handle->reject)) // X
912 IF_FEATURE_TAR_TO_COMMAND(, &(tar_handle->tar__to_command)) // --to-command
907#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM 913#if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
908 , &excludes // --exclude 914 , &excludes // --exclude
909#endif 915#endif
@@ -922,6 +928,12 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
922 if (opt & OPT_2STDOUT) 928 if (opt & OPT_2STDOUT)
923 tar_handle->action_data = data_extract_to_stdout; 929 tar_handle->action_data = data_extract_to_stdout;
924 930
931 if (opt & OPT_2COMMAND) {
932 putenv((char*)"TAR_FILETYPE=f");
933 signal(SIGPIPE, SIG_IGN);
934 tar_handle->action_data = data_extract_to_command;
935 }
936
925 if (opt & OPT_KEEP_OLD) 937 if (opt & OPT_KEEP_OLD)
926 tar_handle->ah_flags &= ~ARCHIVE_UNLINK_OLD; 938 tar_handle->ah_flags &= ~ARCHIVE_UNLINK_OLD;
927 939
diff --git a/include/unarchive.h b/include/unarchive.h
index 8009de282..f3aa05d09 100644
--- a/include/unarchive.h
+++ b/include/unarchive.h
@@ -75,6 +75,9 @@ typedef struct archive_handle_t {
75 char* tar__longname; 75 char* tar__longname;
76 char* tar__linkname; 76 char* tar__linkname;
77# endif 77# endif
78#if ENABLE_FEATURE_TAR_TO_COMMAND
79 char* tar__to_command;
80#endif
78# if ENABLE_FEATURE_TAR_SELINUX 81# if ENABLE_FEATURE_TAR_SELINUX
79 char* tar__global_sctx; 82 char* tar__global_sctx;
80 char* tar__next_file_sctx; 83 char* tar__next_file_sctx;
@@ -128,6 +131,7 @@ extern void unpack_ar_archive(archive_handle_t *ar_archive) FAST_FUNC;
128extern void data_skip(archive_handle_t *archive_handle) FAST_FUNC; 131extern void data_skip(archive_handle_t *archive_handle) FAST_FUNC;
129extern void data_extract_all(archive_handle_t *archive_handle) FAST_FUNC; 132extern void data_extract_all(archive_handle_t *archive_handle) FAST_FUNC;
130extern void data_extract_to_stdout(archive_handle_t *archive_handle) FAST_FUNC; 133extern void data_extract_to_stdout(archive_handle_t *archive_handle) FAST_FUNC;
134extern void data_extract_to_command(archive_handle_t *archive_handle) FAST_FUNC;
131 135
132extern void header_skip(const file_header_t *file_header) FAST_FUNC; 136extern void header_skip(const file_header_t *file_header) FAST_FUNC;
133extern void header_list(const file_header_t *file_header) FAST_FUNC; 137extern void header_list(const file_header_t *file_header) FAST_FUNC;