123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- #include "platform.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include "archive.h"
- #include "ccache.h"
- #include "hexify.h"
- #include "multitape.h"
- #include "bsdtar.h"
- /*
- * Delete a tape.
- */
- void
- tarsnap_mode_d(struct bsdtar *bsdtar)
- {
- TAPE_D * d;
- size_t i;
- /* Prepare for deletes. */
- if ((d = deletetape_init(bsdtar->machinenum)) == NULL)
- goto err1;
- /* Delete archives. */
- for (i = 0; i < bsdtar->ntapes; i++) {
- if (bsdtar->verbose)
- fprintf(stderr, "Deleting archive \"%s\"\n",
- bsdtar->tapenames[i]);
- switch (deletetape(d, bsdtar->machinenum, bsdtar->cachedir,
- bsdtar->tapenames[i], bsdtar->option_print_stats,
- bsdtar->ntapes > 1 ? 1 : 0, bsdtar->option_csv_filename,
- &bsdtar->storage_modified)) {
- case 0:
- break;
- case 1:
- if (bsdtar->option_keep_going)
- break;
- /* FALLTHROUGH */
- default:
- goto err2;
- }
- }
- /* We've finished deleting archives. */
- deletetape_free(d);
- /* Success! */
- return;
- err2:
- deletetape_free(d);
- err1:
- /* Failure! */
- bsdtar_warnc(bsdtar, 0, "Error deleting archive");
- bsdtar->return_value = 1;
- return;
- }
- /*
- * Read the tape and write to stdout.
- */
- void
- tarsnap_mode_r(struct bsdtar *bsdtar)
- {
- TAPE_R * d;
- const void * buf;
- ssize_t lenread;
- size_t writelen;
- /* Open the tape. */
- if ((d = readtape_open(bsdtar->machinenum,
- bsdtar->tapenames[0])) == NULL)
- goto err1;
- /* Loop until we have an error or EOF. */
- do {
- lenread = readtape_read(d, &buf);
- /* Error? */
- if (lenread < 0)
- goto err2;
- /* EOF? */
- if (lenread == 0)
- break;
- /* Output data to stdout. */
- writelen = (size_t)(lenread);
- if (fwrite(buf, 1, writelen, stdout) != writelen)
- goto err2;
- } while (1);
- /* We're done! Close the tape. */
- if (readtape_close(d))
- goto err1;
- /* Success! */
- return;
- err2:
- readtape_close(d);
- err1:
- /* Failure! */
- bsdtar_warnc(bsdtar, 0, "Error reading archive");
- bsdtar->return_value = 1;
- return;
- }
- /*
- * Print statistics relating to an archive or set of archives.
- */
- void
- tarsnap_mode_print_stats(struct bsdtar *bsdtar)
- {
- TAPE_S * d;
- size_t i;
- /* Open the archive set for statistics purposes. */
- if ((d = statstape_open(bsdtar->machinenum,
- bsdtar->cachedir)) == NULL)
- goto err1;
- /* Print statistics about the archive set. */
- if (statstape_printglobal(d, bsdtar->option_csv_filename))
- goto err2;
- if (bsdtar->ntapes == 0) {
- /* User only wanted global statistics. */
- } else if ((bsdtar->tapenames[0][0] == '*') &&
- (bsdtar->tapenames[0][1] == '\0')) {
- /* User wants statistics on all archives. */
- if (statstape_printall(d, bsdtar->option_csv_filename))
- goto err2;
- } else {
- /* User wants statistics about specific archive(s). */
- for (i = 0; i < bsdtar->ntapes; i++) {
- switch (statstape_print(d, bsdtar->tapenames[i],
- bsdtar->option_csv_filename)) {
- case 0:
- break;
- case 1:
- if (bsdtar->option_keep_going)
- break;
- /* FALLTHROUGH */
- default:
- goto err2;
- }
- }
- }
- /* We're done. Close the archive set. */
- if (statstape_close(d))
- goto err1;
- /* Success! */
- return;
- err2:
- statstape_close(d);
- err1:
- /* Failure! */
- bsdtar_warnc(bsdtar, 0, "Error generating archive statistics");
- bsdtar->return_value = 1;
- return;
- }
- /*
- * Print the names of all the archives.
- */
- void
- tarsnap_mode_list_archives(struct bsdtar *bsdtar, int print_hashes)
- {
- TAPE_S * d;
- uint8_t hash[32];
- size_t i;
- /* Sanity check. */
- if ((print_hashes == 0) && (bsdtar->ntapes > 0)) {
- bsdtar_warnc(bsdtar, 0, "--list-archives: can only use -f"
- " with --hashes");
- goto err1;
- }
- /* Open the archive set for statistics purposes. */
- if ((d = statstape_open(bsdtar->machinenum, NULL)) == NULL)
- goto err1;
- /* Ask for the list of archives to be printed. */
- if (bsdtar->ntapes == 0) {
- if (statstape_printlist(d, bsdtar->verbose, bsdtar->option_null,
- print_hashes))
- goto err2;
- } else {
- /* User wants metadata about specific archive(s). */
- for (i = 0; i < bsdtar->ntapes; i++) {
- /* Convert ascii hex to a hash. */
- if (unhexify(bsdtar->tapenames[i], hash, 32)) {
- bsdtar_warnc(bsdtar, 0,
- "Invalid archive hash: %s",
- bsdtar->tapenames[i]);
- goto err1;
- }
- /* Print desired metadata about the archive. */
- if (statstape_printlist_item(d, hash,
- bsdtar->verbose, bsdtar->option_null, 1))
- goto err2;
- }
- }
- /* We're done. Close the archive set. */
- if (statstape_close(d))
- goto err1;
- /* Success! */
- return;
- err2:
- statstape_close(d);
- err1:
- /* Failure! */
- bsdtar_warnc(bsdtar, 0, "Error listing archives");
- bsdtar->return_value = 1;
- return;
- }
- /*
- * Archive set consistency check and repair.
- */
- void
- tarsnap_mode_fsck(struct bsdtar *bsdtar, int prune, int whichkey)
- {
- if (fscktape(bsdtar->machinenum, bsdtar->cachedir, prune, whichkey,
- &bsdtar->storage_modified)) {
- bsdtar_warnc(bsdtar, 0, "Error fscking archives");
- goto err0;
- }
- /*
- * Remove the chunkification cache in case whatever caused the fsck to
- * be necessary (e.g., disk corruption) also damaged that cache. The
- * chunkification cache is purely a performance optimization; since
- * we're dealing with backups here it makes sense to sacrifice some
- * performance to prevent possible data loss.
- */
- if (ccache_remove(bsdtar->cachedir)) {
- bsdtar_warnc(bsdtar, 0, "Error removing chunkification cache");
- goto err0;
- }
- /* Success! */
- return;
- err0:
- /* Failure! */
- bsdtar->return_value = 1;
- return;
- }
- /*
- * Initialize cache directory.
- */
- void
- tarsnap_mode_initialize_cachedir(struct bsdtar *bsdtar)
- {
- switch (statstape_initialize(bsdtar->machinenum, bsdtar->cachedir)) {
- case 0:
- break;
- case 1:
- bsdtar_warnc(bsdtar, 0, "Cache directory already initialized");
- /* FALLTHROUGH */
- default:
- goto err0;
- }
- /* Success! */
- return;
- err0:
- /* Failure! */
- bsdtar->return_value = 1;
- return;
- }
- /*
- * Nuke all the files belonging to an archive set.
- */
- void
- tarsnap_mode_nuke(struct bsdtar *bsdtar)
- {
- char s[100];
- /* Safeguard against being called accidentally. */
- fprintf(stderr, "Please type 'No Tomorrow' to continue\n");
- if (fgets(s, 100, stdin) == NULL) {
- bsdtar_warnc(bsdtar, 0,
- "Error reading string from standard input");
- goto err0;
- }
- if (strcmp(s, "No Tomorrow\n")) {
- bsdtar_warnc(bsdtar, 0, "You didn't type 'No Tomorrow'");
- goto err0;
- }
- if (nuketape(bsdtar->machinenum, &bsdtar->storage_modified)) {
- bsdtar_warnc(bsdtar, 0, "Error nuking archives");
- goto err0;
- }
- /* Success! */
- return;
- err0:
- /* Failure! */
- bsdtar->return_value = 1;
- return;
- }
- /*
- * Recover an interrupted archive if one exists.
- */
- void
- tarsnap_mode_recover(struct bsdtar *bsdtar, int whichkey)
- {
- if (recovertape(bsdtar->machinenum, bsdtar->cachedir, whichkey,
- &bsdtar->storage_modified))
- goto err1;
- /* Success! */
- return;
- err1:
- /* Failure! */
- bsdtar_warnc(bsdtar, 0, "Error recovering archive");
- bsdtar->return_value = 1;
- return;
- }
|