Skip to content

Commit

Permalink
lib-storage: Add mail_storage_get_last_internal_error()
Browse files Browse the repository at this point in the history
This returns the error given to mail_storage_set_critical().
  • Loading branch information
mrannanj authored and sirainen committed Mar 27, 2017
1 parent 690f935 commit dcf7e4f
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 1 deletion.
4 changes: 4 additions & 0 deletions src/lib-storage/mail-storage-private.h
Expand Up @@ -128,6 +128,9 @@ struct mail_storage {
* uniqueness checking (via strcmp) and never used as a path. */
const char *unique_root_dir;

/* Last error set in mail_storage_set_critical(). */
char *last_internal_error;

char *error_string;
enum mail_error error;
ARRAY(struct mail_storage_error) error_stack;
Expand All @@ -152,6 +155,7 @@ struct mail_storage {

/* Failed to create shared attribute dict, don't try again */
unsigned int shared_attr_dict_failed:1;
unsigned int last_error_is_internal:1;
};

struct mail_attachment_part {
Expand Down
28 changes: 27 additions & 1 deletion src/lib-storage/mail-storage.c
Expand Up @@ -452,6 +452,7 @@ void mail_storage_unref(struct mail_storage **_storage)
DLLIST_REMOVE(&storage->user->storages, storage);

storage->v.destroy(storage);
i_free(storage->last_internal_error);
i_free(storage->error_string);
if (array_is_created(&storage->error_stack)) {
i_assert(array_count(&storage->error_stack) == 0);
Expand Down Expand Up @@ -487,6 +488,8 @@ void mail_storage_clear_error(struct mail_storage *storage)
{
i_free_and_null(storage->error_string);

i_free(storage->last_internal_error);
storage->last_error_is_internal = FALSE;
storage->error = MAIL_ERROR_NONE;
}

Expand All @@ -497,6 +500,7 @@ void mail_storage_set_error(struct mail_storage *storage,
i_free(storage->error_string);
storage->error_string = i_strdup(string);
}
storage->last_error_is_internal = FALSE;
storage->error = error;
}

Expand All @@ -516,16 +520,38 @@ void mail_storage_set_critical(struct mail_storage *storage,
{
va_list va;

i_free(storage->last_internal_error);
va_start(va, fmt);
i_error("%s", t_strdup_vprintf(fmt, va));
storage->last_internal_error = i_strdup_vprintf(fmt, va);
va_end(va);
storage->last_error_is_internal = TRUE;
i_error("%s", storage->last_internal_error);

/* critical errors may contain sensitive data, so let user
see only "Internal error" with a timestamp to make it
easier to look from log files the actual error message. */
mail_storage_set_internal_error(storage);
}

const char *mail_storage_get_last_internal_error(struct mail_storage *storage,
enum mail_error *error_r)
{
if (error_r != NULL)
*error_r = storage->error;
if (storage->last_error_is_internal) {
i_assert(storage->last_internal_error != NULL);
return storage->last_internal_error;
}
return mail_storage_get_last_error(storage, error_r);
}

const char *mailbox_get_last_internal_error(struct mailbox *box,
enum mail_error *error_r)
{
return mail_storage_get_last_internal_error(mailbox_get_storage(box),
error_r);
}

void mail_storage_copy_error(struct mail_storage *dest,
struct mail_storage *src)
{
Expand Down
8 changes: 8 additions & 0 deletions src/lib-storage/mail-storage.h
Expand Up @@ -481,6 +481,14 @@ mailbox_get_last_error(struct mailbox *box, enum mail_error *error_r)
/* Wrapper for mail_storage_get_last_error(); */
enum mail_error mailbox_get_last_mail_error(struct mailbox *box);

const char * ATTR_NOWARN_UNUSED_RESULT
mail_storage_get_last_internal_error(struct mail_storage *storage,
enum mail_error *error_r) ATTR_NULL(2);
/* Wrapper for mail_storage_get_last_internal_error(); */
const char * ATTR_NOWARN_UNUSED_RESULT
mailbox_get_last_internal_error(struct mailbox *box,
enum mail_error *error_r) ATTR_NULL(2);

/* Save the last error until it's popped. This is useful for cases where the
storage has already failed, but the cleanup code path changes the error to
something else unwanted. */
Expand Down

0 comments on commit dcf7e4f

Please sign in to comment.