Ladislav Michl | 2b46fd4 | 2010-06-25 01:33:00 +0200 | [diff] [blame] | 1 | /* vi: set sw=4 ts=4: */ |
| 2 | /* |
Denys Vlasenko | 0ef64bd | 2010-08-16 20:14:46 +0200 | [diff] [blame] | 3 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
Ladislav Michl | 2b46fd4 | 2010-06-25 01:33:00 +0200 | [diff] [blame] | 4 | */ |
Ladislav Michl | 2b46fd4 | 2010-06-25 01:33:00 +0200 | [diff] [blame] | 5 | #include "libbb.h" |
Denys Vlasenko | d184a72 | 2011-09-22 12:45:14 +0200 | [diff] [blame] | 6 | #include "bb_archive.h" |
Ladislav Michl | 2b46fd4 | 2010-06-25 01:33:00 +0200 | [diff] [blame] | 7 | |
| 8 | enum { |
| 9 | //TAR_FILETYPE, |
| 10 | TAR_MODE, |
| 11 | TAR_FILENAME, |
| 12 | TAR_REALNAME, |
| 13 | #if ENABLE_FEATURE_TAR_UNAME_GNAME |
| 14 | TAR_UNAME, |
| 15 | TAR_GNAME, |
| 16 | #endif |
| 17 | TAR_SIZE, |
| 18 | TAR_UID, |
| 19 | TAR_GID, |
| 20 | TAR_MAX, |
| 21 | }; |
| 22 | |
| 23 | static const char *const tar_var[] = { |
| 24 | // "FILETYPE", |
| 25 | "MODE", |
| 26 | "FILENAME", |
| 27 | "REALNAME", |
| 28 | #if ENABLE_FEATURE_TAR_UNAME_GNAME |
| 29 | "UNAME", |
| 30 | "GNAME", |
| 31 | #endif |
| 32 | "SIZE", |
| 33 | "UID", |
| 34 | "GID", |
| 35 | }; |
| 36 | |
| 37 | static void xputenv(char *str) |
| 38 | { |
| 39 | if (putenv(str)) |
| 40 | bb_error_msg_and_die(bb_msg_memory_exhausted); |
| 41 | } |
| 42 | |
| 43 | static void str2env(char *env[], int idx, const char *str) |
| 44 | { |
| 45 | env[idx] = xasprintf("TAR_%s=%s", tar_var[idx], str); |
| 46 | xputenv(env[idx]); |
| 47 | } |
| 48 | |
| 49 | static void dec2env(char *env[], int idx, unsigned long long val) |
| 50 | { |
| 51 | env[idx] = xasprintf("TAR_%s=%llu", tar_var[idx], val); |
| 52 | xputenv(env[idx]); |
| 53 | } |
| 54 | |
| 55 | static void oct2env(char *env[], int idx, unsigned long val) |
| 56 | { |
| 57 | env[idx] = xasprintf("TAR_%s=%lo", tar_var[idx], val); |
| 58 | xputenv(env[idx]); |
| 59 | } |
| 60 | |
| 61 | void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle) |
| 62 | { |
| 63 | file_header_t *file_header = archive_handle->file_header; |
| 64 | |
| 65 | #if 0 /* do we need this? ENABLE_FEATURE_TAR_SELINUX */ |
Denys Vlasenko | 6111f96 | 2012-02-23 13:45:18 +0100 | [diff] [blame] | 66 | char *sctx = archive_handle->tar__sctx[PAX_NEXT_FILE]; |
Ladislav Michl | 2b46fd4 | 2010-06-25 01:33:00 +0200 | [diff] [blame] | 67 | if (!sctx) |
Denys Vlasenko | 6111f96 | 2012-02-23 13:45:18 +0100 | [diff] [blame] | 68 | sctx = archive_handle->tar__sctx[PAX_GLOBAL]; |
Ladislav Michl | 2b46fd4 | 2010-06-25 01:33:00 +0200 | [diff] [blame] | 69 | if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */ |
| 70 | setfscreatecon(sctx); |
Denys Vlasenko | 6111f96 | 2012-02-23 13:45:18 +0100 | [diff] [blame] | 71 | free(archive_handle->tar__sctx[PAX_NEXT_FILE]); |
| 72 | archive_handle->tar__sctx[PAX_NEXT_FILE] = NULL; |
Ladislav Michl | 2b46fd4 | 2010-06-25 01:33:00 +0200 | [diff] [blame] | 73 | } |
| 74 | #endif |
| 75 | |
| 76 | if ((file_header->mode & S_IFMT) == S_IFREG) { |
| 77 | pid_t pid; |
| 78 | int p[2], status; |
| 79 | char *tar_env[TAR_MAX]; |
| 80 | |
| 81 | memset(tar_env, 0, sizeof(tar_env)); |
| 82 | |
| 83 | xpipe(p); |
Pascal Bellard | 926031b | 2010-07-04 15:32:38 +0200 | [diff] [blame] | 84 | pid = BB_MMU ? xfork() : xvfork(); |
| 85 | if (pid == 0) { |
Ladislav Michl | 2b46fd4 | 2010-06-25 01:33:00 +0200 | [diff] [blame] | 86 | /* Child */ |
| 87 | /* str2env(tar_env, TAR_FILETYPE, "f"); - parent should do it once */ |
| 88 | oct2env(tar_env, TAR_MODE, file_header->mode); |
| 89 | str2env(tar_env, TAR_FILENAME, file_header->name); |
| 90 | str2env(tar_env, TAR_REALNAME, file_header->name); |
| 91 | #if ENABLE_FEATURE_TAR_UNAME_GNAME |
| 92 | str2env(tar_env, TAR_UNAME, file_header->tar__uname); |
| 93 | str2env(tar_env, TAR_GNAME, file_header->tar__gname); |
| 94 | #endif |
| 95 | dec2env(tar_env, TAR_SIZE, file_header->size); |
| 96 | dec2env(tar_env, TAR_UID, file_header->uid); |
| 97 | dec2env(tar_env, TAR_GID, file_header->gid); |
| 98 | close(p[1]); |
| 99 | xdup2(p[0], STDIN_FILENO); |
| 100 | signal(SIGPIPE, SIG_DFL); |
Denys Vlasenko | 681efe2 | 2011-03-08 21:00:36 +0100 | [diff] [blame] | 101 | execl(archive_handle->tar__to_command_shell, |
| 102 | archive_handle->tar__to_command_shell, |
| 103 | "-c", |
| 104 | archive_handle->tar__to_command, |
Rich Felker | 16614e9 | 2013-06-30 13:45:17 +0200 | [diff] [blame] | 105 | (char *)0); |
Denys Vlasenko | 681efe2 | 2011-03-08 21:00:36 +0100 | [diff] [blame] | 106 | bb_perror_msg_and_die("can't execute '%s'", archive_handle->tar__to_command_shell); |
Ladislav Michl | 2b46fd4 | 2010-06-25 01:33:00 +0200 | [diff] [blame] | 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: */ |
Denys Vlasenko | d0a8a0d | 2010-06-26 18:11:44 +0200 | [diff] [blame] | 111 | bb_copyfd_exact_size(archive_handle->src_fd, p[1], -file_header->size); |
Ladislav Michl | 2b46fd4 | 2010-06-25 01:33:00 +0200 | [diff] [blame] | 112 | close(p[1]); |
| 113 | |
Denys Vlasenko | c4199f2 | 2016-04-01 22:12:44 +0200 | [diff] [blame] | 114 | status = wait_for_exitstatus(pid); |
Ladislav Michl | 2b46fd4 | 2010-06-25 01:33:00 +0200 | [diff] [blame] | 115 | if (WIFEXITED(status) && WEXITSTATUS(status)) |
| 116 | bb_error_msg_and_die("'%s' returned status %d", |
| 117 | archive_handle->tar__to_command, WEXITSTATUS(status)); |
| 118 | if (WIFSIGNALED(status)) |
Denys Vlasenko | 7f3a2a2 | 2015-10-08 11:24:44 +0200 | [diff] [blame] | 119 | bb_error_msg_and_die("'%s' terminated by signal %d", |
Ladislav Michl | 2b46fd4 | 2010-06-25 01:33:00 +0200 | [diff] [blame] | 120 | archive_handle->tar__to_command, WTERMSIG(status)); |
| 121 | |
| 122 | if (!BB_MMU) { |
| 123 | int i; |
| 124 | for (i = 0; i < TAR_MAX; i++) { |
| 125 | if (tar_env[i]) |
| 126 | bb_unsetenv_and_free(tar_env[i]); |
| 127 | } |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | #if 0 /* ENABLE_FEATURE_TAR_SELINUX */ |
| 132 | if (sctx) |
| 133 | /* reset the context after creating an entry */ |
| 134 | setfscreatecon(NULL); |
| 135 | #endif |
| 136 | } |