get_header_cpio.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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 Library 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 <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <unistd.h>
  20. #include <sys/sysmacros.h> /* major() and minor() */
  21. #include "unarchive.h"
  22. #include "libbb.h"
  23. typedef struct hardlinks_s {
  24. file_header_t *entry;
  25. int inode;
  26. struct hardlinks_s *next;
  27. } hardlinks_t;
  28. extern char get_header_cpio(archive_handle_t *archive_handle)
  29. {
  30. static hardlinks_t *saved_hardlinks = NULL;
  31. static unsigned short pending_hardlinks = 0;
  32. file_header_t *file_header = archive_handle->file_header;
  33. char cpio_header[110];
  34. int namesize;
  35. char dummy[16];
  36. int major, minor, nlink, inode;
  37. if (pending_hardlinks) { /* Deal with any pending hardlinks */
  38. hardlinks_t *tmp;
  39. hardlinks_t *oldtmp;
  40. tmp = saved_hardlinks;
  41. oldtmp = NULL;
  42. while (tmp) {
  43. bb_error_msg_and_die("need to fix this\n");
  44. if (tmp->entry->link_name) { /* Found a hardlink ready to be extracted */
  45. file_header = tmp->entry;
  46. if (oldtmp) {
  47. oldtmp->next = tmp->next; /* Remove item from linked list */
  48. } else {
  49. saved_hardlinks = tmp->next;
  50. }
  51. free(tmp);
  52. continue;
  53. }
  54. oldtmp = tmp;
  55. tmp = tmp->next;
  56. }
  57. pending_hardlinks = 0; /* No more pending hardlinks, read next file entry */
  58. }
  59. /* There can be padding before archive header */
  60. data_align(archive_handle, 4);
  61. if (archive_xread_all_eof(archive_handle, cpio_header, 110) == 0) {
  62. return(EXIT_FAILURE);
  63. }
  64. archive_handle->offset += 110;
  65. if ((strncmp(&cpio_header[0], "07070", 5) != 0) || ((cpio_header[5] != '1') && (cpio_header[5] != '2'))) {
  66. bb_error_msg_and_die("Unsupported cpio format, use newc or crc");
  67. }
  68. {
  69. unsigned long tmpsize;
  70. sscanf(cpio_header, "%6c%8x%8x%8x%8x%8x%8lx%8lx%16c%8x%8x%8x%8c",
  71. dummy, &inode, (unsigned int*)&file_header->mode,
  72. (unsigned int*)&file_header->uid, (unsigned int*)&file_header->gid,
  73. &nlink, &file_header->mtime, &tmpsize,
  74. dummy, &major, &minor, &namesize, dummy);
  75. file_header->size = tmpsize;
  76. }
  77. file_header->name = (char *) xmalloc(namesize + 1);
  78. archive_xread_all(archive_handle, file_header->name, namesize); /* Read in filename */
  79. file_header->name[namesize] = '\0';
  80. archive_handle->offset += namesize;
  81. /* Update offset amount and skip padding before file contents */
  82. data_align(archive_handle, 4);
  83. if (strcmp(file_header->name, "TRAILER!!!") == 0) {
  84. printf("%d blocks\n", (int) (archive_handle->offset % 512 ? (archive_handle->offset / 512) + 1 : archive_handle->offset / 512)); /* Always round up */
  85. if (saved_hardlinks) { /* Bummer - we still have unresolved hardlinks */
  86. hardlinks_t *tmp = saved_hardlinks;
  87. hardlinks_t *oldtmp = NULL;
  88. while (tmp) {
  89. bb_error_msg("%s not created: cannot resolve hardlink", tmp->entry->name);
  90. oldtmp = tmp;
  91. tmp = tmp->next;
  92. free (oldtmp->entry->name);
  93. free (oldtmp->entry);
  94. free (oldtmp);
  95. }
  96. saved_hardlinks = NULL;
  97. pending_hardlinks = 0;
  98. }
  99. return(EXIT_FAILURE);
  100. }
  101. if (S_ISLNK(file_header->mode)) {
  102. file_header->link_name = (char *) xmalloc(file_header->size + 1);
  103. archive_xread_all(archive_handle, file_header->link_name, file_header->size);
  104. file_header->link_name[file_header->size] = '\0';
  105. archive_handle->offset += file_header->size;
  106. file_header->size = 0; /* Stop possible seeks in future */
  107. } else {
  108. file_header->link_name = NULL;
  109. }
  110. if (nlink > 1 && !S_ISDIR(file_header->mode)) {
  111. if (file_header->size == 0) { /* Put file on a linked list for later */
  112. hardlinks_t *new = xmalloc(sizeof(hardlinks_t));
  113. new->next = saved_hardlinks;
  114. new->inode = inode;
  115. new->entry = file_header;
  116. saved_hardlinks = new;
  117. return(EXIT_SUCCESS); // Skip this one
  118. } else { /* Found the file with data in */
  119. hardlinks_t *tmp = saved_hardlinks;
  120. pending_hardlinks = 1;
  121. while (tmp) {
  122. if (tmp->inode == inode) {
  123. tmp->entry->link_name = bb_xstrdup(file_header->name);
  124. nlink--;
  125. }
  126. tmp = tmp->next;
  127. }
  128. if (nlink > 1) {
  129. bb_error_msg("error resolving hardlink: did you create the archive with GNU cpio 2.0-2.2?");
  130. }
  131. }
  132. }
  133. file_header->device = makedev(major, minor);
  134. if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
  135. archive_handle->action_data(archive_handle);
  136. archive_handle->action_header(archive_handle->file_header);
  137. } else {
  138. data_skip(archive_handle);
  139. }
  140. archive_handle->offset += file_header->size;
  141. free(file_header->link_name);
  142. return (EXIT_SUCCESS);
  143. }