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);

Reply via email to