Commit 74b2971a 74b2971a50804a51f83bea8c49648fe9d2b344c4 by Sergey Poznyakoff

Gracefully handle empty mailboxes in mu_msgset_parse_imap

* libmailutils/msgset/parse.c (MU_MSGSET_EMPTY): New constant.
(parse_msgrange): Don't add any ranges if mode is set to
MU_MSGSET_EMPTY.
(mu_msgset_parse_imap): Force MU_MSGSET_EMPTY mode if the mailbox
is empty.
* libmailutils/msgset/print.c (mu_msgset_print): Handle empty message
sets.
* libmailutils/msgset/trans.c (_mu_msgset_translate_pair): Initialize
variable.
* libmailutils/tests/Makefile.am (msgset_LDADD): New variable.
* libmailutils/tests/msgset.c (parse_msgset): Take mailbox as first
argument.
(main): New option -mailbox
1 parent 561ce8ff
...@@ -26,6 +26,9 @@ ...@@ -26,6 +26,9 @@
26 #include <mailutils/msgset.h> 26 #include <mailutils/msgset.h>
27 #include <mailutils/sys/msgset.h> 27 #include <mailutils/sys/msgset.h>
28 28
29 /* Special translation mode, indicating that the mailbox is empty */
30 #define MU_MSGSET_EMPTY -1
31
29 /* This structure keeps parser state while parsing message set. */ 32 /* This structure keeps parser state while parsing message set. */
30 struct parse_msgnum_env 33 struct parse_msgnum_env
31 { 34 {
...@@ -33,7 +36,7 @@ struct parse_msgnum_env ...@@ -33,7 +36,7 @@ struct parse_msgnum_env
33 size_t minval; /* Min. sequence number or UID */ 36 size_t minval; /* Min. sequence number or UID */
34 size_t maxval; /* Max. sequence number or UID */ 37 size_t maxval; /* Max. sequence number or UID */
35 mu_msgset_t msgset; /* Message set being built. */ 38 mu_msgset_t msgset; /* Message set being built. */
36 int mode; /* Operation mode (num/uid) */ 39 int mode; /* Operation mode (num/uid/dry_run) */
37 }; 40 };
38 41
39 /* Get a single message number/UID from env->s and store it into *PN. 42 /* Get a single message number/UID from env->s and store it into *PN.
...@@ -96,6 +99,8 @@ parse_msgrange (struct parse_msgnum_env *env) ...@@ -96,6 +99,8 @@ parse_msgrange (struct parse_msgnum_env *env)
96 msgrange.msg_beg = tmp; 99 msgrange.msg_beg = tmp;
97 } 100 }
98 101
102 if (env->mode == MU_MSGSET_EMPTY)
103 return 0;
99 return mu_msgset_add_range (env->msgset, msgrange.msg_beg, msgrange.msg_end, 104 return mu_msgset_add_range (env->msgset, msgrange.msg_beg, msgrange.msg_end,
100 env->mode); 105 env->mode);
101 } 106 }
...@@ -131,7 +136,11 @@ mu_msgset_parse_imap (mu_msgset_t mset, int mode, const char *s, char **end) ...@@ -131,7 +136,11 @@ mu_msgset_parse_imap (mu_msgset_t mset, int mode, const char *s, char **end)
131 rc = mu_mailbox_messages_count (mset->mbox, &lastmsgno); 136 rc = mu_mailbox_messages_count (mset->mbox, &lastmsgno);
132 if (rc == 0) 137 if (rc == 0)
133 { 138 {
134 if (mode == MU_MSGSET_UID) 139 if (lastmsgno == 0)
140 {
141 env.mode = MU_MSGSET_EMPTY;
142 }
143 else if (mode == MU_MSGSET_UID)
135 { 144 {
136 rc = mu_mailbox_translate (mset->mbox, MU_MAILBOX_MSGNO_TO_UID, 145 rc = mu_mailbox_translate (mset->mbox, MU_MAILBOX_MSGNO_TO_UID,
137 lastmsgno, &env.maxval); 146 lastmsgno, &env.maxval);
......
...@@ -64,7 +64,7 @@ mu_msgset_print (mu_stream_t str, mu_msgset_t mset) ...@@ -64,7 +64,7 @@ mu_msgset_print (mu_stream_t str, mu_msgset_t mset)
64 int rc; 64 int rc;
65 65
66 if (mu_list_is_empty (mset->list)) 66 if (mu_list_is_empty (mset->list))
67 return MU_ERR_NOENT; 67 return mu_stream_printf (str, "%s", "nil");
68 rc = mu_msgset_aggregate (mset); 68 rc = mu_msgset_aggregate (mset);
69 if (rc) 69 if (rc)
70 return rc; 70 return rc;
......
...@@ -30,7 +30,7 @@ _mu_msgset_translate_pair (mu_msgset_t mset, int mode, ...@@ -30,7 +30,7 @@ _mu_msgset_translate_pair (mu_msgset_t mset, int mode,
30 if (mode != _MU_MSGSET_MODE (mset->flags) && mset->mbox) 30 if (mode != _MU_MSGSET_MODE (mset->flags) && mset->mbox)
31 { 31 {
32 int cmd, rc; 32 int cmd, rc;
33 size_t n; 33 size_t n = 1;
34 size_t beg = *pbeg; 34 size_t beg = *pbeg;
35 size_t end = *pend; 35 size_t end = *pend;
36 36
......
...@@ -69,6 +69,12 @@ noinst_PROGRAMS = \ ...@@ -69,6 +69,12 @@ noinst_PROGRAMS = \
69 69
70 LDADD = ${MU_LIB_MAILUTILS} 70 LDADD = ${MU_LIB_MAILUTILS}
71 71
72 msgset_LDADD = \
73 ${MU_LIB_MBOX}\
74 ${MU_LIB_MH}\
75 ${MU_LIB_MAILDIR}\
76 ${MU_LIB_MAILUTILS}
77
72 EXTRA_DIST += Encode Decode Wicketfile 78 EXTRA_DIST += Encode Decode Wicketfile
73 79
74 ## ------------ ## 80 ## ------------ ##
......
...@@ -53,16 +53,16 @@ parse_msgrange (char *arg, struct mu_msgrange *range) ...@@ -53,16 +53,16 @@ parse_msgrange (char *arg, struct mu_msgrange *range)
53 } 53 }
54 54
55 mu_msgset_t 55 mu_msgset_t
56 parse_msgset (const char *arg) 56 parse_msgset (mu_mailbox_t mbox, const char *arg)
57 { 57 {
58 int rc; 58 int rc;
59 mu_msgset_t msgset; 59 mu_msgset_t msgset;
60 char *end; 60 char *end;
61 61
62 MU_ASSERT (mu_msgset_create (&msgset, NULL, MU_MSGSET_NUM)); 62 MU_ASSERT (mu_msgset_create (&msgset, mbox, MU_MSGSET_NUM));
63 if (arg) 63 if (arg)
64 { 64 {
65 rc = mu_msgset_parse_imap (msgset, MU_MSGSET_NUM, arg, &end); 65 rc = mu_msgset_parse_imap (msgset, MU_MSGSET_UID, arg, &end);
66 if (rc) 66 if (rc)
67 { 67 {
68 mu_error ("mu_msgset_parse_imap: %s near %s", 68 mu_error ("mu_msgset_parse_imap: %s near %s",
...@@ -79,26 +79,33 @@ main (int argc, char **argv) ...@@ -79,26 +79,33 @@ main (int argc, char **argv)
79 int i; 79 int i;
80 char *msgset_string = NULL; 80 char *msgset_string = NULL;
81 mu_msgset_t msgset; 81 mu_msgset_t msgset;
82 mu_mailbox_t mbox = NULL;
82 83
83 mu_set_program_name (argv[0]); 84 mu_set_program_name (argv[0]);
85 mu_register_local_mbox_formats ();
84 for (i = 1; i < argc; i++) 86 for (i = 1; i < argc; i++)
85 { 87 {
86 char *arg = argv[i]; 88 char *arg = argv[i];
87 89
88 if (strcmp (arg, "-h") == 0 || strcmp (arg, "-help") == 0) 90 if (strcmp (arg, "-h") == 0 || strcmp (arg, "-help") == 0)
89 { 91 {
90 mu_printf ("usage: %s [-msgset=SET] [-add=X[:Y]] [-del=X[:Y]] " 92 mu_printf ("usage: %s [-mailbox=PATH] [-msgset=SET] [-add=X[:Y]] [-del=X[:Y]] "
91 "[-addset=SET] [-delset=SET] ...\n", 93 "[-addset=SET] [-delset=SET] ...\n",
92 mu_program_name); 94 mu_program_name);
93 return 0; 95 return 0;
94 } 96 }
95 else if (strncmp (arg, "-msgset=", 8) == 0) 97 else if (strncmp (arg, "-msgset=", 8) == 0)
96 msgset_string = arg + 8; 98 msgset_string = arg + 8;
99 else if (strncmp (arg, "-mailbox=", 9) == 0)
100 {
101 MU_ASSERT (mu_mailbox_create_default (&mbox, arg + 9));
102 MU_ASSERT (mu_mailbox_open (mbox, MU_STREAM_READ));
103 }
97 else 104 else
98 break; 105 break;
99 } 106 }
100 107
101 msgset = parse_msgset (msgset_string); 108 msgset = parse_msgset (mbox, msgset_string);
102 109
103 for (; i < argc; i++) 110 for (; i < argc; i++)
104 { 111 {
...@@ -119,7 +126,7 @@ main (int argc, char **argv) ...@@ -119,7 +126,7 @@ main (int argc, char **argv)
119 } 126 }
120 else if (strncmp (arg, "-addset=", 8) == 0) 127 else if (strncmp (arg, "-addset=", 8) == 0)
121 { 128 {
122 mu_msgset_t tset = parse_msgset (arg + 8); 129 mu_msgset_t tset = parse_msgset (mbox, arg + 8);
123 if (!msgset) 130 if (!msgset)
124 msgset = tset; 131 msgset = tset;
125 else 132 else
...@@ -130,7 +137,7 @@ main (int argc, char **argv) ...@@ -130,7 +137,7 @@ main (int argc, char **argv)
130 } 137 }
131 else if (strncmp (arg, "-subset=", 8) == 0) 138 else if (strncmp (arg, "-subset=", 8) == 0)
132 { 139 {
133 mu_msgset_t tset = parse_msgset (arg + 8); 140 mu_msgset_t tset = parse_msgset (mbox, arg + 8);
134 if (!msgset) 141 if (!msgset)
135 { 142 {
136 mu_error ("no initial message set"); 143 mu_error ("no initial message set");
......