Пример #1
0
{
    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");
Пример #2
0
/*
 * 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;
}
Пример #3
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;
}
Пример #4
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);
        }
    }
}