mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-24 11:58:10 +01:00
lib: Return an error from operations that require an upgrade
Previously, there was no protection against a caller invoking an operation on an old database version that would effectively corrupt the database by treating it like a newer version. According to notmuch.h, any caller that opens the database in read/write mode is supposed to check if the database needs upgrading and perform an upgrade if it does. This would protect against this, but nobody (even the CLI) actually does this. However, with features, it's easy to protect against incompatible operations on a fine-grained basis. This lightweight change allows callers to safely operate on old database versions, while preventing specific operations that would corrupt the database with an informative error message.
This commit is contained in:
parent
5dbfed4a73
commit
ec573cd54f
4 changed files with 34 additions and 0 deletions
|
@ -316,6 +316,8 @@ notmuch_status_to_string (notmuch_status_t status)
|
||||||
return "Unbalanced number of calls to notmuch_database_begin_atomic/end_atomic";
|
return "Unbalanced number of calls to notmuch_database_begin_atomic/end_atomic";
|
||||||
case NOTMUCH_STATUS_UNSUPPORTED_OPERATION:
|
case NOTMUCH_STATUS_UNSUPPORTED_OPERATION:
|
||||||
return "Unsupported operation";
|
return "Unsupported operation";
|
||||||
|
case NOTMUCH_STATUS_UPGRADE_REQUIRED:
|
||||||
|
return "Operation requires a database upgrade";
|
||||||
default:
|
default:
|
||||||
case NOTMUCH_STATUS_LAST_STATUS:
|
case NOTMUCH_STATUS_LAST_STATUS:
|
||||||
return "Unknown error status value";
|
return "Unknown error status value";
|
||||||
|
@ -2226,6 +2228,9 @@ notmuch_database_find_message_by_filename (notmuch_database_t *notmuch,
|
||||||
if (message_ret == NULL)
|
if (message_ret == NULL)
|
||||||
return NOTMUCH_STATUS_NULL_POINTER;
|
return NOTMUCH_STATUS_NULL_POINTER;
|
||||||
|
|
||||||
|
if (! (notmuch->features & NOTMUCH_FEATURE_FILE_TERMS))
|
||||||
|
return NOTMUCH_STATUS_UPGRADE_REQUIRED;
|
||||||
|
|
||||||
/* return NULL on any failure */
|
/* return NULL on any failure */
|
||||||
*message_ret = NULL;
|
*message_ret = NULL;
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,11 @@ _notmuch_directory_create (notmuch_database_t *notmuch,
|
||||||
const char *db_path;
|
const char *db_path;
|
||||||
notmuch_bool_t create = (flags & NOTMUCH_FIND_CREATE);
|
notmuch_bool_t create = (flags & NOTMUCH_FIND_CREATE);
|
||||||
|
|
||||||
|
if (! (notmuch->features & NOTMUCH_FEATURE_DIRECTORY_DOCS)) {
|
||||||
|
*status_ret = NOTMUCH_STATUS_UPGRADE_REQUIRED;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
*status_ret = NOTMUCH_STATUS_SUCCESS;
|
*status_ret = NOTMUCH_STATUS_SUCCESS;
|
||||||
|
|
||||||
path = _notmuch_database_relative_path (notmuch, path);
|
path = _notmuch_database_relative_path (notmuch, path);
|
||||||
|
|
|
@ -655,6 +655,10 @@ _notmuch_message_add_filename (notmuch_message_t *message,
|
||||||
if (filename == NULL)
|
if (filename == NULL)
|
||||||
INTERNAL_ERROR ("Message filename cannot be NULL.");
|
INTERNAL_ERROR ("Message filename cannot be NULL.");
|
||||||
|
|
||||||
|
if (! (message->notmuch->features & NOTMUCH_FEATURE_FILE_TERMS) ||
|
||||||
|
! (message->notmuch->features & NOTMUCH_FEATURE_BOOL_FOLDER))
|
||||||
|
return NOTMUCH_STATUS_UPGRADE_REQUIRED;
|
||||||
|
|
||||||
relative = _notmuch_database_relative_path (message->notmuch, filename);
|
relative = _notmuch_database_relative_path (message->notmuch, filename);
|
||||||
|
|
||||||
status = _notmuch_database_split_path (local, relative, &directory, NULL);
|
status = _notmuch_database_split_path (local, relative, &directory, NULL);
|
||||||
|
@ -699,6 +703,10 @@ _notmuch_message_remove_filename (notmuch_message_t *message,
|
||||||
notmuch_private_status_t private_status;
|
notmuch_private_status_t private_status;
|
||||||
notmuch_status_t status;
|
notmuch_status_t status;
|
||||||
|
|
||||||
|
if (! (message->notmuch->features & NOTMUCH_FEATURE_FILE_TERMS) ||
|
||||||
|
! (message->notmuch->features & NOTMUCH_FEATURE_BOOL_FOLDER))
|
||||||
|
return NOTMUCH_STATUS_UPGRADE_REQUIRED;
|
||||||
|
|
||||||
status = _notmuch_database_filename_to_direntry (
|
status = _notmuch_database_filename_to_direntry (
|
||||||
local, message->notmuch, filename, NOTMUCH_FIND_LOOKUP, &direntry);
|
local, message->notmuch, filename, NOTMUCH_FIND_LOOKUP, &direntry);
|
||||||
if (status || !direntry)
|
if (status || !direntry)
|
||||||
|
|
|
@ -159,6 +159,10 @@ typedef enum _notmuch_status {
|
||||||
* The operation is not supported.
|
* The operation is not supported.
|
||||||
*/
|
*/
|
||||||
NOTMUCH_STATUS_UNSUPPORTED_OPERATION,
|
NOTMUCH_STATUS_UNSUPPORTED_OPERATION,
|
||||||
|
/**
|
||||||
|
* The operation requires a database upgrade.
|
||||||
|
*/
|
||||||
|
NOTMUCH_STATUS_UPGRADE_REQUIRED,
|
||||||
/**
|
/**
|
||||||
* Not an actual status value. Just a way to find out how many
|
* Not an actual status value. Just a way to find out how many
|
||||||
* valid status values there are.
|
* valid status values there are.
|
||||||
|
@ -438,6 +442,9 @@ notmuch_database_end_atomic (notmuch_database_t *notmuch);
|
||||||
*
|
*
|
||||||
* NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred;
|
* NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred;
|
||||||
* directory not retrieved.
|
* directory not retrieved.
|
||||||
|
*
|
||||||
|
* NOTMUCH_STATUS_UPGRADE_REQUIRED: The caller must upgrade the
|
||||||
|
* database to use this function.
|
||||||
*/
|
*/
|
||||||
notmuch_status_t
|
notmuch_status_t
|
||||||
notmuch_database_get_directory (notmuch_database_t *database,
|
notmuch_database_get_directory (notmuch_database_t *database,
|
||||||
|
@ -490,6 +497,9 @@ notmuch_database_get_directory (notmuch_database_t *database,
|
||||||
*
|
*
|
||||||
* NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
|
* NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
|
||||||
* mode so no message can be added.
|
* mode so no message can be added.
|
||||||
|
*
|
||||||
|
* NOTMUCH_STATUS_UPGRADE_REQUIRED: The caller must upgrade the
|
||||||
|
* database to use this function.
|
||||||
*/
|
*/
|
||||||
notmuch_status_t
|
notmuch_status_t
|
||||||
notmuch_database_add_message (notmuch_database_t *database,
|
notmuch_database_add_message (notmuch_database_t *database,
|
||||||
|
@ -520,6 +530,9 @@ notmuch_database_add_message (notmuch_database_t *database,
|
||||||
*
|
*
|
||||||
* NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
|
* NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
|
||||||
* mode so no message can be removed.
|
* mode so no message can be removed.
|
||||||
|
*
|
||||||
|
* NOTMUCH_STATUS_UPGRADE_REQUIRED: The caller must upgrade the
|
||||||
|
* database to use this function.
|
||||||
*/
|
*/
|
||||||
notmuch_status_t
|
notmuch_status_t
|
||||||
notmuch_database_remove_message (notmuch_database_t *database,
|
notmuch_database_remove_message (notmuch_database_t *database,
|
||||||
|
@ -575,6 +588,9 @@ notmuch_database_find_message (notmuch_database_t *database,
|
||||||
* NOTMUCH_STATUS_OUT_OF_MEMORY: Out of memory, creating the message object
|
* NOTMUCH_STATUS_OUT_OF_MEMORY: Out of memory, creating the message object
|
||||||
*
|
*
|
||||||
* NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred
|
* NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred
|
||||||
|
*
|
||||||
|
* NOTMUCH_STATUS_UPGRADE_REQUIRED: The caller must upgrade the
|
||||||
|
* database to use this function.
|
||||||
*/
|
*/
|
||||||
notmuch_status_t
|
notmuch_status_t
|
||||||
notmuch_database_find_message_by_filename (notmuch_database_t *notmuch,
|
notmuch_database_find_message_by_filename (notmuch_database_t *notmuch,
|
||||||
|
|
Loading…
Reference in a new issue