123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- #include "platform.h"
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include "chunks.h"
- #include "crypto.h"
- #include "multitape_internal.h"
- #include "storage.h"
- #include "warnp.h"
- #include "multitape.h"
- /* Cookie created by deletetape_init and passed to other functions. */
- struct multitape_delete_internal {
- STORAGE_R * S; /* Storage read cookie. */
- };
- static int callback_delete(void *, struct chunkheader *);
- /**
- * callback_delete(cookie, ch):
- * Call chunks_delete_chunk on the chunk delete cookie ${cookie} and the
- * chunk header ${ch}.
- */
- static int
- callback_delete(void * cookie, struct chunkheader * ch)
- {
- CHUNKS_D * C = cookie;
- return (chunks_delete_chunk(C, ch->hash));
- }
- /**
- * deletetape_init(machinenum):
- * Return a cookie which can be passed to deletetape.
- */
- TAPE_D *
- deletetape_init(uint64_t machinenum)
- {
- struct multitape_delete_internal * d;
- /* Allocate memory. */
- if ((d = malloc(sizeof(struct multitape_delete_internal))) == NULL)
- goto err0;
- /* Obtain a storage layer read cookie. */
- if ((d->S = storage_read_init(machinenum)) == NULL)
- goto err1;
- /* Success! */
- return (d);
- err1:
- free(d);
- err0:
- /* Failure! */
- return (NULL);
- }
- /**
- * deletetape(d, machinenum, cachedir, tapename, printstats, withname,
- * csv_filename, storage_modified):
- * Delete the specified tape, and print statistics to stderr if requested.
- * If ${withname} is non-zero, print statistics with the archive name, not
- * just as "This archive". Return 0 on success, 1 if the tape does not exist,
- * or -1 on other errors. If ${csv_filename} is specified, output in CSV
- * format instead of to stderr. If the data on the server has been modified,
- * set ${*storage_modified} to 1.
- */
- int
- deletetape(TAPE_D * d, uint64_t machinenum, const char * cachedir,
- const char * tapename, int printstats, int withname,
- const char * csv_filename, int * storage_modified)
- {
- struct tapemetadata tmd;
- CHUNKS_D * C; /* Chunk layer delete cookie. */
- STORAGE_D * S; /* Storage layer delete cookie. */
- STORAGE_R * SR = d->S; /* Storage layer read cookie. */
- int lockfd;
- uint8_t lastseq[32];
- uint8_t seqnum[32];
- int rc = -1; /* Presume error was not !found. */
- FILE * output = stderr;
- int csv = 0;
- /* Should we output to a CSV file? */
- if (csv_filename != NULL)
- csv = 1;
- /* Lock the cache directory. */
- if ((lockfd = multitape_lock(cachedir)) == -1)
- goto err0;
- /* Make sure the lower layers are in a clean state. */
- if (multitape_cleanstate(cachedir, machinenum, 1, storage_modified))
- goto err1;
- /* Get sequence number (# of last committed transaction). */
- if (multitape_sequence(cachedir, lastseq))
- goto err1;
- /* Obtain storage and chunk layer cookies. */
- if ((S = storage_delete_start(machinenum, lastseq, seqnum)) == NULL)
- goto err1;
- if ((C = chunks_delete_start(cachedir, S)) == NULL)
- goto err2;
- /* Cache up to 100 bytes of blocks per chunk in the directory. */
- storage_read_set_cache_limit(SR, 100 * chunks_delete_getdirsz(C));
- /* Read archive metadata. */
- switch (multitape_metadata_get_byname(SR, NULL, &tmd, tapename, 0)) {
- case 0:
- break;
- case 1:
- rc = 1;
- /* FALLTHROUGH */
- default:
- goto err3;
- }
- /* Delete chunks. */
- if (multitape_chunkiter_tmd(SR, NULL, &tmd, callback_delete, C, 0))
- goto err5;
- /* Delete archive index. */
- if (multitape_metaindex_delete(S, C, &tmd))
- goto err5;
- /* Delete archive metadata. */
- if (multitape_metadata_delete(S, C, &tmd))
- goto err5;
- /* Free tape metadata. */
- multitape_metadata_free(&tmd);
- /* Ask the storage layer to flush all pending deletes. */
- if (storage_delete_flush(S))
- goto err3;
- /* Print statistics if they were requested. */
- if (printstats != 0) {
- if (csv && (output = fopen(csv_filename, "w")) == NULL)
- goto err3;
- /* Actually print statistics. */
- if (chunks_delete_printstats(output, C,
- withname ? tapename : NULL, csv))
- goto err4;
- if (csv && fclose(output)) {
- warnp("fclose");
- goto err3;
- }
- }
- /* Close storage and chunk layer cookies. */
- if (chunks_delete_end(C))
- goto err2;
- if (storage_delete_end(S))
- goto err1;
- /* Commit the transaction. */
- if (multitape_commit(cachedir, machinenum, seqnum, 1, storage_modified))
- goto err1;
- /* Unlock the cache directory. */
- if (close(lockfd))
- warnp("close");
- /* Success! */
- return (0);
- err5:
- multitape_metadata_free(&tmd);
- err4:
- if ((output != stderr) && fclose(output))
- warnp("fclose");
- err3:
- chunks_delete_free(C);
- err2:
- storage_delete_free(S);
- err1:
- if (close(lockfd))
- warnp("close");
- err0:
- /* Failure! */
- return (rc);
- }
- /**
- * deletetape_free(d):
- * Free the delete cookie ${d}.
- */
- void
- deletetape_free(TAPE_D * d)
- {
- /* Behave consistently with free(NULL). */
- if (d == NULL)
- return;
- /* Close the storage layer read cookie. */
- storage_read_free(d->S);
- /* Free the multitape layer delete cookie. */
- free(d);
- }
|