THIS IS A TEST INSTANCE ONLY! REPOSITORIES CAN BE DELETED AT ANY TIME!

Git Source Code Mirror - This is a publish-only repository and all pull requests are ignored. Please follow Documentation/SubmittingPatches procedure for any of your improvements.
git
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

187 lines
4.1KB

  1. /*
  2. * csum-file.c
  3. *
  4. * Copyright (C) 2005 Linus Torvalds
  5. *
  6. * Simple file write infrastructure for writing SHA1-summed
  7. * files. Useful when you write a file that you want to be
  8. * able to verify hasn't been messed with afterwards.
  9. */
  10. #include "cache.h"
  11. #include "progress.h"
  12. #include "csum-file.h"
  13. static void flush(struct hashfile *f, const void *buf, unsigned int count)
  14. {
  15. if (0 <= f->check_fd && count) {
  16. unsigned char check_buffer[8192];
  17. ssize_t ret = read_in_full(f->check_fd, check_buffer, count);
  18. if (ret < 0)
  19. die_errno("%s: sha1 file read error", f->name);
  20. if (ret != count)
  21. die("%s: sha1 file truncated", f->name);
  22. if (memcmp(buf, check_buffer, count))
  23. die("sha1 file '%s' validation error", f->name);
  24. }
  25. for (;;) {
  26. int ret = xwrite(f->fd, buf, count);
  27. if (ret > 0) {
  28. f->total += ret;
  29. display_throughput(f->tp, f->total);
  30. buf = (char *) buf + ret;
  31. count -= ret;
  32. if (count)
  33. continue;
  34. return;
  35. }
  36. if (!ret)
  37. die("sha1 file '%s' write error. Out of diskspace", f->name);
  38. die_errno("sha1 file '%s' write error", f->name);
  39. }
  40. }
  41. void hashflush(struct hashfile *f)
  42. {
  43. unsigned offset = f->offset;
  44. if (offset) {
  45. the_hash_algo->update_fn(&f->ctx, f->buffer, offset);
  46. flush(f, f->buffer, offset);
  47. f->offset = 0;
  48. }
  49. }
  50. int finalize_hashfile(struct hashfile *f, unsigned char *result, unsigned int flags)
  51. {
  52. int fd;
  53. hashflush(f);
  54. the_hash_algo->final_fn(f->buffer, &f->ctx);
  55. if (result)
  56. hashcpy(result, f->buffer);
  57. if (flags & CSUM_HASH_IN_STREAM)
  58. flush(f, f->buffer, the_hash_algo->rawsz);
  59. if (flags & CSUM_FSYNC)
  60. fsync_or_die(f->fd, f->name);
  61. if (flags & CSUM_CLOSE) {
  62. if (close(f->fd))
  63. die_errno("%s: sha1 file error on close", f->name);
  64. fd = 0;
  65. } else
  66. fd = f->fd;
  67. if (0 <= f->check_fd) {
  68. char discard;
  69. int cnt = read_in_full(f->check_fd, &discard, 1);
  70. if (cnt < 0)
  71. die_errno("%s: error when reading the tail of sha1 file",
  72. f->name);
  73. if (cnt)
  74. die("%s: sha1 file has trailing garbage", f->name);
  75. if (close(f->check_fd))
  76. die_errno("%s: sha1 file error on close", f->name);
  77. }
  78. free(f);
  79. return fd;
  80. }
  81. void hashwrite(struct hashfile *f, const void *buf, unsigned int count)
  82. {
  83. while (count) {
  84. unsigned offset = f->offset;
  85. unsigned left = sizeof(f->buffer) - offset;
  86. unsigned nr = count > left ? left : count;
  87. const void *data;
  88. if (f->do_crc)
  89. f->crc32 = crc32(f->crc32, buf, nr);
  90. if (nr == sizeof(f->buffer)) {
  91. /* process full buffer directly without copy */
  92. data = buf;
  93. } else {
  94. memcpy(f->buffer + offset, buf, nr);
  95. data = f->buffer;
  96. }
  97. count -= nr;
  98. offset += nr;
  99. buf = (char *) buf + nr;
  100. left -= nr;
  101. if (!left) {
  102. the_hash_algo->update_fn(&f->ctx, data, offset);
  103. flush(f, data, offset);
  104. offset = 0;
  105. }
  106. f->offset = offset;
  107. }
  108. }
  109. struct hashfile *hashfd(int fd, const char *name)
  110. {
  111. return hashfd_throughput(fd, name, NULL);
  112. }
  113. struct hashfile *hashfd_check(const char *name)
  114. {
  115. int sink, check;
  116. struct hashfile *f;
  117. sink = open("/dev/null", O_WRONLY);
  118. if (sink < 0)
  119. die_errno("unable to open /dev/null");
  120. check = open(name, O_RDONLY);
  121. if (check < 0)
  122. die_errno("unable to open '%s'", name);
  123. f = hashfd(sink, name);
  124. f->check_fd = check;
  125. return f;
  126. }
  127. struct hashfile *hashfd_throughput(int fd, const char *name, struct progress *tp)
  128. {
  129. struct hashfile *f = xmalloc(sizeof(*f));
  130. f->fd = fd;
  131. f->check_fd = -1;
  132. f->offset = 0;
  133. f->total = 0;
  134. f->tp = tp;
  135. f->name = name;
  136. f->do_crc = 0;
  137. the_hash_algo->init_fn(&f->ctx);
  138. return f;
  139. }
  140. void hashfile_checkpoint(struct hashfile *f, struct hashfile_checkpoint *checkpoint)
  141. {
  142. hashflush(f);
  143. checkpoint->offset = f->total;
  144. checkpoint->ctx = f->ctx;
  145. }
  146. int hashfile_truncate(struct hashfile *f, struct hashfile_checkpoint *checkpoint)
  147. {
  148. off_t offset = checkpoint->offset;
  149. if (ftruncate(f->fd, offset) ||
  150. lseek(f->fd, offset, SEEK_SET) != offset)
  151. return -1;
  152. f->total = offset;
  153. f->ctx = checkpoint->ctx;
  154. f->offset = 0; /* hashflush() was called in checkpoint */
  155. return 0;
  156. }
  157. void crc32_begin(struct hashfile *f)
  158. {
  159. f->crc32 = crc32(0, NULL, 0);
  160. f->do_crc = 1;
  161. }
  162. uint32_t crc32_end(struct hashfile *f)
  163. {
  164. f->do_crc = 0;
  165. return f->crc32;
  166. }