Esempio n. 1
0
/* Create filename corresponding to DAV DB for mailbox */
EXPORTED void dav_getpath(struct buf *fname, struct mailbox *mailbox)
{
    const char *userid;

    userid = mboxname_to_userid(mailbox->name);

    if (userid) dav_getpath_byuserid(fname, userid);
    else buf_setcstr(fname, mailbox_meta_fname(mailbox, META_DAV));
}
Esempio n. 2
0
/* create a downgraded index file in cyrus.index.  We don't copy back
 * expunged messages, sorry */
static int dump_index(struct mailbox *mailbox, int oldversion,
                      struct seqset *expunged_seq, int first, int sync,
                      struct protstream *pin, struct protstream *pout)
{
    char oldname[MAX_MAILBOX_PATH];
    const char *fname;
    int oldindex_fd = -1;
    indexbuffer_t headerbuf;
    indexbuffer_t recordbuf;
    char *hbuf = (char *)headerbuf.buf;
    char *rbuf = (char *)recordbuf.buf;
    int header_size;
    int record_size;
    int n, r;

    if (oldversion == 6) {
        header_size = 76;
        record_size = 60;
    }
    else if (oldversion == 7) {
        header_size = 76;
        record_size = 72;
    }
    else if (oldversion == 8) {
        header_size = 92;
        record_size = 80;
    }
    else if (oldversion == 9) {
        header_size = 96;
        record_size = 80;
    }
    else if (oldversion == 10) {
        header_size = 96;
        record_size = 88;
    }
    else {
        return IMAP_MAILBOX_BADFORMAT;
    }

    fname = mailbox_meta_fname(mailbox, META_INDEX);
    snprintf(oldname, MAX_MAILBOX_PATH, "%s.OLD", fname);

    oldindex_fd = open(oldname, O_RDWR|O_TRUNC|O_CREAT, 0666);
    if (oldindex_fd == -1) goto fail;

    downgrade_header(&mailbox->i, hbuf, oldversion,
                     header_size, record_size);

    /* Write header - everything we'll say */
    n = retry_write(oldindex_fd, hbuf, header_size);
    if (n == -1) goto fail;

    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);
        /* we have to make sure expunged records don't get the
         * file copied, or a reconstruct could bring them back
         * to life!  It we're not creating an expunged file... */
        if (record->system_flags & FLAG_EXPUNGED) {
            if (oldversion < 9) seqset_add(expunged_seq, record->uid, 1);
            continue;
        }
        /* not making sure exists matches, we do trust a bit */
        downgrade_record(record, rbuf, oldversion);
        n = retry_write(oldindex_fd, rbuf, record_size);
        if (n == -1) goto fail;
    }

    mailbox_iter_done(&iter);

    close(oldindex_fd);
    r = dump_file(first, sync, pin, pout, oldname, "cyrus.index", NULL, 0);
    unlink(oldname);
    if (r) return r;

    /* create cyrus.expunge */
    if (oldversion > 8 && mailbox->i.num_records > mailbox->i.exists) {
        int nexpunge = mailbox->i.num_records - mailbox->i.exists;
        fname = mailbox_meta_fname(mailbox, META_EXPUNGE);
        snprintf(oldname, MAX_MAILBOX_PATH, "%s.OLD", fname);

        oldindex_fd = open(oldname, O_RDWR|O_TRUNC|O_CREAT, 0666);
        if (oldindex_fd == -1) goto fail;

        header_set_num_records(hbuf, nexpunge);

        /* Write header - everything we'll say */
        n = retry_write(oldindex_fd, hbuf, header_size);
        if (n == -1) goto fail;

        iter = mailbox_iter_init(mailbox, 0, ITER_SKIP_UNLINKED);
        while ((msg = mailbox_iter_step(iter))) {
            const struct index_record *record = msg_record(msg);
            /* ignore non-expunged records */
            if (!(record->system_flags & FLAG_EXPUNGED))
                continue;
            downgrade_record(record, rbuf, oldversion);
            n = retry_write(oldindex_fd, rbuf, record_size);
            if (n == -1) goto fail;
        }

        close(oldindex_fd);
        r = dump_file(first, sync, pin, pout, oldname, "cyrus.expunge", NULL, 0);
        unlink(oldname);
        if (r) return r;
    }

    return 0;

