chunks_read.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #include "platform.h"
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <errno.h>
  5. #include <fcntl.h>
  6. #include <limits.h>
  7. #include <stdint.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <unistd.h>
  12. #include <zlib.h>
  13. #include "crypto.h"
  14. #include "hexify.h"
  15. #include "storage.h"
  16. #include "warnp.h"
  17. #include "chunks.h"
  18. struct chunks_read_internal {
  19. size_t maxlen; /* Maximum chunk size. */
  20. uint8_t * zbuf; /* Buffer for compression. */
  21. size_t zbuflen; /* Length of zbuf. */
  22. STORAGE_R * S; /* Cookie for file read operations. */
  23. };
  24. /**
  25. * chunks_read_init(S, maxchunksize):
  26. * Prepare to read chunks of maximum size ${maxchunksize} using the storage
  27. * layer cookie ${S}.
  28. */
  29. CHUNKS_R *
  30. chunks_read_init(STORAGE_R * S, size_t maxchunksize)
  31. {
  32. CHUNKS_R * C;
  33. /* Sanity check. */
  34. if ((maxchunksize == 0) || (maxchunksize > SIZE_MAX / 2)) {
  35. warn0("Programmer error: maxchunksize invalid");
  36. goto err0;
  37. }
  38. /* Allocate memory. */
  39. if ((C = malloc(sizeof(struct chunks_read_internal))) == NULL)
  40. goto err0;
  41. /* Set length parameters. */
  42. C->maxlen = maxchunksize;
  43. C->zbuflen = C->maxlen + (C->maxlen / 1000) + 13;
  44. /* Allocate buffer for holding a compressed chunk. */
  45. if ((C->zbuf = malloc(C->zbuflen)) == NULL)
  46. goto err1;
  47. /* Record the storage cookie that we're using. */
  48. C->S = S;
  49. /* Success! */
  50. return (C);
  51. err1:
  52. free(C);
  53. err0:
  54. /* Failure! */
  55. return (NULL);
  56. }
  57. /**
  58. * chunks_read_cache(C, hash):
  59. * Using the read cookie ${C}, tell the storage layer to cache the chunk with
  60. * HMAC ${hash} after it is read.
  61. */
  62. int
  63. chunks_read_cache(CHUNKS_R * C, const uint8_t * hash)
  64. {
  65. /* Pass the message on to the storage layer. */
  66. return (storage_read_add_name_cache(C->S, 'c', hash));
  67. }
  68. /**
  69. * chunks_read_chunk(C, hash, len, zlen, buf, quiet):
  70. * Using the read cookie ${C}, read the chunk with HMAC ${hash}
  71. * into ${buf}; it should have length ${len} and compressed size ${zlen}.
  72. * If ${quiet}, don't print any warnings about corrupt or missing chunks.
  73. * Return 0 (success), 1 (ENOENT), 2 (corrupt), or -1 (error).
  74. */
  75. int
  76. chunks_read_chunk(CHUNKS_R * C, const uint8_t * hash, size_t len,
  77. size_t zlen, uint8_t * buf, int quiet)
  78. {
  79. char hashbuf[65];
  80. uint8_t hash_actual[32];
  81. char hashbuf_actual[65];
  82. int rc;
  83. uLongf buflen;
  84. /* Sanity check ${len} and ${zlen} against parameters in ${C}. */
  85. if ((len > C->maxlen) || (zlen > C->zbuflen)) {
  86. if (quiet == 0)
  87. warn0("Chunk exceeds maximum size");
  88. goto corrupt;
  89. }
  90. /* Write the hash in hex for the benefit of error messages. */
  91. hexify(hash, hashbuf, 32);
  92. /* Ask the storage layer to read the file for us. */
  93. switch (storage_read_file(C->S, C->zbuf, zlen, 'c', hash)) {
  94. case -1:
  95. warnp("Error reading chunk %s", hashbuf);
  96. goto err0;
  97. case 0:
  98. /* File read successfully. */
  99. break;
  100. case 1:
  101. if (quiet == 0)
  102. warnp("Chunk not present: %s: Run --fsck", hashbuf);
  103. goto notpresent;
  104. case 2:
  105. if (quiet == 0)
  106. warn0("Chunk %s is corrupt", hashbuf);
  107. goto corrupt;
  108. }
  109. /* Decompress the chunk into ${buf}. */
  110. buflen = len;
  111. if ((rc = uncompress(buf, &buflen, C->zbuf, zlen)) != Z_OK) {
  112. if (quiet == 0) {
  113. switch (rc) {
  114. case Z_MEM_ERROR:
  115. errno = ENOMEM;
  116. warnp("Error decompressing chunk %s",
  117. hashbuf);
  118. break;
  119. case Z_BUF_ERROR:
  120. case Z_DATA_ERROR:
  121. warn0("Error decompressing chunk %s: "
  122. "chunk is corrupt", hashbuf);
  123. break;
  124. default:
  125. warn0("Programmer error: "
  126. "Unexpected error code from "
  127. "uncompress: %d", rc);
  128. break;
  129. }
  130. }
  131. goto corrupt;
  132. }
  133. /* Make sure the decompressed chunk length is correct. */
  134. if (buflen != len) {
  135. if (quiet == 0)
  136. warn0("Chunk %s has incorrect length"
  137. " (%zd, expected %zd)",
  138. hashbuf, (size_t)buflen, len);
  139. goto corrupt;
  140. }
  141. /* Make sure the decompressed chunk has correct HMAC. */
  142. if (crypto_hash_data(CRYPTO_KEY_HMAC_CHUNK, buf, len, hash_actual))
  143. goto err0;
  144. if (memcmp(hash, hash_actual, 32)) {
  145. hexify(hash_actual, hashbuf_actual, 32);
  146. if (quiet == 0)
  147. warn0("Chunk has incorrect hash (%s, expected %s)",
  148. hashbuf_actual, hashbuf);
  149. goto corrupt;
  150. }
  151. /* Success! */
  152. return (0);
  153. notpresent:
  154. /* ENOENT. */
  155. return (1);
  156. corrupt:
  157. /* Chunk is corrupt. */
  158. return (2);
  159. err0:
  160. /* Failure! */
  161. return (-1);
  162. }
  163. /**
  164. * chunks_read_free(C):
  165. * Close the read cookie ${C} and free any allocated memory.
  166. */
  167. void
  168. chunks_read_free(CHUNKS_R * C)
  169. {
  170. /* Behave consistently with free(NULL). */
  171. if (C == NULL)
  172. return;
  173. /* Free memory. */
  174. free(C->zbuf);
  175. free(C);
  176. }