multitape_chunkiter.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #include "platform.h"
  2. #include <stdint.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "chunks.h"
  6. #include "crypto.h"
  7. #include "ctassert.h"
  8. #include "storage.h"
  9. #include "sysendian.h"
  10. #include "warnp.h"
  11. #include "multitape_internal.h"
  12. /*
  13. * The buffer management logic requires that a struct chunkdata and a
  14. * maximum-size chunk fit into a buffer.
  15. */
  16. CTASSERT(MAXCHUNK < SIZE_MAX - sizeof(struct chunkheader));
  17. /**
  18. * multitape_chunkiter_tmd(S, C, tmd, func, cookie, quiet):
  19. * Call ${func} on ${cookie} and each struct chunkheader involved in the
  20. * archive associated with the metadata ${tmd}. If ${C} is non-NULL, call
  21. * chunks_stats_extrastats on ${C} and the length of each metadata fragment.
  22. * If ${quiet}, don't print any warnings about corrupt or missing files.
  23. * Return 0 (success), 1 (a required file is missing), 2 (a required file is
  24. * corrupt), -1 (error), or the first non-zero value returned by ${func}.
  25. */
  26. int
  27. multitape_chunkiter_tmd(STORAGE_R * S, CHUNKS_S * C,
  28. const struct tapemetadata * tmd,
  29. int func(void *, struct chunkheader *), void * cookie, int quiet)
  30. {
  31. CHUNKS_R * CR; /* Chunk layer read cookie. */
  32. struct tapemetaindex tmi; /* Metaindex. */
  33. size_t hindexpos; /* Header stream index position. */
  34. size_t cindexpos; /* Chunk index stream index position. */
  35. size_t tindexpos; /* Trailer stream index position. */
  36. uint8_t * ibuf; /* Contains a tape index chunk. */
  37. size_t ibufpos; /* Position within ibuf. */
  38. size_t ibuflen; /* Length of valid data in ibuf. */
  39. struct chunkheader * ch; /* Chunk header being processed. */
  40. size_t chunklen, chunkzlen; /* Decoded chunk parameters. */
  41. int rc;
  42. /* Obtain a chunk layer read cookie. */
  43. if ((CR = chunks_read_init(S, MAXCHUNK)) == NULL) {
  44. rc = -1;
  45. goto err0;
  46. }
  47. /* Read the tape metaindex. */
  48. if ((rc = multitape_metaindex_get(S, C, &tmi, tmd, quiet)) != 0)
  49. goto err1;
  50. /* Allocate a buffer for holding chunks of index. */
  51. if ((ibuf = malloc(MAXCHUNK + sizeof(struct chunkheader))) == NULL) {
  52. rc = -1;
  53. goto err2;
  54. }
  55. ibuflen = 0;
  56. /* Iterate through the header stream index. */
  57. for (hindexpos = 0;
  58. hindexpos + sizeof(struct chunkheader) <= tmi.hindexlen;
  59. hindexpos += sizeof(struct chunkheader)) {
  60. ch = (struct chunkheader *)(&tmi.hindex[hindexpos]);
  61. if ((rc = func(cookie, ch)) != 0)
  62. goto err3;
  63. }
  64. /* Iterate through the chunk index stream index. */
  65. for (cindexpos = 0;
  66. cindexpos + sizeof(struct chunkheader) <= tmi.cindexlen;
  67. cindexpos += sizeof(struct chunkheader)) {
  68. /* Call func on the next chunk from the stream. */
  69. ch = (struct chunkheader *)(&tmi.cindex[cindexpos]);
  70. if ((rc = func(cookie, ch)) != 0)
  71. goto err3;
  72. /* Decode chunk header. */
  73. chunklen = le32dec(ch->len);
  74. chunkzlen = le32dec(ch->zlen);
  75. /* Sanity check. */
  76. if (chunklen > MAXCHUNK) {
  77. if (quiet == 0)
  78. warn0("Chunk exceeds maximum size");
  79. rc = 2;
  80. goto err3;
  81. }
  82. /* We want to cache this chunk after reading it. */
  83. if (chunks_read_cache(CR, ch->hash))
  84. goto err3;
  85. /* Read the chunk into buffer. */
  86. if ((rc = chunks_read_chunk(CR, ch->hash, chunklen, chunkzlen,
  87. ibuf + ibuflen, quiet)) != 0)
  88. goto err3;
  89. ibuflen += chunklen;
  90. /* Handle any chunk headers within ibuf. */
  91. for (ibufpos = 0;
  92. ibufpos + sizeof(struct chunkheader) <= ibuflen;
  93. ibufpos += sizeof(struct chunkheader)) {
  94. /* Deal with a chunk header. */
  95. ch = (struct chunkheader *)(&ibuf[ibufpos]);
  96. if ((rc = func(cookie, ch)) != 0)
  97. goto err3;
  98. }
  99. /* Move buffered data to the start of the buffer. */
  100. memmove(ibuf, ibuf + ibufpos, ibuflen - ibufpos);
  101. ibuflen -= ibufpos;
  102. }
  103. /* Iterate through the trailer stream index. */
  104. for (tindexpos = 0;
  105. tindexpos + sizeof(struct chunkheader) <= tmi.tindexlen;
  106. tindexpos += sizeof(struct chunkheader)) {
  107. ch = (struct chunkheader *)(&tmi.tindex[tindexpos]);
  108. if ((rc = func(cookie, ch)) != 0)
  109. goto err3;
  110. }
  111. /* Free index chunk buffer. */
  112. free(ibuf);
  113. /* Free metaindex buffers. */
  114. multitape_metaindex_free(&tmi);
  115. /* Close handles. */
  116. chunks_read_free(CR);
  117. /* Success! */
  118. return (0);
  119. err3:
  120. free(ibuf);
  121. err2:
  122. multitape_metaindex_free(&tmi);
  123. err1:
  124. chunks_read_free(CR);
  125. err0:
  126. /* Failure! */
  127. return (rc);
  128. }