On Wed, Jun 08, 2016 at 09:39:21AM +1000, Bron Gondwana via Cyrus-devel wrote:
> Looks good to me. It's perfectly safe to load the cache data as well if we
> want to extend it to have more information later, but it's definitely worth
> having. I'd say it's a candidate for 2.5 and master.
Great, I'm sending an updated patch using the cache info. It also fixes the
stats capitalization for total.
--
Valentin
diff --git a/docsrc/imap/admin/systemcommands/ipurge.rst b/docsrc/imap/admin/systemcommands/ipurge.rst
index 6ac5fde..84ccf80 100644
--- a/docsrc/imap/admin/systemcommands/ipurge.rst
+++ b/docsrc/imap/admin/systemcommands/ipurge.rst
@@ -13,7 +13,7 @@ Synopsis
.. parsed-literal::
- **ipurge** [ **-f** ] [ **-C** *config-file* ] [ **-x** ] [ **-X** ] [ **-i** ] [ **-s** ] [ **-o** ]
+ **ipurge** [ **-f** ] [ **-C** *config-file* ] [ **-x** ] [ **-X** ] [ **-i** ] [ **-s** ] [ **-o** ] [ **-n** ]
[ **-d** *days* | **-b** *bytes* | **-k** *Kbytes* | **-m** *Mbytes* ]
[ *mailbox-pattern*... ]
@@ -85,6 +85,10 @@ Options
Only purge messages that have the \\Deleted flag set.
+.. option:: -n
+
+ Only print messages that would be deleted (dry run).
+
Examples
========
diff --git a/imap/ipurge.c b/imap/ipurge.c
index 07b6382..100b663 100644
--- a/imap/ipurge.c
+++ b/imap/ipurge.c
@@ -91,6 +91,7 @@ typedef struct mbox_stats_s {
} mbox_stats_t;
+static int dryrun = 0;
static int verbose = 1;
static int forceall = 0;
@@ -99,6 +100,8 @@ static unsigned purge_check(struct mailbox *mailbox,
const struct index_record *record,
void *rock);
static int usage(const char *name);
+static void print_record(struct mailbox *mailbox,
+ const struct index_record *record);
static void print_stats(mbox_stats_t *stats);
int main (int argc, char *argv[]) {
@@ -109,7 +112,7 @@ int main (int argc, char *argv[]) {
fatal("must run as the Cyrus user", EC_USAGE);
}
- while ((option = getopt(argc, argv, "C:hxd:b:k:m:fsXio")) != EOF) {
+ while ((option = getopt(argc, argv, "C:hxd:b:k:m:fsXion")) != EOF) {
switch (option) {
case 'C': /* alt config file */
alt_config = optarg;
@@ -138,6 +141,9 @@ int main (int argc, char *argv[]) {
}
size = atoi(optarg) * 1048576; /* 1024 * 1024 */
} break;
+ case 'n' : {
+ dryrun = 1;
+ } break;
case 'x' : {
exact = 1;
} break;
@@ -207,7 +213,7 @@ int main (int argc, char *argv[]) {
static int usage(const char *name)
{
- printf("usage: %s [-f] [-s] [-C <alt_config>] [-x] [-X] [-i] [-o] {-d days | -b bytes|-k Kbytes|-m Mbytes}\n\t[mboxpattern1 ... [mboxpatternN]]\n", name);
+ printf("usage: %s [-f] [-s] [-C <alt_config>] [-x] [-X] [-i] [-o] [-n] {-d days | -b bytes|-k Kbytes|-m Mbytes}\n\t[mboxpattern1 ... [mboxpatternN]]\n", name);
printf("\tthere are no defaults and at least one of -d, -b, -k, -m\n\tmust be specified\n");
printf("\tif no mboxpattern is given %s works on all mailboxes\n", name);
printf("\t -x specifies an exact match for days or size\n");
@@ -216,6 +222,7 @@ static int usage(const char *name)
printf("\t -X use delivery time instead of date header for date matches.\n");
printf("\t -i invert match logic: -x means not equal, date is for newer, size is for smaller.\n");
printf("\t -o only purge messages that are deleted.\n");
+ printf("\t -n only print messages that would be deleted (dry run).\n");
exit(0);
}
@@ -263,7 +270,7 @@ static void deleteit(bit32 msgsize, mbox_stats_t *stats)
/* thumbs up routine, checks date & size and returns yes or no for deletion */
/* 0 = no, 1 = yes */
-static unsigned purge_check(struct mailbox *mailbox __attribute__((unused)),
+static unsigned purge_check(struct mailbox *mailbox,
const struct index_record *record,
void *deciderock)
{
@@ -289,11 +296,11 @@ static unsigned purge_check(struct mailbox *mailbox __attribute__((unused)),
if (((my_time - (time_t) senttime)/86400) == (days/86400)) {
if (invertmatch) return 0;
deleteit(record->size, stats);
- return 1;
+ return dryrun ? print_record(mailbox, record), 0 : 1;
} else {
if (!invertmatch) return 0;
deleteit(record->size, stats);
- return 1;
+ return dryrun ? print_record(mailbox, record), 0 : 1;
}
}
if (size >= 0) {
@@ -301,11 +308,11 @@ static unsigned purge_check(struct mailbox *mailbox __attribute__((unused)),
if (record->size == (unsigned)size) {
if (invertmatch) return 0;
deleteit(record->size, stats);
- return 1;
+ return dryrun ? print_record(mailbox, record), 0 : 1;
} else {
if (!invertmatch) return 0;
deleteit(record->size, stats);
- return 1;
+ return dryrun ? print_record(mailbox, record), 0 : 1;
}
}
return 0;
@@ -314,32 +321,58 @@ static unsigned purge_check(struct mailbox *mailbox __attribute__((unused)),
/* printf("comparing %ld :: %ld\n", my_time, the_record->sentdate); */
if (!invertmatch && ((my_time - (time_t) senttime) > days)) {
deleteit(record->size, stats);
- return 1;
+ return dryrun ? print_record(mailbox, record), 0 : 1;
}
if (invertmatch && ((my_time - (time_t) senttime) < days)) {
deleteit(record->size, stats);
- return 1;
+ return dryrun ? print_record(mailbox, record), 0 : 1;
}
}
if (size >= 0) {
/* check size */
if (!invertmatch && ((int) record->size > size)) {
deleteit(record->size, stats);
- return 1;
+ return dryrun ? print_record(mailbox, record), 0 : 1;
}
if (invertmatch && ((int) record->size < size)) {
deleteit(record->size, stats);
- return 1;
+ return dryrun ? print_record(mailbox, record), 0 : 1;
}
}
return 0;
}
}
+static void print_record(struct mailbox *mailbox,
+ const struct index_record *record)
+{
+ printf("UID: %u\n", record->uid);
+ printf("\tSize: %u\n", record->size);
+ printf("\tSent: %s", ctime(&record->sentdate));
+ printf("\tRecv: %s", ctime(&record->internaldate));
+
+ if (mailbox_cacherecord(mailbox, record)) {
+ printf("\tERROR: cache record missing or corrupt, "
+ "not printing cache details\n\n");
+ return;
+ }
+
+ 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));
+}
+
static void print_stats(mbox_stats_t *stats)
{
- printf("total messages \t\t %d\n",stats->total);
- printf("total bytes \t\t %d\n",stats->total_bytes);
+ printf("Total messages \t\t %d\n",stats->total);
+ printf("Total bytes \t\t %d\n",stats->total_bytes);
printf("Deleted messages \t\t %d\n",stats->deleted);
printf("Deleted bytes \t\t %d\n",stats->deleted_bytes);
printf("Remaining messages\t\t %d\n",stats->total - stats->deleted);