get_header_cpio.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /* vi: set sw=4 ts=4: */
  2. /* Copyright 2002 Laurence Anderson
  3. *
  4. * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  5. */
  6. #include "libbb.h"
  7. #include "unarchive.h"
  8. typedef struct hardlinks_s {
  9. char *name;
  10. int inode;
  11. struct hardlinks_s *next;
  12. } hardlinks_t;
  13. char get_header_cpio(archive_handle_t *archive_handle)
  14. {
  15. static hardlinks_t *saved_hardlinks = NULL;
  16. static unsigned short pending_hardlinks = 0;
  17. static int inode;
  18. file_header_t *file_header = archive_handle->file_header;
  19. char cpio_header[110];
  20. int namesize;
  21. char dummy[16];
  22. int major, minor, nlink;
  23. if (pending_hardlinks) { /* Deal with any pending hardlinks */
  24. hardlinks_t *tmp, *oldtmp;
  25. tmp = saved_hardlinks;
  26. oldtmp = NULL;
  27. file_header->link_name = file_header->name;
  28. file_header->size = 0;
  29. while (tmp) {
  30. if (tmp->inode != inode) {
  31. tmp = tmp->next;
  32. continue;
  33. }
  34. file_header->name = tmp->name;
  35. if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
  36. archive_handle->action_data(archive_handle);
  37. archive_handle->action_header(archive_handle->file_header);
  38. }
  39. pending_hardlinks--;
  40. oldtmp = tmp;
  41. tmp = tmp->next;
  42. free(oldtmp->name);
  43. free(oldtmp);
  44. if (oldtmp == saved_hardlinks)
  45. saved_hardlinks = tmp;
  46. }
  47. file_header->name = file_header->link_name;
  48. if (pending_hardlinks > 1) {
  49. bb_error_msg("error resolving hardlink: archive made by GNU cpio 2.0-2.2?");
  50. }
  51. /* No more pending hardlinks, read next file entry */
  52. pending_hardlinks = 0;
  53. }
  54. /* There can be padding before archive header */
  55. data_align(archive_handle, 4);
  56. if (archive_xread_all_eof(archive_handle, (unsigned char*)cpio_header, 110) == 0) {
  57. return EXIT_FAILURE;
  58. }
  59. archive_handle->offset += 110;
  60. if (strncmp(&cpio_header[0], "07070", 5) != 0
  61. || (cpio_header[5] != '1' && cpio_header[5] != '2')
  62. ) {
  63. bb_error_msg_and_die("unsupported cpio format, use newc or crc");
  64. }
  65. {
  66. unsigned long tmpsize;
  67. sscanf(cpio_header, "%6c%8x%8x%8x%8x%8x%8lx%8lx%16c%8x%8x%8x%8c",
  68. dummy, &inode, (unsigned int*)&file_header->mode,
  69. (unsigned int*)&file_header->uid, (unsigned int*)&file_header->gid,
  70. &nlink, &file_header->mtime, &tmpsize,
  71. dummy, &major, &minor, &namesize, dummy);
  72. file_header->size = tmpsize;
  73. }
  74. free(file_header->name);
  75. file_header->name = xzalloc(namesize + 1);
  76. /* Read in filename */
  77. xread(archive_handle->src_fd, file_header->name, namesize);
  78. archive_handle->offset += namesize;
  79. /* Update offset amount and skip padding before file contents */
  80. data_align(archive_handle, 4);
  81. if (strcmp(file_header->name, "TRAILER!!!") == 0) {
  82. /* Always round up */
  83. printf("%d blocks\n", (int) (archive_handle->offset % 512 ?
  84. archive_handle->offset / 512 + 1 :
  85. archive_handle->offset / 512
  86. ));
  87. if (saved_hardlinks) { /* Bummer - we still have unresolved hardlinks */
  88. hardlinks_t *tmp = saved_hardlinks;
  89. hardlinks_t *oldtmp = NULL;
  90. while (tmp) {
  91. bb_error_msg("%s not created: cannot resolve hardlink", tmp->name);
  92. oldtmp = tmp;
  93. tmp = tmp->next;
  94. free(oldtmp->name);
  95. free(oldtmp);
  96. }
  97. saved_hardlinks = NULL;
  98. pending_hardlinks = 0;
  99. }
  100. return EXIT_FAILURE;
  101. }
  102. if (S_ISLNK(file_header->mode)) {
  103. file_header->link_name = xzalloc(file_header->size + 1);
  104. xread(archive_handle->src_fd, file_header->link_name, file_header->size);
  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. /* name current allocated, freed later */
  116. new->name = file_header->name;
  117. file_header->name = NULL;
  118. saved_hardlinks = new;
  119. return EXIT_SUCCESS; /* Skip this one */
  120. }
  121. /* Found the file with data in */
  122. pending_hardlinks = nlink;
  123. }
  124. file_header->device = makedev(major, minor);
  125. if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
  126. archive_handle->action_data(archive_handle);
  127. archive_handle->action_header(archive_handle->file_header);
  128. } else {
  129. data_skip(archive_handle);
  130. }
  131. archive_handle->offset += file_header->size;
  132. free(file_header->link_name);
  133. return EXIT_SUCCESS;
  134. }