diff options
author | Ladislav Michl <Ladislav.Michl@seznam.cz> | 2010-06-25 01:33:00 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-06-25 01:33:00 +0200 |
commit | 2b46fd49b14b2ac30e0c767c65ac2b29f6922a45 (patch) | |
tree | 184e89b5922c87c866c7ae02ca4a87a61d0ac384 /archival/libunarchive | |
parent | 51fa147c9bab41cc1f7bf5b2e3bbeddf0fdaf5ca (diff) | |
download | busybox-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>
Diffstat (limited to 'archival/libunarchive')
-rw-r--r-- | archival/libunarchive/Kbuild.src | 1 | ||||
-rw-r--r-- | archival/libunarchive/data_extract_to_command.c | 137 |
2 files changed, 138 insertions, 0 deletions
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 | |||
53 | lib-$(CONFIG_FEATURE_SEAMLESS_LZMA) += open_transformer.o decompress_unlzma.o get_header_tar_lzma.o | 53 | lib-$(CONFIG_FEATURE_SEAMLESS_LZMA) += open_transformer.o decompress_unlzma.o get_header_tar_lzma.o |
54 | lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o | 54 | lib-$(CONFIG_FEATURE_SEAMLESS_XZ) += open_transformer.o decompress_unxz.o |
55 | lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += decompress_bunzip2.o | 55 | lib-$(CONFIG_FEATURE_COMPRESS_USAGE) += decompress_bunzip2.o |
56 | lib-$(CONFIG_FEATURE_TAR_TO_COMMAND) += data_extract_to_command.o | ||
56 | 57 | ||
57 | ifneq ($(lib-y),) | 58 | ifneq ($(lib-y),) |
58 | lib-y += $(COMMON_FILES) | 59 | lib-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 | |||
9 | enum { | ||
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 | |||
24 | static 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 | |||
38 | static void xputenv(char *str) | ||
39 | { | ||
40 | if (putenv(str)) | ||
41 | bb_error_msg_and_die(bb_msg_memory_exhausted); | ||
42 | } | ||
43 | |||
44 | static 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 | |||
50 | static 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 | |||
56 | static 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 | |||
62 | void 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 | } | ||