]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Add mailbox_list_last_error_push/pop()
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 6 Jul 2017 14:36:28 +0000 (17:36 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 12 Jul 2017 21:40:11 +0000 (00:40 +0300)
These are similar to mail_storage_last_error_push/pop()

src/lib-storage/mailbox-list-private.h
src/lib-storage/mailbox-list.c
src/lib-storage/mailbox-list.h

index ac5d28b76c5271779b01246dbea133ae61346b77..4ab18a2b9bd3b5460e5e4ca928b84a8984bf09a0 100644 (file)
@@ -134,6 +134,7 @@ struct mailbox_list {
        char *error_string;
        enum mail_error error;
        bool temporary_error;
+       ARRAY(struct mail_storage_error) error_stack;
 
        ARRAY(union mailbox_list_module_context *) module_contexts;
 
index 117f7026257dd40c32a7d3c26ee52fbcb677e210..3204b787e14cd31b2a0abb9bae8cd011be2ff62a 100644 (file)
@@ -784,6 +784,11 @@ void mailbox_list_destroy(struct mailbox_list **_list)
                mailbox_tree_deinit(&list->subscriptions);
        if (list->changelog != NULL)
                mailbox_log_free(&list->changelog);
+
+       if (array_is_created(&list->error_stack)) {
+               i_assert(array_count(&list->error_stack) == 0);
+               array_free(&list->error_stack);
+       }
        list->v.deinit(list);
 }
 
@@ -1905,6 +1910,35 @@ bool mailbox_list_set_error_from_errno(struct mailbox_list *list)
        return TRUE;
 }
 
+void mailbox_list_last_error_push(struct mailbox_list *list)
+{
+       struct mail_storage_error *err;
+
+       if (!array_is_created(&list->error_stack))
+               i_array_init(&list->error_stack, 2);
+       err = array_append_space(&list->error_stack);
+       err->error_string = i_strdup(list->error_string);
+       err->error = list->error;
+       err->last_error_is_internal = list->last_error_is_internal;
+       if (err->last_error_is_internal)
+               err->last_internal_error = i_strdup(list->last_internal_error);
+}
+
+void mailbox_list_last_error_pop(struct mailbox_list *list)
+{
+       unsigned int count = array_count(&list->error_stack);
+       const struct mail_storage_error *err =
+               array_idx(&list->error_stack, count-1);
+
+       i_free(list->error_string);
+       i_free(list->last_internal_error);
+       list->error_string = err->error_string;
+       list->error = err->error;
+       list->last_error_is_internal = err->last_error_is_internal;
+       list->last_internal_error = err->last_internal_error;
+       array_delete(&list->error_stack, count-1, 1);
+}
+
 int mailbox_list_init_fs(struct mailbox_list *list, const char *driver,
                         const char *args, const char *root_dir,
                         struct fs **fs_r, const char **error_r)
index 6a2595edb8e12a50f5401492151141960d7f6906..3cb09c53f375b83c212d3ca561b75d4e4f812e2d 100644 (file)
@@ -278,6 +278,12 @@ const char * ATTR_NOWARN_UNUSED_RESULT
 mailbox_list_get_last_internal_error(struct mailbox_list *list,
                                     enum mail_error *error_r);
 
+/* Save the last error until it's popped. This is useful for cases where the
+   list operation has already failed, but the cleanup code path changes the
+   error to something else unwanted. */
+void mailbox_list_last_error_push(struct mailbox_list *list);
+void mailbox_list_last_error_pop(struct mailbox_list *list);
+
 /* Create a fs based on the settings in the given mailbox_list. */
 int mailbox_list_init_fs(struct mailbox_list *list, const char *driver,
                         const char *args, const char *root_dir,