3
0

data_extract_all.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  4. */
  5. #include "libbb.h"
  6. #include "unarchive.h"
  7. void data_extract_all(archive_handle_t *archive_handle)
  8. {
  9. file_header_t *file_header = archive_handle->file_header;
  10. int dst_fd;
  11. int res;
  12. if (archive_handle->flags & ARCHIVE_CREATE_LEADING_DIRS) {
  13. char *name = xstrdup(file_header->name);
  14. bb_make_directory(dirname(name), -1, FILEUTILS_RECUR);
  15. free(name);
  16. }
  17. /* Check if the file already exists */
  18. if (archive_handle->flags & ARCHIVE_EXTRACT_UNCONDITIONAL) {
  19. /* Remove the existing entry if it exists */
  20. if (((file_header->mode & S_IFMT) != S_IFDIR)
  21. && (unlink(file_header->name) == -1)
  22. && (errno != ENOENT)
  23. ) {
  24. bb_perror_msg_and_die("cannot remove old file");
  25. }
  26. }
  27. else if (archive_handle->flags & ARCHIVE_EXTRACT_NEWER) {
  28. /* Remove the existing entry if its older than the extracted entry */
  29. struct stat statbuf;
  30. if (lstat(file_header->name, &statbuf) == -1) {
  31. if (errno != ENOENT) {
  32. bb_perror_msg_and_die("cannot stat old file");
  33. }
  34. }
  35. else if (statbuf.st_mtime <= file_header->mtime) {
  36. if (!(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
  37. bb_error_msg("%s not created: newer or "
  38. "same age file exists", file_header->name);
  39. }
  40. data_skip(archive_handle);
  41. return;
  42. }
  43. else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {
  44. bb_perror_msg_and_die("cannot remove old file %s",
  45. file_header->name);
  46. }
  47. }
  48. /* Handle hard links separately
  49. * We identified hard links as regular files of size 0 with a symlink */
  50. if (S_ISREG(file_header->mode) && (file_header->link_name)
  51. && (file_header->size == 0)
  52. ) {
  53. /* hard link */
  54. res = link(file_header->link_name, file_header->name);
  55. if ((res == -1) && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)) {
  56. bb_perror_msg("cannot create hard link");
  57. }
  58. } else {
  59. /* Create the filesystem entry */
  60. switch (file_header->mode & S_IFMT) {
  61. case S_IFREG: {
  62. /* Regular file */
  63. dst_fd = xopen3(file_header->name, O_WRONLY | O_CREAT | O_EXCL,
  64. file_header->mode);
  65. bb_copyfd_size(archive_handle->src_fd, dst_fd, file_header->size);
  66. close(dst_fd);
  67. break;
  68. }
  69. case S_IFDIR:
  70. res = mkdir(file_header->name, file_header->mode);
  71. if ((errno != EISDIR) && (res == -1)
  72. && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)
  73. ) {
  74. bb_perror_msg("extract_archive: %s", file_header->name);
  75. }
  76. break;
  77. case S_IFLNK:
  78. /* Symlink */
  79. res = symlink(file_header->link_name, file_header->name);
  80. if ((res == -1)
  81. && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)
  82. ) {
  83. bb_perror_msg("cannot create symlink "
  84. "from %s to '%s'",
  85. file_header->name,
  86. file_header->link_name);
  87. }
  88. break;
  89. case S_IFSOCK:
  90. case S_IFBLK:
  91. case S_IFCHR:
  92. case S_IFIFO:
  93. res = mknod(file_header->name, file_header->mode, file_header->device);
  94. if ((res == -1)
  95. && !(archive_handle->flags & ARCHIVE_EXTRACT_QUIET)
  96. ) {
  97. bb_perror_msg("cannot create node %s", file_header->name);
  98. }
  99. break;
  100. default:
  101. bb_error_msg_and_die("unrecognized file type");
  102. }
  103. }
  104. if (!(archive_handle->flags & ARCHIVE_NOPRESERVE_OWN)) {
  105. lchown(file_header->name, file_header->uid, file_header->gid);
  106. }
  107. if (archive_handle->flags & ARCHIVE_PRESERVE_DATE) {
  108. struct utimbuf t;
  109. t.actime = t.modtime = file_header->mtime;
  110. utime(file_header->name, &t);
  111. }
  112. }