storage_delete.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. #include "platform.h"
  2. #include <stdint.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "crypto.h"
  6. #include "netpacket.h"
  7. #include "netproto.h"
  8. #include "storage_internal.h"
  9. #include "tsnetwork.h"
  10. #include "warnp.h"
  11. #include "storage.h"
  12. /*
  13. * Maximum number of delete operations which are allowed to be pending
  14. * before storage_delete_file will block.
  15. */
  16. #define MAXPENDING_DELETE 1024
  17. struct storage_delete_internal {
  18. /* Transaction parameters. */
  19. NETPACKET_CONNECTION * NPC;
  20. uint64_t machinenum;
  21. uint8_t nonce[32];
  22. /* Are we not allowed to delete files? */
  23. int readonly;
  24. /* Number of pending deletes. */
  25. size_t npending;
  26. };
  27. struct delete_file_internal {
  28. /* Pointer to transaction to which this belongs. */
  29. struct storage_delete_internal * S;
  30. /* General state information. */
  31. uint64_t machinenum;
  32. int done;
  33. /* Parameters used in delete_file. */
  34. uint8_t class;
  35. uint8_t name[32];
  36. uint8_t nonce[32];
  37. };
  38. static sendpacket_callback callback_delete_file_send;
  39. static handlepacket_callback callback_delete_file_response;
  40. /**
  41. * storage_delete_start(machinenum, lastseq, seqnum):
  42. * Start a delete transaction, presuming that ${lastseq} is the sequence
  43. * number of the last committed transaction, or zeroes if there is no
  44. * previous transaction; and store the sequence number of the new transaction
  45. * into ${seqnum}.
  46. */
  47. STORAGE_D *
  48. storage_delete_start(uint64_t machinenum, const uint8_t lastseq[32],
  49. uint8_t seqnum[32])
  50. {
  51. struct storage_delete_internal * S;
  52. /* Allocate memory. */
  53. if ((S = malloc(sizeof(struct storage_delete_internal))) == NULL)
  54. goto err0;
  55. /* Store machine number. */
  56. S->machinenum = machinenum;
  57. /* No pending deletes so far. */
  58. S->npending = 0;
  59. /* This is not readonly. */
  60. S->readonly = 0;
  61. /* Open netpacket connection. */
  62. if ((S->NPC = netpacket_open(USERAGENT)) == NULL)
  63. goto err1;
  64. /* Start a delete transaction. */
  65. if (storage_transaction_start_delete(S->NPC, machinenum, lastseq,
  66. S->nonce))
  67. goto err2;
  68. /* Copy the transaction nonce out. */
  69. memcpy(seqnum, S->nonce, 32);
  70. /* Success! */
  71. return (S);
  72. err2:
  73. netpacket_close(S->NPC);
  74. err1:
  75. free(S);
  76. err0:
  77. /* Failure! */
  78. return (NULL);
  79. }
  80. /**
  81. * storage_fsck_start(machinenum, seqnum, readonly, whichkey):
  82. * Start a fsck transaction, and store the sequence number of said
  83. * transaction into ${seqnum}. If ${whichkey} is zero, use the write key
  84. * (in which case the transaction must be readonly).
  85. */
  86. STORAGE_D *
  87. storage_fsck_start(uint64_t machinenum, uint8_t seqnum[32],
  88. int readonly, uint8_t whichkey)
  89. {
  90. struct storage_delete_internal * S;
  91. /* Allocate memory. */
  92. if ((S = malloc(sizeof(struct storage_delete_internal))) == NULL)
  93. goto err0;
  94. /* Store machine number. */
  95. S->machinenum = machinenum;
  96. /* No pending deletes so far. */
  97. S->npending = 0;
  98. /* This is not readonly. */
  99. S->readonly = readonly;
  100. /* Open netpacket connection. */
  101. if ((S->NPC = netpacket_open(USERAGENT)) == NULL)
  102. goto err1;
  103. /* Start a delete transaction. */
  104. if (storage_transaction_start_fsck(S->NPC, machinenum, S->nonce,
  105. whichkey))
  106. goto err2;
  107. /* Copy the transaction nonce out. */
  108. memcpy(seqnum, S->nonce, 32);
  109. /* Success! */
  110. return (S);
  111. err2:
  112. netpacket_close(S->NPC);
  113. err1:
  114. free(S);
  115. err0:
  116. /* Failure! */
  117. return (NULL);
  118. }
  119. /**
  120. * storage_delete_file(S, class, name):
  121. * Delete the file ${name} from class ${class} as part of the delete
  122. * transaction associated with the cookie ${S}.
  123. */
  124. int
  125. storage_delete_file(STORAGE_D * S, char class, const uint8_t name[32])
  126. {
  127. struct delete_file_internal * C;
  128. if (S->readonly) {
  129. warn0("Not pruning corrupted data; please run --fsck-prune");
  130. goto err0;
  131. }
  132. /* Create delete cookie. */
  133. if ((C = malloc(sizeof(struct delete_file_internal))) == NULL)
  134. goto err0;
  135. C->S = S;
  136. C->machinenum = S->machinenum;
  137. C->class = (uint8_t)class;
  138. memcpy(C->name, name, 32);
  139. memcpy(C->nonce, S->nonce, 32);
  140. C->done = 0;
  141. /* We're issuing a delete operation. */
  142. S->npending += 1;
  143. /*
  144. * Make sure the pending operation queue isn't too large before we
  145. * add yet another operation to it.
  146. */
  147. if (S->npending > MAXPENDING_DELETE) {
  148. /* Avoid silly window syndrome. */
  149. while (S->npending > MAXPENDING_DELETE / 2 + 1) {
  150. if (network_select(1))
  151. goto err1;
  152. }
  153. }
  154. /* Ask the netpacket layer to send a request and get a response. */
  155. if (netpacket_op(S->NPC, callback_delete_file_send, C))
  156. goto err0;
  157. /* Success! */
  158. return (0);
  159. err1:
  160. free(C);
  161. err0:
  162. /* Failure! */
  163. return (-1);
  164. }
  165. static int
  166. callback_delete_file_send(void * cookie, NETPACKET_CONNECTION * NPC)
  167. {
  168. struct delete_file_internal * C = cookie;
  169. /* Ask the server to delete the file in question. */
  170. return (netpacket_delete_file(NPC, C->machinenum, C->class,
  171. C->name, C->nonce, callback_delete_file_response));
  172. }
  173. static int
  174. callback_delete_file_response(void * cookie,
  175. NETPACKET_CONNECTION * NPC, int status, uint8_t packettype,
  176. const uint8_t * packetbuf, size_t packetlen)
  177. {
  178. struct delete_file_internal * C = cookie;
  179. (void)packetlen; /* UNUSED */
  180. (void)NPC; /* UNUSED */
  181. /* Handle errors. */
  182. if (status != NETWORK_STATUS_OK) {
  183. netproto_printerr(status);
  184. goto err1;
  185. }
  186. /* Make sure we received the right type of packet. */
  187. if (packettype != NETPACKET_DELETE_FILE_RESPONSE)
  188. goto err2;
  189. /* Verify packet hmac. */
  190. switch (netpacket_hmac_verify(packettype, C->nonce,
  191. packetbuf, 34, CRYPTO_KEY_AUTH_DELETE)) {
  192. case 1:
  193. goto err2;
  194. case -1:
  195. goto err1;
  196. }
  197. /* Make sure that the packet corresponds to the right file. */
  198. if ((packetbuf[1] != C->class) ||
  199. (memcmp(&packetbuf[2], C->name, 32)))
  200. goto err2;
  201. /* Parse status returned by server. */
  202. switch (packetbuf[0]) {
  203. case 0:
  204. /* This delete operation is no longer pending. */
  205. C->S->npending -= 1;
  206. break;
  207. case 1:
  208. warn0("Cannot delete file: File does not exist");
  209. goto err1;
  210. case 2:
  211. /* Bad nonce. */
  212. warn0("Delete transaction interrupted");
  213. goto err1;
  214. default:
  215. goto err2;
  216. }
  217. /* Free delete cookie. */
  218. free(C);
  219. /* Success! */
  220. return (0);
  221. err2:
  222. netproto_printerr(NETPROTO_STATUS_PROTERR);
  223. err1:
  224. free(C);
  225. /* Failure! */
  226. return (-1);
  227. }
  228. /**
  229. * storage_delete_flush(S):
  230. * Make sure all operations performed as part of the transaction associated
  231. * with the cookie ${S} have been safely stored in preparation for being
  232. * committed.
  233. */
  234. int
  235. storage_delete_flush(STORAGE_D * S)
  236. {
  237. /* Wait until all pending deletes have been completed. */
  238. while (S->npending > 0) {
  239. if (network_select(1))
  240. goto err0;
  241. }
  242. /* Success! */
  243. return (0);
  244. err0:
  245. /* Failure! */
  246. return (-1);
  247. }
  248. /**
  249. * storage_delete_end(S):
  250. * Make sure that all operations performed as part of the transaction
  251. * associated with the cookie ${S} have been safely stored in
  252. * preparation for being committed; and close the transaction and free
  253. * associated memory.
  254. */
  255. int
  256. storage_delete_end(STORAGE_D * S)
  257. {
  258. /* Flush any pending deletes. */
  259. if (storage_delete_flush(S))
  260. goto err2;
  261. /* Close netpacket connection. */
  262. if (netpacket_close(S->NPC))
  263. goto err1;
  264. /* Free structure. */
  265. free(S);
  266. /* Success! */
  267. return (0);
  268. err2:
  269. netpacket_close(S->NPC);
  270. err1:
  271. free(S);
  272. /* Failure! */
  273. return (-1);
  274. }
  275. /**
  276. * storage_delete_free(S):
  277. * Free any memory allocated as part of the delete transaction associated
  278. * with the cookie ${S}; the transaction will not be committed.
  279. */
  280. void
  281. storage_delete_free(STORAGE_D * S)
  282. {
  283. /* Behave consistently with free(NULL). */
  284. if (S == NULL)
  285. return;
  286. /* Close netpacket connection. */
  287. netpacket_close(S->NPC);
  288. /* Free structure. */
  289. free(S);
  290. }