1 /* vi: set sw=4 ts=4: */
3 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 #include "bb_archive.h"
14 #if ENABLE_FEATURE_TAR_UNAME_GNAME
24 static const char *const tar_var[] = {
29 #if ENABLE_FEATURE_TAR_UNAME_GNAME
38 static void xputenv(char *str)
41 bb_error_msg_and_die(bb_msg_memory_exhausted);
44 static void str2env(char *env[], int idx, const char *str)
46 env[idx] = xasprintf("TAR_%s=%s", tar_var[idx], str);
50 static void dec2env(char *env[], int idx, unsigned long long val)
52 env[idx] = xasprintf("TAR_%s=%llu", tar_var[idx], val);
56 static void oct2env(char *env[], int idx, unsigned long val)
58 env[idx] = xasprintf("TAR_%s=%lo", tar_var[idx], val);
62 void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle)
64 file_header_t *file_header = archive_handle->file_header;
66 #if 0 /* do we need this? ENABLE_FEATURE_TAR_SELINUX */
67 char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE];
69 sctx = archive_handle->tar__sctx[PAX_GLOBAL];
70 if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
72 free(archive_handle->tar__sctx[PAX_NEXT_FILE]);
73 archive_handle->tar__sctx[PAX_NEXT_FILE] = NULL;
77 if ((file_header->mode & S_IFMT) == S_IFREG) {
80 char *tar_env[TAR_MAX];
82 memset(tar_env, 0, sizeof(tar_env));
85 pid = BB_MMU ? xfork() : xvfork();
88 /* str2env(tar_env, TAR_FILETYPE, "f"); - parent should do it once */
89 oct2env(tar_env, TAR_MODE, file_header->mode);
90 str2env(tar_env, TAR_FILENAME, file_header->name);
91 str2env(tar_env, TAR_REALNAME, file_header->name);
92 #if ENABLE_FEATURE_TAR_UNAME_GNAME
93 str2env(tar_env, TAR_UNAME, file_header->tar__uname);
94 str2env(tar_env, TAR_GNAME, file_header->tar__gname);
96 dec2env(tar_env, TAR_SIZE, file_header->size);
97 dec2env(tar_env, TAR_UID, file_header->uid);
98 dec2env(tar_env, TAR_GID, file_header->gid);
100 xdup2(p[0], STDIN_FILENO);
101 signal(SIGPIPE, SIG_DFL);
102 execl(archive_handle->tar__to_command_shell,
103 archive_handle->tar__to_command_shell,
105 archive_handle->tar__to_command,
107 bb_perror_msg_and_die("can't execute '%s'", archive_handle->tar__to_command_shell);
110 /* Our caller is expected to do signal(SIGPIPE, SIG_IGN)
111 * so that we don't die if child don't read all the input: */
112 bb_copyfd_exact_size(archive_handle->src_fd, p[1], -file_header->size);
115 status = wait_for_exitstatus(pid);
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 by signal %d",
121 archive_handle->tar__to_command, WTERMSIG(status));
125 for (i = 0; i < TAR_MAX; i++) {
127 bb_unsetenv_and_free(tar_env[i]);
132 #if 0 /* ENABLE_FEATURE_TAR_SELINUX */
134 /* reset the context after creating an entry */
135 setfscreatecon(NULL);