コード例 #1
0
ファイル: mbtool.c プロジェクト: pmhahn/cyrus-imapd
/*
 * mboxlist_findall() callback function to examine a mailbox
 */
static int do_timestamp(char *name)
{
    unsigned recno;
    int r = 0;
    char ext_name_buf[MAX_MAILBOX_PATH+1];
    struct mailbox *mailbox = NULL;
    struct index_record record;
    char olddate[RFC822_DATETIME_MAX+1];
    char newdate[RFC822_DATETIME_MAX+1];

    signals_poll();

    /* Convert internal name to external */
    (*recon_namespace.mboxname_toexternal)(&recon_namespace, name,
					   "cyrus", ext_name_buf);
    printf("Working on %s...\n", ext_name_buf);

    /* Open/lock header */
    r = mailbox_open_iwl(name, &mailbox);
    if (r) return r;

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

	if (record.system_flags & FLAG_EXPUNGED)
	    continue;

	/* 1 day is close enough */
	if (abs(record.internaldate - record.gmtime) < 86400)
	    continue;

	time_to_rfc822(record.internaldate, olddate, sizeof(olddate));
	time_to_rfc822(record.gmtime, newdate, sizeof(newdate));
	printf("  %u: %s => %s\n", record.uid, olddate, newdate);

	/* switch internaldate */
	record.internaldate = record.gmtime;

	r = mailbox_rewrite_index_record(mailbox, &record);
	if (r) goto done;
    }

 done:
    mailbox_close(&mailbox);

    return r;
}
コード例 #2
0
ファイル: statuscache_db.c プロジェクト: gnb/cyrus-imapd
/*
 * Performs a STATUS command - note: state MAY be NULL here.
 */