fail:
    if (oldindex_fd != -1)
        close(oldindex_fd);
    unlink(oldname);

    return IMAP_IOERROR;
}
Esempio n. 3
0
/* create a downgraded index file in cyrus.index.  We don't copy back
 * expunged messages, sorry */
static int dump_index(struct mailbox *mailbox, int oldversion,
		      struct seqset *expunged_seq, int first, int sync,
		      struct protstream *pin, struct protstream *pout)
{
    char oldname[MAX_MAILBOX_PATH];
    const char *fname;
    int oldindex_fd = -1;
    indexbuffer_t headerbuf;
    indexbuffer_t recordbuf;
    char *hbuf = (char *)headerbuf.buf;
    char *rbuf = (char *)recordbuf.buf;
    int header_size;
    int record_size;
    int n, r;
    struct index_record record;
    unsigned recno;

    if (oldversion == 6) {
	header_size = 76;
	record_size = 60;
    }
    else if (oldversion == 7) {
	header_size = 76;
	record_size = 72;
    }
    else if (oldversion == 8) {
	header_size = 92;
	record_size = 80;
    }
    else if (oldversion == 9) {
	header_size = 96;
	record_size = 80;
    }
    else if (oldversion == 10) {
	header_size = 96;
	record_size = 88;
    }
    else {
	return IMAP_MAILBOX_BADFORMAT;
    }

    fname = mailbox_meta_fname(mailbox, META_INDEX);
    snprintf(oldname, MAX_MAILBOX_PATH, "%s.OLD", fname);
    
    oldindex_fd = open(oldname, O_RDWR|O_TRUNC|O_CREAT, 0666);
    if (oldindex_fd == -1) goto fail;

    downgrade_header(&mailbox->i, hbuf, oldversion,
		     header_size, record_size);

    /* Write header - everything we'll say */
    n = retry_write(oldindex_fd, hbuf, header_size);
    if (n == -1) goto fail;

    for (recno = 1; recno <= mailbox->i.num_records; recno++) {
	if (mailbox_read_index_record(mailbox, recno, &record))
	    goto fail;
	/* we don't care about unlinked records at all */
	if (record.system_flags & FLAG_UNLINKED)
	    continue;
	/* we have to make sure expunged records don't get the
	 * file copied, or a reconstruct could bring them back
	 * to life!  It we're not creating an expunged file... */
	if (record.system_flags & FLAG_EXPUNGED) {
	    if (oldversion < 9) seqset_add(expunged_seq, record.uid, 1);
	    continue;
	}
	/* not making sure exists matches, we do trust a bit */
	downgrade_record(&record, rbuf, oldversion);
	n = retry_write(oldindex_fd, rbuf, record_size);
	if (n == -1) goto fail;
    }

    close(oldindex_fd);
    r = dump_file(first, sync, pin, pout, oldname, "cyrus.index");
    unlink(oldname);
    if (r) return r;

    /* create cyrus.expunge */
    if (oldversion > 8 && mailbox->i.num_records > mailbox->i.exists) {
	int nexpunge = mailbox->i.num_records - mailbox->i.exists;
	fname = mailbox_meta_fname(mailbox, META_EXPUNGE);
	snprintf(oldname, MAX_MAILBOX_PATH, "%s.OLD", fname);
	
	oldindex_fd = open(oldname, O_RDWR|O_TRUNC|O_CREAT, 0666);
	if (oldindex_fd == -1) goto fail;

	*((bit32 *)(hbuf+OFFSET_NUM_RECORDS)) = htonl(nexpunge);

	/* Write header - everything we'll say */
	n = retry_write(oldindex_fd, hbuf, header_size);
	if (n == -1) goto fail;

	for (recno = 1; recno <= mailbox->i.num_records; recno++) {
	    if (mailbox_read_index_record(mailbox, recno, &record))
		goto fail;
	    /* ignore non-expunged records */
	    if (!(record.system_flags & FLAG_EXPUNGED))
		continue;
	    downgrade_record(&record, rbuf, oldversion);
	    n = retry_write(oldindex_fd, rbuf, record_size);
	    if (n == -1) goto fail;
	}

	close(oldindex_fd);
	r = dump_file(first, sync, pin, pout, oldname, "cyrus.expunge");
	unlink(oldname);
	if (r) return r;
    }

    return 0;

fail:
    if (oldindex_fd != -1)
	close(oldindex_fd);
    unlink(oldname);

    return IMAP_IOERROR;
}
Esempio n. 4
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;
}