예제 #1
0
static int restore_expunged(struct mailbox *mailbox, int mode, unsigned long *uids,
                     unsigned nuids, time_t time_since, unsigned *numrestored,
                     const char *extname)
{
    struct index_record newrecord;
    annotate_state_t *astate = NULL;
    unsigned uidnum = 0;
    char oldfname[MAX_MAILBOX_PATH];
    const char *fname;
    char *userid = mboxname_to_userid(mailbox->name);
    int r = 0;

    *numrestored = 0;

    struct mailbox_iter *iter = mailbox_iter_init(mailbox, 0, ITER_SKIP_UNLINKED);
    const message_t *msg;
    while ((msg = mailbox_iter_step(iter))) {
        const struct index_record *record = msg_record(msg);
        /* still active */
        if (!(record->internal_flags & FLAG_INTERNAL_EXPUNGED))
            continue;

        if (mode == MODE_UID) {
            while (uidnum < nuids && record->uid > uids[uidnum])
                uidnum++;
            if (uidnum >= nuids)
                continue;
            if (record->uid != uids[uidnum])
                continue;
            /* otherwise we want this one */
        }
        else if (mode == MODE_TIME) {
            if (record->last_updated < time_since)
                continue;
            /* otherwise we want this one */
        }

        /* work on a copy */
        newrecord = *record;

        /* duplicate the old filename */
        fname = mailbox_record_fname(mailbox, record);
        xstrncpy(oldfname, fname, MAX_MAILBOX_PATH);

        /* bump the UID, strip the flags */
        newrecord.uid = mailbox->i.last_uid + 1;
        newrecord.internal_flags &= ~FLAG_INTERNAL_EXPUNGED;
        if (unsetdeleted)
            newrecord.system_flags &= ~FLAG_DELETED;

        /* copy the message file */
        fname = mailbox_record_fname(mailbox, &newrecord);
        r = mailbox_copyfile(oldfname, fname, 0);
        if (r) break;

        /* add the flag if requested */
        if (addflag) {
            int userflag = 0;
            r = mailbox_user_flag(mailbox, addflag, &userflag, 1);
            if (r) break;
            newrecord.user_flags[userflag/32] |= 1<<(userflag&31);
        }

        /* and append the new record */
        r = mailbox_append_index_record(mailbox, &newrecord);
        if (r) break;

        /* ensure we have an astate connected to the destination
         * mailbox, so that the annotation txn will be committed
         * when we close the mailbox */
        r = mailbox_get_annotate_state(mailbox, newrecord.uid, &astate);
        if (r) break;

        /* and copy over any annotations */
        r = annotate_msg_copy(mailbox, record->uid,
                              mailbox, newrecord.uid,
                              userid);
        if (r) break;

        if (verbose)
            printf("Unexpunged %s: %u => %u\n",
                   extname, record->uid, newrecord.uid);

        /* mark the old one unlinked so we don't see it again */
        struct index_record oldrecord = *record;
        oldrecord.internal_flags |= FLAG_INTERNAL_UNLINKED |
            FLAG_INTERNAL_NEEDS_CLEANUP;
        r = mailbox_rewrite_index_record(mailbox, &oldrecord);
        if (r) break;

        (*numrestored)++;
    }

    /* better get that seen to */
    if (*numrestored)
        mailbox->i.options |= OPT_MAILBOX_NEEDS_UNLINK;

    mailbox_iter_done(&iter);
    free(userid);
    return r;
}
예제 #2
0
static int restore_expunged(struct mailbox *mailbox, int mode, unsigned long *uids,
		     unsigned nuids, time_t time_since, unsigned *numrestored,
		     const char *mboxname)
{
    uint32_t recno;
    uint32_t olduid;
    struct index_record record;
    unsigned uidnum = 0;
    char oldfname[MAX_MAILBOX_PATH];
    const char *fname;
    int r = 0;

    *numrestored = 0;

    for (recno = 1; recno <= mailbox->i.num_records; recno++) {
	r = mailbox_read_index_record(mailbox, recno, &record);
	if (r) return r;

	/* still active */
	if (!(record.system_flags & FLAG_EXPUNGED))
	    continue;
	/* no file, unrescuable */
	if (record.system_flags & FLAG_UNLINKED)
	    continue;

	if (mode == MODE_UID) {
	    while (uidnum < nuids && record.uid > uids[uidnum])
		uidnum++;
	    if (uidnum >= nuids)
		continue;
	    if (record.uid != uids[uidnum])
		continue;
	    /* otherwise we want this one */
	}
	else if (mode == MODE_TIME) {
	    if (record.last_updated < time_since)
		continue;
	    /* otherwise we want this one */
	}

	/* mark the old one unlinked so we don't see it again */
	olduid = record.uid;
	record.system_flags |= FLAG_UNLINKED;
	r = mailbox_rewrite_index_record(mailbox, &record);
	if (r) return r;

	/* duplicate the old filename */
	fname = mailbox_message_fname(mailbox, olduid);
	xstrncpy(oldfname, fname, MAX_MAILBOX_PATH);

	/* bump the UID, strip the flags */
	record.uid = mailbox->i.last_uid + 1;
	record.system_flags &= ~(FLAG_UNLINKED|FLAG_EXPUNGED);
	if (unsetdeleted)
	    record.system_flags &= ~FLAG_DELETED;

	/* copy the message file */
	fname = mailbox_message_fname(mailbox, record.uid);
	r = mailbox_copyfile(oldfname, fname, 0);
	if (r) return r;

	/* and append the new record */
	mailbox_append_index_record(mailbox, &record);

	if (verbose)
	    printf("Unexpunged %s: %u => %u\n",
		   mboxname, olduid, record.uid);

	(*numrestored)++;
    }

    return 0;
}