int do_check_replycache(const char *timespec) { u64_t log_count; timestring_t timestring; if (find_time(timespec, ×tring) != 0) { qerrorf("\nFailed to find a timestring: [%s] is not <hours>h<minutes>m.\n", timespec); serious_errors = 1; return -1; } if (no_to_all) { qprintf("\nCounting RC entries older than [%s]...\n", timestring); if (db_count_replycache(timestring, &log_count) < 0) { qerrorf("Failed. An error occured. Check the log.\n"); serious_errors = 1; return -1; } qprintf("Ok. [%llu] RC entries are older than [%s].\n", log_count, timestring); } if (yes_to_all) { qprintf("\nRemoving RC entries older than [%s]...\n", timestring); if (! db_cleanup_replycache(timestring)) { qerrorf("Failed. Please check the log.\n"); serious_errors = 1; return -1; } qprintf("Ok. RC entries were older than [%s] cleaned.\n", timestring); } return 0; }
int do_set_deleted(void) { u64_t messages_set_to_delete; if (no_to_all) { // TODO: Count messages to delete. qprintf("\nCounting deleted messages that need the DELETE status set...\n"); if (! db_count_deleted(&messages_set_to_delete)) { qerrorf ("Failed. An error occured. Please check log.\n"); serious_errors = 1; return -1; } qprintf("Ok. [%llu] messages need to be set for deletion.\n", messages_set_to_delete); } if (yes_to_all) { qprintf("\nSetting DELETE status for deleted messages...\n"); if (! db_set_deleted()) { qerrorf ("Failed. An error occured. Please check log.\n"); serious_errors = 1; return -1; } qprintf("Ok. Messages set for deletion.\n"); qprintf("Re-calculating used quota for all users...\n"); if (dm_quota_rebuild() < 0) { qerrorf ("Failed. An error occured. Please check log.\n"); serious_errors = 1; return -1; } qprintf("Ok. Used quota updated for all users.\n"); } return 0; }
int do_check_iplog(const char *timespec) { uint64_t log_count; TimeString_T timestring; if (find_time(timespec, ×tring) != 0) { qerrorf("\nFailed to find a timestring: [%s] is not <hours>h<minutes>m.\n", timespec); serious_errors = 1; return -1; } if (no_to_all) { qprintf("\nCounting IP entries older than [%s]...\n", timestring); if (db_count_iplog(timestring, &log_count) < 0) { qerrorf("Failed. An error occured. Check the log.\n"); serious_errors = 1; return -1; } qprintf("Ok. [%" PRIu64 "] IP entries are older than [%s].\n", log_count, timestring); } if (yes_to_all) { qprintf("\nRemoving IP entries older than [%s]...\n", timestring); if (! db_cleanup_iplog(timestring)) { qerrorf("Failed. Please check the log.\n"); serious_errors = 1; return -1; } qprintf("Ok. IP entries older than [%s] removed.\n", timestring); } return 0; }
int do_dangling_aliases(void) { int count = 0; int result = 0; GList *aliases = NULL; if (no_to_all) qprintf("\nCounting aliases with nonexistent delivery userid's...\n"); if (yes_to_all) qprintf("\nRemoving aliases with nonexistent delivery userid's...\n"); aliases = auth_get_known_aliases(); aliases = g_list_dedup(aliases, (GCompareFunc)strcmp, TRUE); aliases = g_list_first(aliases); while (aliases) { char deliver_to[21]; GList *dangling = find_dangling_aliases(aliases->data); dangling = g_list_first(dangling); while (dangling) { count++; g_snprintf(deliver_to, 21, "%llu", *(u64_t *)dangling->data); qverbosef("Dangling alias [%s] delivers to nonexistent user [%s]\n", (char *)aliases->data, deliver_to); if (yes_to_all) { if (auth_removealias_ext(aliases->data, deliver_to) < 0) { qerrorf("Error: could not remove alias [%s] deliver to [%s] \n", (char *)aliases->data, deliver_to); serious_errors = 1; result = -1; } } if (!g_list_next(dangling)) break; dangling = g_list_next(dangling); } g_list_destroy(g_list_first(dangling)); if (! g_list_next(aliases)) break; aliases = g_list_next(aliases); } g_list_destroy(g_list_first(aliases)); if (count > 0) { qerrorf("Ok. Found [%d] dangling aliases.\n", count); has_errors = 1; } else { qprintf("Ok. Found [%d] dangling aliases.\n", count); } return result; }
int do_header_cache(void) { time_t start, stop; GList *lost = NULL; if (do_rfc_size()) { serious_errors = 1; return -1; } if (do_envelope()) { serious_errors = 1; return -1; } if (no_to_all) qprintf("\nChecking DBMAIL for cached header values...\n"); if (yes_to_all) qprintf("\nRepairing DBMAIL for cached header values...\n"); time(&start); if (db_icheck_headercache(&lost) < 0) { qerrorf("Failed. An error occured. Please check log.\n"); serious_errors = 1; return -1; } if (g_list_length(lost) > 0) { qerrorf("Ok. Found [%d] un-cached physmessages.\n", g_list_length(lost)); has_errors = 1; } else { qprintf("Ok. Found [%d] un-cached physmessages.\n", g_list_length(lost)); } if (yes_to_all) { if (db_set_headercache(lost) < 0) { qerrorf("Error caching the header values "); serious_errors = 1; } } g_list_free(lost); time(&stop); qverbosef("--- checking cached headervalues took %g seconds\n", difftime(stop, start)); return 0; }
GList *find_dangling_aliases(const char * const name) { int result; char *username; GList *uids = NULL; GList *fwds = NULL; GList *dangling = NULL; /* For each alias, figure out if it resolves to a valid user * or some forwarding address. If neither, remove it. */ result = auth_check_user_ext(name,&uids,&fwds,0); if (!result) { qerrorf("Nothing found searching for [%s].\n", name); serious_errors = 1; return dangling; } uids = g_list_first(uids); while (uids) { username = auth_get_userid(*(u64_t *)uids->data); if (!username) dangling = g_list_prepend(dangling, uids->data); g_free(username); if (! g_list_next(uids)) break; uids = g_list_next(uids); } return dangling; }
static int do_envelope(void) { time_t start, stop; GList *lost = NULL; if (no_to_all) { qprintf("\nChecking DBMAIL for cached envelopes...\n"); } if (yes_to_all) { qprintf("\nRepairing DBMAIL for cached envelopes...\n"); } time(&start); if (db_icheck_envelope(&lost) < 0) { qerrorf("Failed. An error occured. Please check log.\n"); serious_errors = 1; return -1; } if (g_list_length(lost) > 0) { qerrorf("Ok. Found [%d] missing envelope values.\n", g_list_length(lost)); has_errors = 1; } else { qprintf("Ok. Found [%d] missing envelope values.\n", g_list_length(lost)); } if (yes_to_all) { if (db_set_envelope(lost) < 0) { qerrorf("Error setting the envelope cache"); has_errors = 1; } } g_list_free(g_list_first(lost)); time(&stop); qverbosef("--- checking envelope cache took %g seconds\n", difftime(stop, start)); return 0; }
static int do_rfc_size(void) { time_t start, stop; GList *lost = NULL; if (no_to_all) { qprintf("\nChecking DBMAIL for rfcsize field...\n"); } if (yes_to_all) { qprintf("\nRepairing DBMAIL for rfcsize field...\n"); } time(&start); if (db_icheck_rfcsize(&lost) < 0) { qerrorf("Failed. An error occured. Please check log.\n"); serious_errors = 1; return -1; } if (g_list_length(lost) > 0) { qerrorf("Ok. Found [%d] missing rfcsize values.\n", g_list_length(lost)); has_errors = 1; } else { qprintf("Ok. Found [%d] missing rfcsize values.\n", g_list_length(lost)); } if (yes_to_all) { if (db_update_rfcsize(lost) < 0) { qerrorf("Error setting the rfcsize values"); has_errors = 1; } } g_list_destroy(lost); time(&stop); qverbosef("--- checking rfcsize field took %g seconds\n", difftime(stop, start)); return 0; }
int do_purge_deleted(void) { u64_t deleted_messages; if (no_to_all) { qprintf("\nCounting messages with DELETE status...\n"); if (! db_deleted_count(&deleted_messages)) { qerrorf ("Failed. An error occured. Please check log.\n"); serious_errors = 1; return -1; } qprintf("Ok. [%llu] messages have DELETE status.\n", deleted_messages); } if (yes_to_all) { qprintf("\nDeleting messages with DELETE status...\n"); if (! db_deleted_purge()) { qerrorf ("Failed. An error occured. Please check log.\n"); serious_errors = 1; return -1; } qprintf("Ok. Messages deleted.\n"); } return 0; }
int do_rehash(void) { if (yes_to_all) { qprintf ("Rebuild hash keys for stored message chunks...\n"); if (db_rehash_store() == DM_EQUERY) { qerrorf("Failed. Please check the log.\n"); serious_errors = 1; return -1; } qprintf ("Ok. Hash keys rebuild successfully.\n"); } return 0; }
int do_vacuum_db(void) { if (no_to_all) { qprintf("\nVacuum and optimize not performed.\n"); } if (yes_to_all) { qprintf("\nVacuuming and optimizing database...\n"); fflush(stdout); if (db_cleanup() < 0) { qerrorf("Failed. Please check the log.\n"); serious_errors = 1; return -1; } qprintf("Ok. Database cleaned up.\n"); } return 0; }
int do_check_integrity(void) { time_t start, stop; GList *lost = NULL; const char *action; gboolean cleanup; long count = 0; if (yes_to_all) { action = "Repairing"; cleanup = TRUE; } else { action = "Checking"; cleanup = FALSE; } qprintf("\n%s DBMAIL message integrity...\n", action); /* This is what we do: 3. Check for loose physmessages 4. Check for loose partlists 5. Check for loose mimeparts */ /* part 3 */ start = stop; qprintf("\n%s DBMAIL physmessage integrity...\n", action); if ((count = db_icheck_physmessages(cleanup)) < 0) { qerrorf("Failed. An error occurred. Please check log.\n"); serious_errors = 1; return -1; } if (count > 0) { qerrorf("Ok. Found [%ld] unconnected physmessages.\n", count); if (cleanup) { qerrorf("Ok. Orphaned physmessages deleted.\n"); } } else { qprintf("Ok. Found [%ld] unconnected physmessages.\n", count); } time(&stop); qverbosef("--- %s unconnected physmessages took %g seconds\n", action, difftime(stop, start)); /* end part 3 */ /* part 4 */ start = stop; qprintf("\n%s DBMAIL partlists integrity...\n", action); if ((count = db_icheck_partlists(cleanup)) < 0) { qerrorf("Failed. An error occurred. Please check log.\n"); serious_errors = 1; return -1; } if (count > 0) { qerrorf("Ok. Found [%ld] unconnected partlists.\n", count); if (cleanup) { qerrorf("Ok. Orphaned partlists deleted.\n"); } } else { qprintf("Ok. Found [%ld] unconnected partlists.\n", count); } time(&stop); qverbosef("--- %s unconnected partlists took %g seconds\n", action, difftime(stop, start)); /* end part 4 */ /* part 5 */ start = stop; qprintf("\n%s DBMAIL mimeparts integrity...\n", action); if ((count = db_icheck_mimeparts(cleanup)) < 0) { qerrorf("Failed. An error occurred. Please check log.\n"); serious_errors = 1; return -1; } if (count > 0) { qerrorf("Ok. Found [%ld] unconnected mimeparts.\n", count); if (cleanup) { qerrorf("Ok. Orphaned mimeparts deleted.\n"); } } else { qprintf("Ok. Found [%ld] unconnected mimeparts.\n", count); } time(&stop); qverbosef("--- %s unconnected mimeparts took %g seconds\n", action, difftime(stop, start)); /* end part 5 */ g_list_destroy(lost); lost = NULL; time(&stop); qverbosef("--- %s block integrity took %g seconds\n", action, difftime(stop, start)); /* end part 6 */ return 0; }
static int mailbox_dump(u64_t mailbox_idnr, const char *dumpfile, const char *search, int delete_after_dump) { FILE *ostream; DbmailMailbox *mb = NULL; ImapSession *s = NULL; int result = 0; /* * For dbmail the usual filesystem semantics don't really * apply. Mailboxes can contain other mailboxes as well as * messages. For now however, this is solved by appending * the mailboxname with .mbox * * TODO: facilitate maildir type exports */ mb = dbmail_mailbox_new(mailbox_idnr); if (search) { s = dbmail_imap_session_new(); s->ci = client_init(NULL); if (! (imap4_tokenizer_main(s, search))) { qerrorf("error parsing search string"); dbmail_imap_session_delete(&s); dbmail_mailbox_free(mb); return 1; } if (dbmail_mailbox_build_imap_search(mb, s->args, &(s->args_idx), SEARCH_UNORDERED) < 0) { qerrorf("invalid search string"); dbmail_imap_session_delete(&s); dbmail_mailbox_free(mb); return 1; } dbmail_mailbox_search(mb); dbmail_imap_session_delete(&s); } if (strcmp(dumpfile, "-") == 0) { ostream = stdout; } else if (! (ostream = fopen(dumpfile, "a"))) { int err = errno; qerrorf("opening [%s] failed [%s]\n", dumpfile, strerror(err)); result = -1; goto cleanup; } if (dbmail_mailbox_dump(mb, ostream) < 0) { qerrorf("Export failed\n"); result = -1; goto cleanup; } if (delete_after_dump) { int deleted_flag[IMAP_NFLAGS]; memset(deleted_flag, 0, IMAP_NFLAGS * sizeof(int)); deleted_flag[IMAP_FLAG_DELETED] = 1; GList *ids = g_tree_keys(MailboxState_getIds(mb->mbstate)); while (ids) { // Flag the selected messages \\Deleted // Following this, dbmail-util -d sets deleted status if (delete_after_dump & 1) { if (db_set_msgflag(*(u64_t *)ids->data, deleted_flag, NULL, IMAPFA_ADD, NULL) < 0) { qerrorf("Error setting flags for message [%llu]\n", *(u64_t *)ids->data); result = -1; } } // Set deleted status on each message // Following this, dbmail-util -p sets purge status if (delete_after_dump & 2) { if (! db_set_message_status(*(u64_t *)ids->data, MESSAGE_STATUS_DELETE)) { qerrorf("Error setting status for message [%llu]\n", *(u64_t *)ids->data); result = -1; } } if (!g_list_next(ids)) break; ids = g_list_next(ids); } g_list_free(g_list_first(ids)); } cleanup: if (mb) dbmail_mailbox_free(mb); if ((ostream) && (ostream != stdout)) fclose(ostream); return result; }
int main(int argc, char *argv[]) { int opt = 0, opt_prev = 0; int show_help = 0; int result = 0, delete_after_dump = 0, recursive = 0; char *user=NULL, *mailbox=NULL, *outfile=NULL, *basedir=NULL, *search=NULL; openlog(PNAME, LOG_PID, LOG_MAIL); setvbuf(stdout, 0, _IONBF, 0); g_mime_init(0); /* get options */ opterr = 0; /* suppress error message from getopt() */ while ((opt = getopt(argc, argv, "-u:m:o:b:s:dDr" /* Major modes */ "f:qvVh" /* Common options */ )) != -1) { /* The initial "-" of optstring allows unaccompanied * options and reports them as the optarg to opt 1 (not '1') */ if (opt == 1) opt = opt_prev; opt_prev = opt; switch (opt) { /* export specific options */ case 'u': if (optarg && strlen(optarg)) user = optarg; break; case 'm': if (optarg && strlen(optarg)) mailbox = optarg; break; case 'b': if (optarg && strlen(optarg)) basedir = optarg; break; case 'o': if (optarg && strlen(optarg)) outfile = optarg; break; case 'd': delete_after_dump |= 1; break; case 'D': delete_after_dump |= 2; break; case 'r': recursive = 1; break; case 's': if (optarg && strlen(optarg)) search = optarg; else { qerrorf("dbmail-mailbox: -s requires a value\n\n"); result = 1; } break; /* Common options */ case 'f': if (optarg && strlen(optarg) > 0) configFile = optarg; else { qerrorf("dbmail-mailbox: -f requires a filename\n\n"); result = 1; } break; case 'h': show_help = 1; break; case 'q': /* If we get q twice, be really quiet! */ if (quiet) reallyquiet = 1; if (!verbose) quiet = 1; break; case 'v': if (!quiet) verbose = 1; break; case 'V': /* Show the version and return non-zero. */ PRINTF_THIS_IS_DBMAIL; result = 1; break; default: /* printf("unrecognized option [%c], continuing...\n",optopt); */ break; } /* If there's a non-negative return code, * it's time to free memory and bail out. */ if (result) goto freeall; } /* If nothing is happening, show the help text. */ if (!user || (basedir && outfile) || show_help) { do_showhelp(); result = 1; goto freeall; } /* read the config file */ if (config_read(configFile) == -1) { qerrorf("Failed. Unable to read config file %s\n", configFile); result = -1; goto freeall; } SetTraceLevel("DBMAIL"); GetDBParams(); /* open database connection */ if (db_connect() != 0) { qerrorf ("Failed. Could not connect to database (check log)\n"); result = -1; goto freeall; } /* open authentication connection */ if (auth_connect() != 0) { qerrorf("Failed. Could not connect to authentication (check log)\n"); result = -1; goto freeall; } /* Loop over all user accounts if there's a wildcard. */ if (strchr(user, '?') || strchr(user, '*')) { GList *all_users = auth_get_known_users(); GList *matching_users = match_glob_list(user, all_users); GList *users = g_list_first(matching_users); if (!users) { qerrorf("Error: no users matching [%s] were found.\n", user); g_list_destroy(all_users); result = -1; goto freeall; } while (users) { result = do_export(users->data, mailbox, basedir, outfile, search, delete_after_dump, recursive); if (!g_list_next(users)) break; users = g_list_next(users); } g_list_destroy(all_users); g_list_destroy(matching_users); } else { /* No globbing, just run with this one user. */ result = do_export(user, mailbox, basedir, outfile, search, delete_after_dump, recursive); } /* Here's where we free memory and quit. * Be sure that all of these are NULL safe! */ freeall: db_disconnect(); auth_disconnect(); config_free(); g_mime_shutdown(); if (result < 0) qerrorf("Command failed.\n"); return result; }
static int do_export(char *user, char *base_mailbox, char *basedir, char *outfile, char *search, int delete_after_dump, int recursive) { u64_t user_idnr = 0, owner_idnr = 0, mailbox_idnr = 0; char *dumpfile = NULL, *mailbox = NULL, *search_mailbox = NULL, *dir = NULL; GList *children = NULL; int result = 0; /* Verify the existence of this user */ if (! auth_user_exists(user, &user_idnr)) { qerrorf("Error: user [%s] does not exist.\n", user); result = -1; goto cleanup; } mailbox = g_new0(char, IMAP_MAX_MAILBOX_NAMELEN); if (!base_mailbox) { /* Always recursive without a mailbox base */ search_mailbox = g_strdup("*"); } else if (recursive) { /* Base and everything below */ search_mailbox = g_strdup_printf("%s*", base_mailbox); } else if (!recursive) { /* Should yield same results as plain db_findmailbox */ search_mailbox = g_strdup_printf("%s", base_mailbox); } /* FIXME: What are the possible error conditions here? */ db_findmailbox_by_regex(user_idnr, search_mailbox, &children, 0); /* Decision process for basedir vs. outfile: * If we're dumping one mailbox for one user, it goes to * stdout. If we've been given -o -, dump everything to * stdout (e.g., one giant mbox). If we've been given foo */ if (!outfile && !basedir) { /* Default is to use basedir of . */ basedir = "."; } else if (outfile) { /* Everything goes into this one file */ dumpfile = outfile; } children = g_list_first(children); qerrorf("Exporting [%u] mailboxes for [%s]\n", g_list_length(children), user); while (children) { mailbox_idnr = *(u64_t *)children->data; db_getmailboxname(mailbox_idnr, user_idnr, mailbox); if (! db_get_mailbox_owner(mailbox_idnr, &owner_idnr)) { qerrorf("Error checking mailbox ownership"); goto cleanup; } if (owner_idnr == user_idnr) { if (basedir) { /* Prepare the directory */ dumpfile = g_strdup_printf("%s/%s/%s.mbox", basedir, user, mailbox); dir = g_path_get_dirname(dumpfile); if (g_mkdir_with_parents(dir, 0700)) { qerrorf("can't create directory [%s]\n", dir); result = -1; goto cleanup; } } qerrorf(" export mailbox %s -> %s\n", mailbox, dumpfile); if ((result = mailbox_dump(mailbox_idnr, dumpfile, search, delete_after_dump)) != 0) { qerrorf("error exporting mailbox %s -> %s\n", mailbox, dumpfile); goto cleanup; } if (delete_after_dump) db_update("UPDATE %smailboxes SET seq=seq+1 WHERE mailbox_idnr=%d",DBPFX,mailbox_idnr); if (basedir) { g_free(dir); g_free(dumpfile); } } if (! g_list_next(children)) break; children = g_list_next(children); } cleanup: g_list_destroy(children); g_free(search_mailbox); g_free(mailbox); return result; }
int main(int argc, char *argv[]) { int check_integrity = 0; int check_iplog = 0, check_replycache = 0; char *timespec_iplog = NULL, *timespec_replycache = NULL; int vacuum_db = 0, purge_deleted = 0, set_deleted = 0, dangling_aliases = 0, rehash = 0; int show_help = 0; int do_nothing = 1; int is_header = 0; int migrate = 0, migrate_limit = 10000; static struct option long_options[] = { { "rehash", 0, 0, 0 }, { 0, 0, 0, 0 } }; int opt_index = 0; int opt; g_mime_init(0); openlog(PNAME, LOG_PID, LOG_MAIL); setvbuf(stdout, 0, _IONBF, 0); /* get options */ opterr = 0; /* suppress error message from getopt() */ while ((opt = getopt_long(argc, argv, "-acbtl:r:pudsMm:" "i" "f:qnyvVh", long_options, &opt_index)) != -1) { /* The initial "-" of optstring allows unaccompanied * options and reports them as the optarg to opt 1 (not '1') */ switch (opt) { case 0: do_nothing = 0; if (strcmp(long_options[opt_index].name,"rehash")==0) rehash = 1; break; case 'a': /* This list should be kept up to date. */ vacuum_db = 1; purge_deleted = 1; set_deleted = 1; dangling_aliases = 1; check_integrity = 1; is_header = 1; do_nothing = 0; break; case 'c': vacuum_db = 1; do_nothing = 0; break; case 'b': is_header = 1; do_nothing = 0; break; case 'p': purge_deleted = 1; do_nothing = 0; break; case 'd': set_deleted = 1; do_nothing = 0; break; case 's': dangling_aliases = 1; do_nothing = 0; break; case 't': check_integrity = 1; do_nothing = 0; break; case 'u': /* deprecated */ break; case 'l': check_iplog = 1; do_nothing = 0; if (optarg) timespec_iplog = g_strdup(optarg); break; case 'r': check_replycache = 1; do_nothing = 0; if (optarg) timespec_replycache = g_strdup(optarg); break; case 'M': migrate = 1; do_nothing = 0; break; case 'm': if (optarg) migrate_limit = atoi(optarg); break; case 'i': qerrorf("Interactive console is not supported in this release.\n"); return 1; /* Common options */ case 'h': show_help = 1; do_nothing = 0; break; case 'n': no_to_all = 1; break; case 'y': yes_to_all = 1; break; case 'q': /* If we get q twice, be really quiet! */ if (quiet) reallyquiet = 1; if (!verbose) quiet = 1; break; case 'f': if (optarg && strlen(optarg) > 0) configFile = optarg; else { qerrorf("dbmail-util: -f requires a filename\n\n" ); return 1; } break; case 'v': verbose = 1; break; case 'V': PRINTF_THIS_IS_DBMAIL; return 1; default: printf("unrecognized option [%c]\n", optopt); show_help = 1; break; } } if (do_nothing || show_help || (no_to_all && yes_to_all)) { do_showhelp(); return 1; } /* Don't make any changes unless specifically authorized. */ if (!yes_to_all) { qprintf("Choosing dry-run mode. No changes will be made at this time.\n"); no_to_all = 1; } config_read(configFile); SetTraceLevel("DBMAIL"); GetDBParams(); qverbosef("Opening connection to database... \n"); if (db_connect() != 0) { qerrorf("Failed. An error occured. Please check log.\n"); return -1; } qverbosef("Opening connection to authentication... \n"); if (auth_connect() != 0) { qerrorf("Failed. An error occured. Please check log.\n"); return -1; } qverbosef("Ok. Connected.\n"); if (check_integrity) do_check_integrity(); if (purge_deleted) do_purge_deleted(); if (is_header) do_header_cache(); if (set_deleted) do_set_deleted(); if (dangling_aliases) do_dangling_aliases(); if (check_iplog) do_check_iplog(timespec_iplog); if (check_replycache) do_check_replycache(timespec_replycache); if (vacuum_db) do_vacuum_db(); if (rehash) do_rehash(); if (migrate) do_migrate(migrate_limit); if (!has_errors && !serious_errors) { qprintf("\nMaintenance done. No errors found.\n"); } else { qerrorf("\nMaintenance done. Errors were found"); if (serious_errors) { qerrorf(" but not fixed due to failures.\n"); qerrorf("Please check the logs for further details, " "turning up the trace level as needed.\n"); // Indicate that something went really wrong has_errors = 3; } else if (no_to_all) { qerrorf(" but not fixed.\n"); qerrorf("Run again with the '-y' option to " "repair the errors.\n"); // Indicate that the program should be run with -y has_errors = 2; } else if (yes_to_all) { qerrorf(" and fixed.\n"); qerrorf("We suggest running dbmail-util again to " "confirm that all errors were repaired.\n"); // Indicate that the program should be run again has_errors = 1; } } auth_disconnect(); db_disconnect(); config_free(); g_mime_shutdown(); return has_errors; }
int do_check_integrity(void) { time_t start, stop; GList *lost = NULL; const char *action; gboolean cleanup; long count = 0; if (yes_to_all) { action = "Repairing"; cleanup = TRUE; } else { action = "Checking"; cleanup = FALSE; } qprintf("\n%s DBMAIL message integrity...\n", action); /* This is what we do: 3. Check for loose physmessages 4. Check for loose partlists 5. Check for loose mimeparts 6. Check for loose headernames 7. Check for loose headervalues */ /* part 3 */ time(&start); qprintf("\n%s DBMAIL physmessage integrity...\n", action); if ((count = db_icheck_physmessages(cleanup)) < 0) { qerrorf("Failed. An error occurred. Please check log.\n"); serious_errors = 1; return -1; } if (count > 0) { qerrorf("Ok. Found [%ld] unconnected physmessages.\n", count); if (cleanup) { qerrorf("Ok. Orphaned physmessages deleted.\n"); } } else { qprintf("Ok. Found [%ld] unconnected physmessages.\n", count); } time(&stop); qverbosef("--- %s unconnected physmessages took %g seconds\n", action, difftime(stop, start)); /* end part 3 */ /* part 4 */ start = stop; qprintf("\n%s DBMAIL partlists integrity...\n", action); if ((count = db_icheck_partlists(cleanup)) < 0) { qerrorf("Failed. An error occurred. Please check log.\n"); serious_errors = 1; return -1; } if (count > 0) { qerrorf("Ok. Found [%ld] unconnected partlists.\n", count); if (cleanup) { qerrorf("Ok. Orphaned partlists deleted.\n"); } } else { qprintf("Ok. Found [%ld] unconnected partlists.\n", count); } time(&stop); qverbosef("--- %s unconnected partlists took %g seconds\n", action, difftime(stop, start)); /* end part 4 */ /* part 5 */ start = stop; qprintf("\n%s DBMAIL mimeparts integrity...\n", action); if ((count = db_icheck_mimeparts(cleanup)) < 0) { qerrorf("Failed. An error occurred. Please check log.\n"); serious_errors = 1; return -1; } if (count > 0) { qerrorf("Ok. Found [%ld] unconnected mimeparts.\n", count); if (cleanup) { qerrorf("Ok. Orphaned mimeparts deleted.\n"); } } else { qprintf("Ok. Found [%ld] unconnected mimeparts.\n", count); } time(&stop); qverbosef("--- %s unconnected mimeparts took %g seconds\n", action, difftime(stop, start)); /* end part 5 */ /* part 6 */ Field_T config; bool cache_readonly = false; config_get_value("header_cache_readonly", "DBMAIL", config); if (strlen(config)) { if (MATCH(config, "true") || MATCH(config, "yes")) { cache_readonly = true; } } if (! cache_readonly) { start = stop; qprintf("\n%s DBMAIL headernames integrity...\n", action); if ((count = db_icheck_headernames(cleanup)) < 0) { qerrorf("Failed. An error occurred. Please check log.\n"); serious_errors = 1; return -1; } qprintf("Ok. Found [%ld] unconnected headernames.\n", count); if (count > 0 && cleanup) { qerrorf("Ok. Orphaned headernames deleted.\n"); } time(&stop); qverbosef("--- %s unconnected headernames took %g seconds\n", action, difftime(stop, start)); } /* end part 6 */ /* part 7 */ start = stop; qprintf("\n%s DBMAIL headervalues integrity...\n", action); if ((count = db_icheck_headervalues(cleanup)) < 0) { qerrorf("Failed. An error occurred. Please check log.\n"); serious_errors = 1; return -1; } qprintf("Ok. Found [%ld] unconnected headervalues.\n", count); if (count > 0 && cleanup) { qerrorf("Ok. Orphaned headervalues deleted.\n"); } time(&stop); qverbosef("--- %s unconnected headervalues took %g seconds\n", action, difftime(stop, start)); /* end part 7 */ g_list_destroy(lost); lost = NULL; time(&stop); qverbosef("--- %s block integrity took %g seconds\n", action, difftime(stop, start)); return 0; }