multitape_delete.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #include "platform.h"
  2. #include <stdint.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include "chunks.h"
  8. #include "crypto.h"
  9. #include "multitape_internal.h"
  10. #include "storage.h"
  11. #include "warnp.h"
  12. #include "multitape.h"
  13. /* Cookie created by deletetape_init and passed to other functions. */
  14. struct multitape_delete_internal {
  15. STORAGE_R * S; /* Storage read cookie. */
  16. };
  17. static int callback_delete(void *, struct chunkheader *);
  18. /**
  19. * callback_delete(cookie, ch):
  20. * Call chunks_delete_chunk on the chunk delete cookie ${cookie} and the
  21. * chunk header ${ch}.
  22. */
  23. static int
  24. callback_delete(void * cookie, struct chunkheader * ch)
  25. {
  26. CHUNKS_D * C = cookie;
  27. return (chunks_delete_chunk(C, ch->hash));
  28. }
  29. /**
  30. * deletetape_init(machinenum):
  31. * Return a cookie which can be passed to deletetape.
  32. */
  33. TAPE_D *
  34. deletetape_init(uint64_t machinenum)
  35. {
  36. struct multitape_delete_internal * d;
  37. /* Allocate memory. */
  38. if ((d = malloc(sizeof(struct multitape_delete_internal))) == NULL)
  39. goto err0;
  40. /* Obtain a storage layer read cookie. */
  41. if ((d->S = storage_read_init(machinenum)) == NULL)
  42. goto err1;
  43. /* Success! */
  44. return (d);
  45. err1:
  46. free(d);
  47. err0:
  48. /* Failure! */
  49. return (NULL);
  50. }
  51. /**
  52. * deletetape(d, machinenum, cachedir, tapename, printstats, withname,
  53. * csv_filename, storage_modified):
  54. * Delete the specified tape, and print statistics to stderr if requested.
  55. * If ${withname} is non-zero, print statistics with the archive name, not
  56. * just as "This archive". Return 0 on success, 1 if the tape does not exist,
  57. * or -1 on other errors. If ${csv_filename} is specified, output in CSV
  58. * format instead of to stderr. If the data on the server has been modified,
  59. * set ${*storage_modified} to 1.
  60. */
  61. int
  62. deletetape(TAPE_D * d, uint64_t machinenum, const char * cachedir,
  63. const char * tapename, int printstats, int withname,
  64. const char * csv_filename, int * storage_modified)
  65. {
  66. struct tapemetadata tmd;
  67. CHUNKS_D * C; /* Chunk layer delete cookie. */
  68. STORAGE_D * S; /* Storage layer delete cookie. */
  69. STORAGE_R * SR = d->S; /* Storage layer read cookie. */
  70. int lockfd;
  71. uint8_t lastseq[32];
  72. uint8_t seqnum[32];
  73. int rc = -1; /* Presume error was not !found. */
  74. FILE * output = stderr;
  75. int csv = 0;
  76. /* Should we output to a CSV file? */
  77. if (csv_filename != NULL)
  78. csv = 1;
  79. /* Lock the cache directory. */
  80. if ((lockfd = multitape_lock(cachedir)) == -1)
  81. goto err0;
  82. /* Make sure the lower layers are in a clean state. */
  83. if (multitape_cleanstate(cachedir, machinenum, 1, storage_modified))
  84. goto err1;
  85. /* Get sequence number (# of last committed transaction). */
  86. if (multitape_sequence(cachedir, lastseq))
  87. goto err1;
  88. /* Obtain storage and chunk layer cookies. */
  89. if ((S = storage_delete_start(machinenum, lastseq, seqnum)) == NULL)
  90. goto err1;
  91. if ((C = chunks_delete_start(cachedir, S)) == NULL)
  92. goto err2;
  93. /* Cache up to 100 bytes of blocks per chunk in the directory. */
  94. storage_read_set_cache_limit(SR, 100 * chunks_delete_getdirsz(C));
  95. /* Read archive metadata. */
  96. switch (multitape_metadata_get_byname(SR, NULL, &tmd, tapename, 0)) {
  97. case 0:
  98. break;
  99. case 1:
  100. rc = 1;
  101. /* FALLTHROUGH */
  102. default:
  103. goto err3;
  104. }
  105. /* Delete chunks. */
  106. if (multitape_chunkiter_tmd(SR, NULL, &tmd, callback_delete, C, 0))
  107. goto err5;
  108. /* Delete archive index. */
  109. if (multitape_metaindex_delete(S, C, &tmd))
  110. goto err5;
  111. /* Delete archive metadata. */
  112. if (multitape_metadata_delete(S, C, &tmd))
  113. goto err5;
  114. /* Free tape metadata. */
  115. multitape_metadata_free(&tmd);
  116. /* Ask the storage layer to flush all pending deletes. */
  117. if (storage_delete_flush(S))
  118. goto err3;
  119. /* Print statistics if they were requested. */
  120. if (printstats != 0) {
  121. if (csv && (output = fopen(csv_filename, "w")) == NULL)
  122. goto err3;
  123. /* Actually print statistics. */
  124. if (chunks_delete_printstats(output, C,
  125. withname ? tapename : NULL, csv))
  126. goto err4;
  127. if (csv && fclose(output)) {
  128. warnp("fclose");
  129. goto err3;
  130. }
  131. }
  132. /* Close storage and chunk layer cookies. */
  133. if (chunks_delete_end(C))
  134. goto err2;
  135. if (storage_delete_end(S))
  136. goto err1;
  137. /* Commit the transaction. */
  138. if (multitape_commit(cachedir, machinenum, seqnum, 1, storage_modified))
  139. goto err1;
  140. /* Unlock the cache directory. */
  141. if (close(lockfd))
  142. warnp("close");
  143. /* Success! */
  144. return (0);
  145. err5:
  146. multitape_metadata_free(&tmd);
  147. err4:
  148. if ((output != stderr) && fclose(output))
  149. warnp("fclose");
  150. err3:
  151. chunks_delete_free(C);
  152. err2:
  153. storage_delete_free(S);
  154. err1:
  155. if (close(lockfd))
  156. warnp("close");
  157. err0:
  158. /* Failure! */
  159. return (rc);
  160. }
  161. /**
  162. * deletetape_free(d):
  163. * Free the delete cookie ${d}.
  164. */
  165. void
  166. deletetape_free(TAPE_D * d)
  167. {
  168. /* Behave consistently with free(NULL). */
  169. if (d == NULL)
  170. return;
  171. /* Close the storage layer read cookie. */
  172. storage_read_free(d->S);
  173. /* Free the multitape layer delete cookie. */
  174. free(d);
  175. }