static int ct_s3_cleanup(void) { int rc = 0; rc = ct_cleanup(); if (rc == 0) { S3_deinitialize(); } return rc; }
/* Do a complete ct operation from start to finish */ int ct_do_operation(struct ct_config *conf, ct_op_cb *start, ct_op_complete_cb *complete, void *args, int flags) { struct ct_global_state *state; int ret; ct_prompt_for_login_password(conf); if ((ret = ct_init(&state, conf, flags, NULL)) != 0) return (ret); ct_add_operation(state, start, complete, args); ret = ct_event_dispatch(state->event_state); ct_cleanup(state); return (ret); }
int ct_main(int argc, char **argv) { struct ct_extract_args cea; struct ct_archive_args caa; struct ct_ctfileop_args cca; struct ct_ctfile_list_args ccla; struct ct_ctfile_delete_args ccda; struct ct_global_state *state = NULL; struct ct_config *conf; char *ct_tdir = NULL; char *ct_basisbackup = NULL; char *ctfile = NULL; char *ct_includefile = NULL; char *ct_excludefile = NULL; char *configfile = NULL, *config_file = NULL; char *basisfile = NULL; char *debugstring = NULL; char **excludelist = NULL; char **includelist = NULL; uint64_t debug_mask = 0; uint32_t cflags = CLOG_F_ENABLE | CLOG_F_STDERR; int ct_metadata = 0; int ct_match_mode = CT_MATCH_GLOB; int c; int ret = 0; int level0 = 0; int freeincludes = 0; int no_cross_mounts = 0; int strip_slash = 1; int follow_root_symlink = 0; int follow_symlinks = 0; int attr = 0; int verbose_ratios = 0; int ct_flags = 0; while ((c = getopt(argc, argv, "AB:C:D:E:F:HI:PRVXacdef:hmprtvx0")) != -1) { switch (c) { case 'A': /* noop, deprecated */ break; case 'B': basisfile = optarg; break; case 'C': ct_tdir = optarg; break; case 'D': if (debugstring != NULL) CFATALX("only one -D argument is valid"); debugstring = optarg; break; case 'E': ct_excludefile = optarg; break; case 'F': configfile = optarg; break; case 'H': follow_root_symlink = 1; break; case 'I': ct_includefile = optarg; break; case 'P': strip_slash = 0; break; case 'R': verbose_ratios = 1; break; case 'V': show_version(); exit(0); break; case 'X': no_cross_mounts = 1; break; case 'a': /* noop, deprecated */ break; case 'c': if (ct_action) CFATALX("cannot mix operations, -c -e -t -x"); ct_action = CT_A_ARCHIVE; break; case 'e': if (ct_action) CFATALX("cannot mix operations, -c -e -t -x"); ct_action = CT_A_ERASE; break; case 'f': /* metadata file */ ctfile = optarg; break; case 'h': follow_symlinks = 1; break; case 'm': /* metadata processing - XXX temporary? */ ct_metadata = 1; break; case 'r': ct_match_mode = CT_MATCH_REGEX; break; case 'p': attr = 1; break; case 't': if (ct_action) CFATALX("cannot mix operations, -c -e -t -x"); ct_action = CT_A_LIST; break; case 'v': ct_verbose++; break; case 'x': if (ct_action) CFATALX("cannot mix operations, -c -e -t -x"); ct_action = CT_A_EXTRACT; break; case '0': level0 = 1; break; default: ct_usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (debugstring) { cflags |= CLOG_F_DBGENABLE | CLOG_F_FILE | CLOG_F_FUNC | CLOG_F_LINE | CLOG_F_DTIME; exude_enable(CT_LOG_EXUDE); #if CT_ENABLE_THREADS exude_enable_threads(); #endif debug_mask |= ct_get_debugmask(debugstring); } /* please don't delete this line AGAIN! --mp */ if (clog_set_flags(cflags)) errx(1, "illegal clog flags"); clog_set_mask(debug_mask); /* We can allocate these now that we've decided if we need exude */ if (configfile) config_file = e_strdup(configfile); if (basisfile) ct_basisbackup = e_strdup(basisfile); if (ct_includefile != NULL) { int nentries; if ((ct_action == CT_A_LIST || ct_action == CT_A_EXTRACT) && argc != 0) CFATALX("-I is invalid when a pattern is " "provided on the command line"); includelist = ct_matchlist_fromfile(ct_includefile, &nentries); if (nentries == -1) CFATAL("can't get includelist from %s", ct_includefile); freeincludes = 1; } else if ((ct_action == CT_A_LIST || ct_action == CT_A_EXTRACT)) { includelist = argv; } if (ct_excludefile != NULL) { int nentries; excludelist = ct_matchlist_fromfile(ct_excludefile, &nentries); if (nentries == -1) CFATAL("can't get excludelsit from %s", ct_excludefile); } if ((ret = ct_load_config(&conf, &config_file)) != 0) { CFATALX("%s", ct_strerror(ret)); } if (!(ct_metadata && (ct_action == CT_A_LIST || ct_action == CT_A_ERASE))) { if (ctfile == NULL) { CWARNX("ctfile is required"); ct_usage(); } if (conf->ct_ctfile_mode == CT_MDMODE_REMOTE && ctfile_verify_name(ctfile)) CFATALX("invalid ctfile: %s", ctfile); } /* * !metadata extract with no args extracts everything. * and all lists show everything if not filtered */ if (((ct_metadata == 0 && ct_action == CT_A_EXTRACT) || ct_action == CT_A_LIST) && argc == 0) ct_match_mode = CT_MATCH_EVERYTHING; if (level0) conf->ct_auto_incremental = 0; /* force incremental off */ if (conf->ct_ctfile_mode == CT_MDMODE_REMOTE && ct_metadata == 0 && ct_basisbackup != NULL) CFATALX("incremental basis in remote mode"); /* Don't bother starting a connection if just listing local files. */ if (ct_action == CT_A_LIST && conf->ct_ctfile_mode == CT_MDMODE_LOCAL && ct_metadata == 0 ) { ret = ct_list(ctfile, includelist, excludelist, ct_match_mode, NULL, strip_slash, ct_verbose); goto out; } ct_prompt_for_login_password(conf); if (ct_action == CT_A_EXTRACT || ct_action == CT_A_ARCHIVE || (ct_action == CT_A_LIST && conf->ct_ctfile_mode == CT_MDMODE_REMOTE && ct_metadata == 0) || ct_action == CT_A_ERASE) ct_flags |= CT_NEED_SECRETS; if (ct_action == CT_A_ARCHIVE) ct_flags |= CT_NEED_DB; if ((ret = ct_init(&state, conf, ct_flags, ct_info_sig)) != 0) CFATALX("failed to initialise cyphertite: %s", ct_strerror(ret)); #if defined(CT_EXT_INIT) CT_EXT_INIT(state); #endif if (conf->ct_crypto_passphrase != NULL && conf->ct_secrets_upload != 0) { ct_add_operation(state, ctfile_list_start, ct_check_secrets_extract, conf->ct_crypto_secrets); } if (ct_action == CT_A_EXTRACT) ct_set_log_fns(state, &ct_verbose, ct_print_ctfile_info, ct_print_file_start, ct_print_file_end, ct_print_traverse_start, ct_print_traverse_end); else if (ct_action == CT_A_ARCHIVE) ct_set_log_fns(state, &ct_verbose, ct_print_ctfile_info, ct_pr_fmt_file, ct_pr_fmt_file_end, ct_print_traverse_start, ct_print_traverse_end); if (conf->ct_ctfile_mode == CT_MDMODE_REMOTE && ct_metadata == 0) { switch (ct_action) { case CT_A_EXTRACT: case CT_A_LIST: cea.cea_local_ctfile = NULL; /* to be found */ cea.cea_filelist = includelist; cea.cea_excllist = excludelist; cea.cea_matchmode = ct_match_mode; cea.cea_ctfile_basedir = conf->ct_ctfile_cachedir; cea.cea_tdir = ct_tdir; cea.cea_strip_slash = strip_slash; cea.cea_attr = attr; cea.cea_follow_symlinks = follow_symlinks; cea.cea_log_state = &ct_verbose; cea.cea_log_chown_failed = ct_print_extract_chown_failed; ctfile_find_for_operation(state, ctfile, ((ct_action == CT_A_EXTRACT) ? ctfile_nextop_extract : ctfile_nextop_list), &cea, 1, 0); break; case CT_A_ARCHIVE: ct_normalize_filelist(argv); caa.caa_filelist = argv; caa.caa_excllist = excludelist; caa.caa_matchmode = ct_match_mode; caa.caa_includelist = includelist; caa.caa_tdir = ct_tdir; caa.caa_tag = ctfile; caa.caa_ctfile_basedir = conf->ct_ctfile_cachedir; /* we want to encrypt as long as we have keys */ caa.caa_no_cross_mounts = no_cross_mounts; caa.caa_strip_slash = strip_slash; caa.caa_follow_root_symlink = follow_root_symlink; caa.caa_follow_symlinks = follow_symlinks; caa.caa_max_incrementals = conf->ct_max_incrementals; if (conf->ct_auto_incremental) /* * Need to work out basis filename and * download it if necessary */ ctfile_find_for_operation(state, ctfile, ctfile_nextop_archive, &caa, 0, 1); else { /* No basis, just start the op */ ctfile_nextop_archive(state, NULL, &caa); } break; default: CWARNX("invalid action"); ct_usage(); /* NOTREACHED */ break; } } else if (ct_metadata != 0) { if (ct_action == CT_A_ARCHIVE || ct_action == CT_A_EXTRACT) { cca.cca_localname = ctfile; cca.cca_remotename = NULL; cca.cca_tdir = ct_tdir; cca.cca_cleartext = 0; cca.cca_ctfile = 1; /* only matters for archive */ ct_add_operation(state, ((ct_action == CT_A_ARCHIVE) ? ctfile_archive : ctfile_extract), ctfile_op_cleanup, &cca); } else if (ct_action == CT_A_ERASE) { if (ctfile != NULL) CFATALX("-f is not permitted with -me operation"); if (argc == 0) CFATALX("no files specified"); ccda.ccda_pattern = argv; ccda.ccda_matchmode = ct_match_mode; ccda.ccda_callback = ct_print_delete; ct_add_operation(state, ctfile_list_start, ctfile_process_delete, &ccda); } else if (ct_action == CT_A_LIST) { ccla.ccla_search = includelist; ccla.ccla_exclude = excludelist; ccla.ccla_matchmode = ct_match_mode; ct_add_operation(state, ctfile_list_start, ctfile_list_print, &ccla); } else { CWARNX("must specify action"); ct_usage(); /* NOTREACHED */ } } else { /* list is handled above */ if (ct_action == CT_A_ARCHIVE) { caa.caa_local_ctfile = ctfile; ct_normalize_filelist(argv); caa.caa_filelist = argv; caa.caa_excllist = excludelist; caa.caa_matchmode = ct_match_mode; caa.caa_includelist = includelist; caa.caa_tdir = ct_tdir; caa.caa_tag = ctfile; caa.caa_ctfile_basedir = NULL; /* we want to encrypt as long as we have keys */ caa.caa_no_cross_mounts = no_cross_mounts; caa.caa_strip_slash = strip_slash; caa.caa_follow_root_symlink = follow_root_symlink; caa.caa_follow_symlinks = follow_symlinks; caa.caa_max_incrementals = 0; /* unlimited */ caa.caa_basis = ct_basisbackup; ct_add_operation(state, ct_archive, NULL, &caa); } else if (ct_action == CT_A_EXTRACT) { cea.cea_local_ctfile = ctfile; cea.cea_filelist = includelist; cea.cea_excllist = excludelist; cea.cea_matchmode = ct_match_mode; cea.cea_ctfile_basedir = NULL; cea.cea_tdir = ct_tdir; cea.cea_strip_slash = strip_slash; cea.cea_attr = attr; cea.cea_follow_symlinks = follow_symlinks; cea.cea_log_state = &ct_verbose; cea.cea_log_chown_failed = ct_print_extract_chown_failed; ct_add_operation(state, ct_extract, NULL, &cea); } else { CWARNX("must specify action"); ct_usage(); /* NOTREACHED */ } } ct_wakeup_file(state->event_state); if ((ret = ct_run_eventloop(state)) != 0) { if (state->ct_errmsg[0] != '\0') CWARNX("%s: %s", state->ct_errmsg, ct_strerror(ret)); else CWARNX("%s", ct_strerror(ret)); return (ret); } if (verbose_ratios) ct_dump_stats(state, stdout); ct_cleanup_login_cache(); ct_cleanup(state); out: if (includelist && freeincludes == 1) ct_matchlist_free(includelist); if (excludelist) ct_matchlist_free(excludelist); if (conf->ct_ctfile_mode == CT_MDMODE_REMOTE && ct_metadata == 0) ctfile_trim_cache(conf->ct_ctfile_cachedir, conf->ct_ctfile_max_cachesize); ct_unload_config(config_file, conf); #if CT_CHECK_MEMORY e_check_memory(); #endif exude_cleanup(); return (ret); }