data_extract_all.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * This program is free software; you can redistribute it and/or modify
  3. * it under the terms of the GNU General Public License as published by
  4. * the Free Software Foundation; either version 2 of the License, or
  5. * (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program; if not, write to the Free Software
  14. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  15. */
  16. #include <sys/types.h>
  17. #include <errno.h>
  18. #include <fcntl.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <utime.h>
  22. #include <unistd.h>
  23. #include <stdlib.h>
  24. #include "libbb.h"
  25. #include "unarchive.h"
  26. extern void data_extract_all(archive_handle_t *archive_handle)
  27. {
  28. file_header_t *file_header = archive_handle->file_header;
  29. int dst_fd;
  30. int res;
  31. if (archive_handle->flags & ARCHIVE_CREATE_LEADING_DIRS) {
  32. char *name = bb_xstrdup(file_header->name);
  33. bb_make_directory (dirname(name), -1, FILEUTILS_RECUR);
  34. free(name);
  35. }
  36. /* Check if the file already exists */
  37. if (archive_handle->flags & ARCHIVE_EXTRACT_UNCONDITIONAL) {
  38. /* Remove the existing entry if it exists */
  39. if (((file_header->mode & S_IFMT) != S_IFDIR) && (unlink(file_header->name) == -1) && (errno != ENOENT)) {
  40. bb_perror_msg_and_die("Couldnt remove old file");
  41. }
  42. }
  43. else if (archive_handle->flags & ARCHIVE_EXTRACT_NEWER) {
  44. /* Remove the existing entry if its older than the extracted entry */
  45. struct stat statbuf;
  46. if (lstat(file_header->name, &statbuf) == -1) {
  47. if (errno != ENOENT) {
  48. bb_perror_msg_and_die("Couldnt stat old file");
  49. }
  50. }
  51. else if (statbuf.st_mtime <= file_header->mtime) {
  52. if (!(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
  53. bb_error_msg("%s not created: newer or same age file exists", file_header->name);
  54. }
  55. data_skip(archive_handle);
  56. return;
  57. }
  58. else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {
  59. bb_perror_msg_and_die("Couldnt remove old file %s", file_header->name);
  60. }
  61. }
  62. /* Handle hard links separately
  63. * We identified hard links as regular files of size 0 with a symlink */
  64. if (S_ISREG(file_header->mode) && (file_header->link_name) && (file_header->size == 0)) {
  65. /* hard link */
  66. res = link(file_header->link_name, file_header->name);
  67. if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
  68. bb_perror_msg("Couldnt create hard link");
  69. }
  70. } else {
  71. /* Create the filesystem entry */
  72. switch(file_header->mode & S_IFMT) {
  73. case S_IFREG: {
  74. /* Regular file */
  75. dst_fd = bb_xopen(file_header->name, O_WRONLY | O_CREAT | O_EXCL);
  76. bb_copyfd_size(archive_handle->src_fd, dst_fd, file_header->size);
  77. close(dst_fd);
  78. break;
  79. }
  80. case S_IFDIR:
  81. res = mkdir(file_header->name, file_header->mode);
  82. if ((errno != EISDIR) && (res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
  83. bb_perror_msg("extract_archive: %s", file_header->name);
  84. }
  85. break;
  86. case S_IFLNK:
  87. /* Symlink */
  88. res = symlink(file_header->link_name, file_header->name);
  89. if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
  90. bb_perror_msg("Cannot create symlink from %s to '%s'", file_header->name, file_header->link_name);
  91. }
  92. break;
  93. case S_IFSOCK:
  94. case S_IFBLK:
  95. case S_IFCHR:
  96. case S_IFIFO:
  97. res = mknod(file_header->name, file_header->mode, file_header->device);
  98. if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
  99. bb_perror_msg("Cannot create node %s", file_header->name);
  100. }
  101. break;
  102. default:
  103. bb_error_msg_and_die("Unrecognised file type");
  104. }
  105. }
  106. lchown(file_header->name, file_header->uid, file_header->gid);
  107. if ((file_header->mode & S_IFMT) != S_IFLNK) {
  108. chmod(file_header->name, file_header->mode);
  109. }
  110. if (archive_handle->flags & ARCHIVE_PRESERVE_DATE) {
  111. struct utimbuf t;
  112. t.actime = t.modtime = file_header->mtime;
  113. utime(file_header->name, &t);
  114. }
  115. }