/* * 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; }
/* * mboxlist_findall() callback function to examine a mailbox */ static int do_timestamp(const char *name) { int r = 0; char ext_name_buf[MAX_MAILBOX_PATH+1]; struct mailbox *mailbox = NULL; const 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; struct mailbox_iter *iter = mailbox_iter_init(mailbox, 0, ITER_SKIP_EXPUNGED); while ((record = mailbox_iter_step(iter))) { /* 1 day is close enough */ if (labs(record->internaldate - record->gmtime) < 86400) continue; struct index_record copyrecord = *record; time_to_rfc822(copyrecord.internaldate, olddate, sizeof(olddate)); time_to_rfc822(copyrecord.gmtime, newdate, sizeof(newdate)); printf(" %u: %s => %s\n", copyrecord.uid, olddate, newdate); /* switch internaldate */ copyrecord.internaldate = copyrecord.gmtime; r = mailbox_rewrite_index_record(mailbox, ©record); if (r) goto done; } done: mailbox_iter_done(&iter); mailbox_close(&mailbox); return r; }
* (-1 means don't care about quota) * event_type - the event among MessageNew, MessageAppend and * vnd.cmu.MessageCopy (zero means don't send notification) * On success, the struct pointed to by 'as' is set up. * * when you commit or abort, the mailbox is closed */ EXPORTED int append_setup(struct appendstate *as, const char *name, const char *userid, const struct auth_state *auth_state, long aclcheck, const quota_t quotacheck[QUOTA_NUMRESOURCES], const struct namespace *namespace, int isadmin, enum event_type event_type) { int r; struct mailbox *mailbox = NULL; r = mailbox_open_iwl(name, &mailbox); if (r) return r; r = append_setup_mbox(as, mailbox, userid, auth_state, aclcheck, quotacheck, namespace, isadmin, event_type); if (r) mailbox_close(&mailbox); else as->close_mailbox_when_done = 1; return r; } /* setup for append with an existing mailbox * * same as append_setup, but when you commit, the mailbox remains open and locked. * * Requires as write locked mailbox (of course)
int main(int argc, char *argv[]) { extern char *optarg; int opt, r = 0; char *alt_config = NULL, *intname = NULL, *extname = NULL; struct mailbox *mailbox = NULL; int mode = MODE_UNKNOWN; unsigned numrestored = 0; time_t time_since = time(NULL); int len, secs = 0; unsigned long *uids = NULL; unsigned nuids = 0; while ((opt = getopt(argc, argv, "C:laudt:f:v")) != EOF) { switch (opt) { case 'C': /* alt config file */ alt_config = optarg; break; case 'l': if (mode != MODE_UNKNOWN) usage(); mode = MODE_LIST; break; case 'a': if (mode != MODE_UNKNOWN) usage(); mode = MODE_ALL; break; case 't': if (mode != MODE_UNKNOWN) usage(); mode = MODE_TIME; secs = atoi(optarg); len = strlen(optarg); if ((secs > 0) && (len > 1)) { switch (optarg[len-1]) { case 'm': secs *= 60; break; case 'h': secs *= (60*60); break; case 'd': secs *= (24*60*60); break; case 'w': secs *= (7*24*60*60); break; } } time_since = time(NULL) - secs; break; case 'u': if (mode != MODE_UNKNOWN) usage(); mode = MODE_UID; break; case 'd': unsetdeleted = 1; break; case 'f': addflag = optarg; break; case 'v': verbose = 1; break; default: usage(); break; } } /* sanity check */ if (mode == MODE_UNKNOWN || (optind + (mode == MODE_UID ? 1 : 0)) >= argc) usage(); cyrus_init(alt_config, "unexpunge", 0, 0); sync_log_init(); if (addflag && addflag[0] == '\\') { syslog(LOG_ERR, "can't set a system flag"); fatal("can't set a system flag", EX_SOFTWARE); } /* Set namespace -- force standard (internal) */ if ((r = mboxname_init_namespace(&unex_namespace, 1)) != 0) { syslog(LOG_ERR, "%s", error_message(r)); fatal(error_message(r), EX_CONFIG); } /* Translate mailboxname */ intname = mboxname_from_external(argv[optind], &unex_namespace, NULL); if (mode == MODE_LIST) { list_expunged(intname); goto done; } /* Open/lock header */ r = mailbox_open_iwl(intname, &mailbox); if (r) { printf("Failed to open mailbox '%s'\n", intname); goto done; } if (mode == MODE_UID) { unsigned i; nuids = argc - ++optind; uids = (unsigned long *) xmalloc(nuids * sizeof(unsigned long)); for (i = 0; i < nuids; i++) uids[i] = strtoul(argv[optind+i], NULL, 10); /* Sort the UIDs so we can binary search */ qsort(uids, nuids, sizeof(unsigned long), compare_uid); } extname = mboxname_to_external(intname, &unex_namespace, NULL); printf("restoring %sexpunged messages in mailbox '%s'\n", mode == MODE_ALL ? "all " : "", extname); r = restore_expunged(mailbox, mode, uids, nuids, time_since, &numrestored, extname); if (!r) { printf("restored %u expunged messages\n", numrestored); syslog(LOG_NOTICE, "restored %u expunged messages in mailbox '%s'", numrestored, extname); } mailbox_close(&mailbox); done: free(intname); free(extname); sync_log_done(); cyrus_done(); exit(r); }
/* * 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; }
int main(int argc, char *argv[]) { extern char *optarg; int opt, r = 0; char *alt_config = NULL; char buf[MAX_MAILBOX_PATH+1]; struct mailbox *mailbox = NULL; int mode = MODE_UNKNOWN; unsigned numrestored = 0; time_t time_since = time(NULL); int len, secs = 0; unsigned long *uids = NULL; unsigned nuids = 0; char *mboxname = NULL; if ((geteuid()) == 0 && (become_cyrus(/*is_master*/0) != 0)) { fatal("must run as the Cyrus user", EC_USAGE); } while ((opt = getopt(argc, argv, "C:laudt:v")) != EOF) { switch (opt) { case 'C': /* alt config file */ alt_config = optarg; break; case 'l': if (mode != MODE_UNKNOWN) usage(); mode = MODE_LIST; break; case 'a': if (mode != MODE_UNKNOWN) usage(); mode = MODE_ALL; break; case 't': if (mode != MODE_UNKNOWN) usage(); mode = MODE_TIME; secs = atoi(optarg); len = strlen(optarg); if ((secs > 0) && (len > 1)) { switch (optarg[len-1]) { case 'm': secs *= 60; break; case 'h': secs *= (60*60); break; case 'd': secs *= (24*60*60); break; case 'w': secs *= (7*24*60*60); break; } } time_since = time(NULL) - secs; break; case 'u': if (mode != MODE_UNKNOWN) usage(); mode = MODE_UID; break; case 'd': unsetdeleted = 1; break; case 'v': verbose = 1; break; default: usage(); break; } } /* sanity check */ if (mode == MODE_UNKNOWN || (optind + (mode == MODE_UID ? 1 : 0)) >= argc) usage(); cyrus_init(alt_config, "unexpunge", 0, 0); mboxlist_init(0); mboxlist_open(NULL); quotadb_init(0); quotadb_open(NULL); sync_log_init(); /* Set namespace -- force standard (internal) */ if ((r = mboxname_init_namespace(&unex_namespace, 1)) != 0) { syslog(LOG_ERR, "%s", error_message(r)); fatal(error_message(r), EC_CONFIG); } /* Translate mailboxname */ (*unex_namespace.mboxname_tointernal)(&unex_namespace, argv[optind], NULL, buf); if (mode == MODE_LIST) { list_expunged(buf); goto done; } /* Open/lock header */ r = mailbox_open_iwl(buf, &mailbox); if (r) { printf("Failed to open mailbox '%s'\n", buf); goto done; } if (mode == MODE_UID) { unsigned i; nuids = argc - ++optind; uids = (unsigned long *) xmalloc(nuids * sizeof(unsigned long)); for (i = 0; i < nuids; i++) uids[i] = strtoul(argv[optind+i], NULL, 10); /* Sort the UIDs so we can binary search */ qsort(uids, nuids, sizeof(unsigned long), compare_uid); } mboxname = xstrdup(mailbox->name); mboxname_hiersep_toexternal(&unex_namespace, mboxname, 0); printf("restoring %sexpunged messages in mailbox '%s'\n", mode == MODE_ALL ? "all " : "", mboxname); r = restore_expunged(mailbox, mode, uids, nuids, time_since, &numrestored, mboxname); if (!r) { printf("restored %u expunged messages\n", numrestored); syslog(LOG_NOTICE, "restored %u expunged messages in mailbox '%s'", numrestored, mboxname); } mailbox_close(&mailbox); done: sync_log_done(); quotadb_close(); quotadb_done(); mboxlist_close(); mboxlist_done(); cyrus_done(); exit(r); }