23
23
last_io = I_MAX(client->last_input, client->last_output);
24
24
if (now - last_io > MAIL_STORAGE_STAYALIVE_SECS) {
25
o_stream_send_str(client->output, "* OK Hang in there..\r\n");
26
o_stream_flush(client->output);
25
o_stream_nsend_str(client->output, "* OK Hang in there..\r\n");
26
o_stream_nflush(client->output);
27
27
client->last_output = now;
31
static int fetch_and_copy(struct client *client,
31
static int fetch_and_copy(struct client *client, bool move,
32
32
struct mailbox_transaction_context *t,
33
struct mailbox_transaction_context **src_trans_r,
33
34
struct mail_search_args *search_args,
34
35
const char **src_uidset_r,
35
36
unsigned int *copy_count_r)
62
63
save_ctx = mailbox_save_alloc(t);
63
64
mailbox_save_copy_flags(save_ctx, mail);
65
if (mailbox_copy(&save_ctx, mail) < 0)
66
ret = mail->expunged ? 0 : -1;
67
if (mailbox_move(&save_ctx, mail) < 0)
70
if (mailbox_copy(&save_ctx, mail) < 0)
73
if (ret < 0 && mail->expunged)
68
76
msgset_generator_next(&srcset_ctx, mail->uid);
72
80
if (mailbox_search_deinit(&search_ctx) < 0)
75
if (mailbox_transaction_commit(&src_trans) < 0)
83
*src_trans_r = src_trans;
78
84
*src_uidset_r = str_c(src_uidset);
79
85
*copy_count_r = copy_count;
83
bool cmd_copy(struct client_command_context *cmd)
89
static bool cmd_copy_full(struct client_command_context *cmd, bool move)
85
91
struct client *client = cmd->client;
86
92
struct mail_storage *dest_storage;
87
93
struct mailbox *destbox;
88
struct mailbox_transaction_context *t;
94
struct mailbox_transaction_context *t, *src_trans;
89
95
struct mail_search_args *search_args;
90
96
const char *messageset, *mailbox, *src_uidset;
91
97
enum mailbox_sync_flags sync_flags = 0;
114
120
t = mailbox_transaction_begin(destbox,
115
121
MAILBOX_TRANSACTION_FLAG_EXTERNAL |
116
122
MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS);
117
ret = fetch_and_copy(client, t, search_args, &src_uidset, ©_count);
123
ret = fetch_and_copy(client, move, t, &src_trans, search_args,
124
&src_uidset, ©_count);
118
125
mail_search_args_unref(&search_args);
120
127
msg = t_str_new(256);
122
129
mailbox_transaction_rollback(&t);
123
else if (mailbox_transaction_commit_get_changes(&t, &changes) < 0)
125
else if (copy_count == 0) {
126
str_append(msg, "OK No messages copied.");
127
pool_unref(&changes.pool);
128
} else if (seq_range_count(&changes.saved_uids) == 0) {
129
/* not supported by backend (virtual) */
130
str_append(msg, "OK Copy completed.");
130
else if (mailbox_transaction_commit_get_changes(&t, &changes) < 0) {
131
if (mailbox_get_last_mail_error(destbox) == MAIL_ERROR_EXPUNGED) {
132
/* storage backend didn't notice the expunge until
138
} else if (copy_count == 0) {
139
str_append(msg, "OK No messages found.");
140
pool_unref(&changes.pool);
141
} else if (seq_range_count(&changes.saved_uids) == 0 ||
142
changes.no_read_perm) {
143
/* not supported by backend (virtual) or no read permissions
145
str_append(msg, move ? "OK Move completed." :
146
"OK Copy completed.");
147
pool_unref(&changes.pool);
149
i_assert(copy_count == seq_range_count(&changes.saved_uids));
151
str_printfa(msg, "* OK [COPYUID %u %s ",
152
changes.uid_validity, src_uidset);
153
imap_write_seq_range(msg, &changes.saved_uids);
154
str_append(msg, "] Moved UIDs.");
155
client_send_line(client, str_c(msg));
157
str_truncate(msg, 0);
158
str_append(msg, "OK Move completed.");
131
159
pool_unref(&changes.pool);
133
161
i_assert(copy_count == seq_range_count(&changes.saved_uids));
139
167
pool_unref(&changes.pool);
142
dest_storage = mailbox_get_storage(destbox);
170
if (ret <= 0 && move) {
171
/* move failed, don't expunge anything */
172
mailbox_transaction_rollback(&src_trans);
174
if (mailbox_transaction_commit(&src_trans) < 0)
178
dest_storage = mailbox_get_storage(destbox);
143
179
if (destbox != client->mailbox) {
144
sync_flags |= MAILBOX_SYNC_FLAG_FAST;
181
sync_flags |= MAILBOX_SYNC_FLAG_EXPUNGE;
183
sync_flags |= MAILBOX_SYNC_FLAG_FAST;
145
184
imap_flags |= IMAP_SYNC_FLAG_SAFE;
146
185
mailbox_free(&destbox);
187
sync_flags |= MAILBOX_SYNC_FLAG_EXPUNGE;
188
imap_flags |= IMAP_SYNC_FLAG_SAFE;