int status_lookup(const char *mboxname, const char *userid,
		  unsigned statusitems, struct statusdata *sdata)
{
    struct mailbox *mailbox = NULL;
    unsigned numrecent = 0;
    unsigned numunseen = 0;
    unsigned c_statusitems;
    int r;

    /* Check status cache if possible */
    if (config_getswitch(IMAPOPT_STATUSCACHE)) {
	/* Do actual lookup of cache item. */
	r = statuscache_lookup(mboxname, userid, statusitems, sdata);

	/* Seen/recent status uses "push" invalidation events from
	 * seen_db.c.   This avoids needing to open cyrus.header to get
	 * the mailbox uniqueid to open the seen db and get the
	 * unseen_mtime and recentuid.
	 */

	if (!r) {
	    syslog(LOG_DEBUG, "statuscache, '%s', '%s', '0x%02x', 'yes'",
		   mboxname, userid, statusitems);
	    return 0;
	}

	syslog(LOG_DEBUG, "statuscache, '%s', '%s', '0x%02x', 'no'",
	       mboxname, userid, statusitems);
    }

    /* Missing or invalid cache entry */
    r = mailbox_open_irl(mboxname, &mailbox);
    if (r) return r;

    /* We always have message count, uidnext,
       uidvalidity, and highestmodseq for cache */
     c_statusitems = STATUS_MESSAGES | STATUS_UIDNEXT |
		     STATUS_UIDVALIDITY | STATUS_HIGHESTMODSEQ;

    if (!mailbox->i.exists) {
	/* no messages, so these two must also be zero */
	c_statusitems |= STATUS_RECENT | STATUS_UNSEEN;
    }
    else if (statusitems & (STATUS_RECENT | STATUS_UNSEEN)) {
	/* Read \Seen state */
	struct seqset *seq = NULL;
	uint32_t recno;
	struct index_record record;
	int internalseen = mailbox_internal_seen(mailbox, userid);
	unsigned recentuid;

	if (internalseen) {
	    recentuid = mailbox->i.recentuid;
	} else {
	    struct seen *seendb = NULL;
	    struct seendata sd = SEENDATA_INITIALIZER;

	    r = seen_open(userid, SEEN_CREATE, &seendb);
	    if (!r) r = seen_read(seendb, mailbox->uniqueid, &sd);
	    seen_close(&seendb);
	    if (r) goto done;

	    recentuid = sd.lastuid;
	    seq = seqset_parse(sd.seenuids, NULL, recentuid);
	    seen_freedata(&sd);
	}

	for (recno = 1; recno <= mailbox->i.num_records; recno++) {
	    if (mailbox_read_index_record(mailbox, recno, &record))
		continue;
	    if (record.system_flags & FLAG_EXPUNGED)
		continue;
	    if (record.uid > recentuid)
		numrecent++;
	    if (internalseen) {
		if (!(record.system_flags & FLAG_SEEN))
		    numunseen++;
	    }
	    else {
		if (!seqset_ismember(seq, record.uid))
		    numunseen++;
	    }
	}

	/* we've calculated the correct values for both */
	c_statusitems |= STATUS_RECENT | STATUS_UNSEEN;
    }

    statuscache_fill(sdata, userid, mailbox, c_statusitems,
		     numrecent, numunseen);

    /* cache the new value while unlocking */
    mailbox_unlock_index(mailbox, sdata);

  done:
    mailbox_close(&mailbox);
    return r;
}
コード例 #3
0
ファイル: mbdump.c プロジェクト: gnb/cyrus-imapd
/* 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", 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;

	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", NULL, 0);
	unlink(oldname);
	if (r) return r;
    }

    return 0;

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

    return IMAP_IOERROR;
}
コード例 #4
0
ファイル: unexpunge.c プロジェクト: sebmichel/cyrus-imapd
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;
}
コード例 #5
0
ファイル: unexpunge.c プロジェクト: sebmichel/cyrus-imapd
static void list_expunged(const char *mboxname)
{
    struct mailbox *mailbox = NULL;
    struct index_record *records = NULL;
    struct index_record *record;
    uint32_t recno;
    int alloc = 0;
    int num = 0;
    int i;
    int r;

    r = mailbox_open_irl(mboxname, &mailbox);
    if (r) {
	printf("Failed to open mailbox %s: %s",
	       mboxname, error_message(r));
	return;
    }

    /* first pass - read the records.  Don't print until we release the
     * lock */
    for (recno = 1; recno <= mailbox->i.num_records; recno++) {
	/* pre-allocate more space */
	if (alloc <= num) {
	    alloc += 64;
	    records = xrealloc(records, sizeof(struct index_record) * alloc);
	}
	record = &records[num];

	if (mailbox_read_index_record(mailbox, recno, record))
	    continue;

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

	num++;
    }

    mailbox_unlock_index(mailbox, NULL);

    for (i = 0; i < num; i++) {
	record = &records[i];
	printf("UID: %u\n", record->uid);
	printf("\tSize: %u\n", record->size);
	printf("\tSent: %s", ctime(&record->sentdate));
	printf("\tRecv: %s", ctime(&record->internaldate));
	printf("\tExpg: %s", ctime(&record->last_updated));

	if (mailbox_cacherecord(mailbox, record)) {
	    printf("\tERROR: cache record missing or corrupt, "
		   "not printing cache details\n\n");
	    continue;
	}

	printf("\tFrom: %.*s\n", cacheitem_size(record, CACHE_FROM),
		cacheitem_base(record, CACHE_FROM));
	printf("\tTo  : %.*s\n", cacheitem_size(record, CACHE_TO),
		cacheitem_base(record, CACHE_TO));
	printf("\tCc  : %.*s\n", cacheitem_size(record, CACHE_CC),
		cacheitem_base(record, CACHE_CC));
	printf("\tBcc : %.*s\n", cacheitem_size(record, CACHE_BCC),
		cacheitem_base(record, CACHE_BCC));
	printf("\tSubj: %.*s\n\n", cacheitem_size(record, CACHE_SUBJECT),
		cacheitem_base(record, CACHE_SUBJECT));
    }

    free(records);
    mailbox_close(&mailbox);
}