{ if (!data) return 0; unsigned i, msgno; int r = 0; int flag = 0; struct mailbox *mailbox = NULL; const struct index_record *record; int j; signals_poll(); /* Convert internal name to external */ const char *extname = mbname_extname(data->mbname, &recon_namespace, "cyrus"); printf("Examining %s...", extname); const char *name = mbname_intname(data->mbname); /* Open/lock header */ r = mailbox_open_irl(name, &mailbox); if (r) return r; /* Open/lock header */ r = mailbox_open_irl(name, &mailbox); if (r) return r; if (chdir(mailbox_datapath(mailbox, 0)) == -1) { r = IMAP_IOERROR; goto done; } printf(" Mailbox Header Info:\n");
/* * mboxlist_findall() callback function to reconstruct a mailbox */ static int do_reconstruct(struct findall_data *data, void *rock) { if (!data) return 0; strarray_t *discovered = (strarray_t *)rock; int r; static char lastname[MAX_MAILBOX_NAME] = ""; char *other; struct mailbox *mailbox = NULL; char outpath[MAX_MAILBOX_PATH]; const char *name = mbname_intname(data->mbname); signals_poll(); /* don't repeat */ if (!strcmp(name, lastname)) return 0; strncpy(lastname, name, sizeof(lastname)); lastname[sizeof(lastname)-1] = '\0'; r = mailbox_reconstruct(lastname, reconstruct_flags); if (r) { com_err(lastname, r, "%s", (r == IMAP_IOERROR) ? error_message(errno) : "Failed to reconstruct mailbox"); return 0; } r = mailbox_open_iwl(lastname, &mailbox); if (r) { com_err(lastname, r, "Failed to open after reconstruct"); return 0; } other = hash_lookup(mailbox->uniqueid, &unqid_table); if (other) { syslog (LOG_ERR, "uniqueid clash with %s for %s - changing %s", other, mailbox->uniqueid, mailbox->name); /* uniqueid change required! */ mailbox_make_uniqueid(mailbox); } hash_insert(mailbox->uniqueid, xstrdup(mailbox->name), &unqid_table); /* Convert internal name to external */ char *extname = mboxname_to_external(lastname, &recon_namespace, NULL); if (!(reconstruct_flags & RECONSTRUCT_QUIET)) printf("%s\n", extname); strncpy(outpath, mailbox_meta_fname(mailbox, META_HEADER), MAX_MAILBOX_NAME); if (setversion) { /* need to re-set the version! */ int r = mailbox_setversion(mailbox, setversion); if (r) { printf("FAILED TO REPACK %s with new version %s\n", extname, error_message(r)); } else { printf("Repacked %s to version %d\n", extname, setversion); } } mailbox_close(&mailbox); free(extname); if (discovered) { char fnamebuf[MAX_MAILBOX_PATH]; char *ptr; DIR *dirp; struct dirent *dirent; struct stat sbuf; ptr = strstr(outpath, "cyrus.header"); if (!ptr) return 0; *ptr = 0; r = chdir(outpath); if (r) return 0; /* we recurse down this directory to see if there's any mailboxes under this not in the mailboxes database */ dirp = opendir("."); if (!dirp) return 0; while ((dirent = readdir(dirp)) != NULL) { /* mailbox directories never have a dot in them */ if (strchr(dirent->d_name, '.')) continue; if (stat(dirent->d_name, &sbuf) < 0) continue; if (!S_ISDIR(sbuf.st_mode)) continue; /* ok, we found a directory that doesn't have a dot in it; is there a cyrus.header file? */ snprintf(fnamebuf, MAX_MAILBOX_PATH, "%s%s", dirent->d_name, FNAME_HEADER); if (stat(fnamebuf, &sbuf) < 0) continue; /* ok, we have a real mailbox directory */ char buf[MAX_MAILBOX_NAME]; snprintf(buf, MAX_MAILBOX_NAME, "%s.%s", name, dirent->d_name); /* does fnamebuf exist as a mailbox in mboxlist? */ do { r = mboxlist_lookup(buf, NULL, NULL); } while (r == IMAP_AGAIN); if (!r) continue; /* mailbox exists; it'll be reconstructed with a -r */ if (r != IMAP_MAILBOX_NONEXISTENT) break; /* erg? */ else r = 0; /* reset error condition */ printf("discovered %s\n", buf); strarray_append(discovered, buf); } closedir(dirp); } return 0; }
static int dump_me(struct findall_data *data, void *rock) { int r; char boundary[128]; struct imapurl url; char imapurl[MAX_MAILBOX_PATH+1]; struct incremental_record *irec = (struct incremental_record *) rock; struct searchargs searchargs; struct index_state *state; unsigned *uids = NULL; unsigned *uidseq = NULL; int i, n, numuids; unsigned msgno; /* don't want partial matches */ if (!data || !data->mbname) return 0; const char *name = mbname_intname(data->mbname); r = index_open(name, NULL, &state); if (r) { if (verbose) { printf("error opening %s: %s\n", name, error_message(r)); } return 0; } generate_boundary(boundary, sizeof(boundary)); printf("Content-Type: multipart/related; boundary=\"%s\"\n\n", boundary); printf("--%s\n", boundary); printf("Content-Type: text/xml\n"); printf("IMAP-Dump-Version: 0\n"); printf("\n"); printf("<imapdump uniqueid=\"%s\">\n", state->mailbox->uniqueid); memset(&url, 0, sizeof(struct imapurl)); url.server = config_servername; url.mailbox = name; imapurl_toURL(imapurl, &url); printf(" <mailbox-url>%s</mailbox-url>\n", imapurl); printf(" <incremental-uid>%d</incremental-uid>\n", irec->incruid); printf(" <nextuid>%u</nextuid>\n", state->mailbox->i.last_uid + 1); printf("\n"); memset(&searchargs, 0, sizeof(struct searchargs)); searchargs.root = search_expr_new(NULL, SEOP_TRUE); numuids = index_getuidsequence(state, &searchargs, &uids); search_expr_free(searchargs.root); print_seq("uidlist", NULL, uids, numuids); printf("\n"); printf(" <flags>\n"); searchargs.root = systemflag_match(FLAG_ANSWERED); uidseq = NULL; n = index_getuidsequence(state, &searchargs, &uidseq); search_expr_free(searchargs.root); print_seq("flag", "name=\"\\Answered\" user=\"*\"", uidseq, n); if (uidseq) free(uidseq); searchargs.root = systemflag_match(FLAG_DELETED); uidseq = NULL; n = index_getuidsequence(state, &searchargs, &uidseq); search_expr_free(searchargs.root); print_seq("flag", "name=\"\\Deleted\" user=\"*\"", uidseq, n); if (uidseq) free(uidseq); searchargs.root = systemflag_match(FLAG_DRAFT); uidseq = NULL; n = index_getuidsequence(state, &searchargs, &uidseq); search_expr_free(searchargs.root); print_seq("flag", "name=\"\\Draft\" user=\"*\"", uidseq, n); if (uidseq) free(uidseq); searchargs.root = systemflag_match(FLAG_FLAGGED); uidseq = NULL; n = index_getuidsequence(state, &searchargs, &uidseq); search_expr_free(searchargs.root); print_seq("flag", "name=\"\\Flagged\" user=\"*\"", uidseq, n); if (uidseq) free(uidseq); printf(" </flags>\n"); printf("</imapdump>\n"); i = 0; while (i < numuids && uids[i] < irec->incruid) { /* already dumped this message */ /* xxx could do binary search to get to the first undumped uid */ i++; } for (msgno = 1; msgno <= state->exists; msgno++) { struct buf buf = BUF_INITIALIZER; struct index_map *im = &state->map[msgno-1]; struct index_record record; while (im->uid > uids[i] && i < numuids) i++; if (i >= numuids) break; if (im->uid < uids[i]) continue; /* got a match */ i++; memset(&record, 0, sizeof(struct index_record)); record.recno = im->recno; record.uid = im->uid; if (mailbox_reload_index_record(state->mailbox, &record)) continue; printf("\n--%s\n", boundary); printf("Content-Type: message/rfc822\n"); printf("Content-ID: %d\n", uids[i]); printf("\n"); r = mailbox_map_record(state->mailbox, &record, &buf); if (r) { if (verbose) { printf("error mapping message %u: %s\n", record.uid, error_message(r)); } break; } fwrite(buf.s, 1, buf.len, stdout); buf_free(&buf); } printf("\n--%s--\n", boundary); free(uids); index_close(&state); return 0; }
static void apply_mailbox_options(struct backup_mailbox *mailbox, const struct restore_options *options) { if (options->override_mboxname) { if (options->verbose) { fprintf(stderr, "%s: overriding mboxname with %s\n", mailbox->mboxname, options->override_mboxname); } if (mailbox->mboxname) free(mailbox->mboxname); mailbox->mboxname = xstrdup(options->override_mboxname); } if (options->override_partition) { if (options->verbose) { fprintf(stderr, "%s: overriding partition with %s (was %s)\n", mailbox->mboxname, options->override_partition, mailbox->partition); } if (mailbox->partition) free(mailbox->partition); mailbox->partition = xstrdup(options->override_partition); } if (options->override_acl) { if (options->verbose) { fprintf(stderr, "%s: overriding acl with '%s' (was '%s')\n", mailbox->mboxname, options->override_acl, mailbox->acl); } if (mailbox->acl) free(mailbox->acl); /* treat empty override string as no ACL, resulting in the mailbox * being restored with the default ACL for its owner. */ if (*options->override_acl) { mailbox->acl = xstrdup(options->override_acl); } else { mailbox->acl = NULL; } } if (!options->keep_uidvalidity) { if (options->verbose) { fprintf(stderr, "%s: not trying to keep uidvalidity\n", mailbox->mboxname); } if (mailbox->uniqueid) free(mailbox->uniqueid); mailbox->uniqueid = NULL; mailbox->highestmodseq = 0; mailbox->uidvalidity = 0; } else if (options->verbose) { fprintf(stderr, "%s: trying to keep uidvalidity(%u), " "uniqueid(%s), highestmodseq(" MODSEQ_FMT ")\n", mailbox->mboxname, mailbox->uidvalidity, mailbox->uniqueid, mailbox->highestmodseq); } if (mailbox->mboxname && options->trim_deletedprefix) { mbname_t *mbname = mbname_from_intname(mailbox->mboxname); if (mbname_isdeleted(mbname)) { char *freeme = mailbox->mboxname; mbname_set_isdeleted(mbname, 0); mailbox->mboxname = xstrdup(mbname_intname(mbname)); if (options->verbose) { fprintf(stderr, "%s: removing deletedprefix (was %s)\n", mailbox->mboxname, freeme); } free(freeme); } mbname_free(&mbname); } if (options->expunged_mode != RESTORE_EXPUNGED_OKAY) { struct backup_mailbox_message *iter, *tmp, *next; next = mailbox->records->head; while ((iter = next)) { next = iter->next; tmp = NULL; switch (options->expunged_mode) { case RESTORE_EXPUNGED_EXCLUDE: if (iter->expunged) { tmp = backup_mailbox_message_list_remove(mailbox->records, iter); if (options->verbose) { fprintf(stderr, "%s: excluding expunged message: %s\n", mailbox->mboxname, message_guid_encode(&iter->guid)); } } break; case RESTORE_EXPUNGED_ONLY: if (!iter->expunged) { tmp = backup_mailbox_message_list_remove(mailbox->records, iter); if (options->verbose) { fprintf(stderr, "%s: excluding unexpunged message: %s\n", mailbox->mboxname, message_guid_encode(&iter->guid)); } } break; default: break; } if (tmp) backup_mailbox_message_free(&tmp); } } }