data_extract_to_command.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  4. */
  5. #include "libbb.h"
  6. #include "archive.h"
  7. enum {
  8. //TAR_FILETYPE,
  9. TAR_MODE,
  10. TAR_FILENAME,
  11. TAR_REALNAME,
  12. #if ENABLE_FEATURE_TAR_UNAME_GNAME
  13. TAR_UNAME,
  14. TAR_GNAME,
  15. #endif
  16. TAR_SIZE,
  17. TAR_UID,
  18. TAR_GID,
  19. TAR_MAX,
  20. };
  21. static const char *const tar_var[] = {
  22. // "FILETYPE",
  23. "MODE",
  24. "FILENAME",
  25. "REALNAME",
  26. #if ENABLE_FEATURE_TAR_UNAME_GNAME
  27. "UNAME",
  28. "GNAME",
  29. #endif
  30. "SIZE",
  31. "UID",
  32. "GID",
  33. };
  34. static void xputenv(char *str)
  35. {
  36. if (putenv(str))
  37. bb_error_msg_and_die(bb_msg_memory_exhausted);
  38. }
  39. static void str2env(char *env[], int idx, const char *str)
  40. {
  41. env[idx] = xasprintf("TAR_%s=%s", tar_var[idx], str);
  42. xputenv(env[idx]);
  43. }
  44. static void dec2env(char *env[], int idx, unsigned long long val)
  45. {
  46. env[idx] = xasprintf("TAR_%s=%llu", tar_var[idx], val);
  47. xputenv(env[idx]);
  48. }
  49. static void oct2env(char *env[], int idx, unsigned long val)
  50. {
  51. env[idx] = xasprintf("TAR_%s=%lo", tar_var[idx], val);
  52. xputenv(env[idx]);
  53. }
  54. void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle)
  55. {
  56. file_header_t *file_header = archive_handle->file_header;
  57. #if 0 /* do we need this? ENABLE_FEATURE_TAR_SELINUX */
  58. char *sctx = archive_handle->tar__next_file_sctx;
  59. if (!sctx)
  60. sctx = archive_handle->tar__global_sctx;
  61. if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
  62. setfscreatecon(sctx);
  63. free(archive_handle->tar__next_file_sctx);
  64. archive_handle->tar__next_file_sctx = NULL;
  65. }
  66. #endif
  67. if ((file_header->mode & S_IFMT) == S_IFREG) {
  68. pid_t pid;
  69. int p[2], status;
  70. char *tar_env[TAR_MAX];
  71. memset(tar_env, 0, sizeof(tar_env));
  72. xpipe(p);
  73. pid = BB_MMU ? xfork() : xvfork();
  74. if (pid == 0) {
  75. /* Child */
  76. /* str2env(tar_env, TAR_FILETYPE, "f"); - parent should do it once */
  77. oct2env(tar_env, TAR_MODE, file_header->mode);
  78. str2env(tar_env, TAR_FILENAME, file_header->name);
  79. str2env(tar_env, TAR_REALNAME, file_header->name);
  80. #if ENABLE_FEATURE_TAR_UNAME_GNAME
  81. str2env(tar_env, TAR_UNAME, file_header->tar__uname);
  82. str2env(tar_env, TAR_GNAME, file_header->tar__gname);
  83. #endif
  84. dec2env(tar_env, TAR_SIZE, file_header->size);
  85. dec2env(tar_env, TAR_UID, file_header->uid);
  86. dec2env(tar_env, TAR_GID, file_header->gid);
  87. close(p[1]);
  88. xdup2(p[0], STDIN_FILENO);
  89. signal(SIGPIPE, SIG_DFL);
  90. execl(archive_handle->tar__to_command_shell,
  91. archive_handle->tar__to_command_shell,
  92. "-c",
  93. archive_handle->tar__to_command,
  94. NULL);
  95. bb_perror_msg_and_die("can't execute '%s'", archive_handle->tar__to_command_shell);
  96. }
  97. close(p[0]);
  98. /* Our caller is expected to do signal(SIGPIPE, SIG_IGN)
  99. * so that we don't die if child don't read all the input: */
  100. bb_copyfd_exact_size(archive_handle->src_fd, p[1], -file_header->size);
  101. close(p[1]);
  102. if (safe_waitpid(pid, &status, 0) == -1)
  103. bb_perror_msg_and_die("waitpid");
  104. if (WIFEXITED(status) && WEXITSTATUS(status))
  105. bb_error_msg_and_die("'%s' returned status %d",
  106. archive_handle->tar__to_command, WEXITSTATUS(status));
  107. if (WIFSIGNALED(status))
  108. bb_error_msg_and_die("'%s' terminated on signal %d",
  109. archive_handle->tar__to_command, WTERMSIG(status));
  110. if (!BB_MMU) {
  111. int i;
  112. for (i = 0; i < TAR_MAX; i++) {
  113. if (tar_env[i])
  114. bb_unsetenv_and_free(tar_env[i]);
  115. }
  116. }
  117. }
  118. #if 0 /* ENABLE_FEATURE_TAR_SELINUX */
  119. if (sctx)
  120. /* reset the context after creating an entry */
  121. setfscreatecon(NULL);
  122. #endif
  123. }