X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=notmuch-insert.c;h=ccb091ac0561f1af3ceb1f2daefd0e26f7990e88;hb=c878081127f48c393835b6f067f8f85beda9ff29;hp=2207b1e808d34d48e95875851e9d57cdc7adcb57;hpb=426558d37ec098a011af54a7c3fdc6b65a84ed94;p=notmuch diff --git a/notmuch-insert.c b/notmuch-insert.c index 2207b1e8..ccb091ac 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -83,10 +83,13 @@ sync_dir (const char *dir) return ret; } -/* Check the specified folder name does not contain a directory - * component ".." to prevent writes outside of the Maildir hierarchy. */ +/* + * Check the specified folder name does not contain a directory + * component ".." to prevent writes outside of the Maildir + * hierarchy. Return TRUE on valid folder name, FALSE otherwise. + */ static notmuch_bool_t -check_folder_name (const char *folder) +is_valid_folder_name (const char *folder) { const char *p = folder; @@ -291,59 +294,15 @@ copy_stdin (int fdin, int fdout) return (!interrupted && !empty); } -/* Add the specified message file to the notmuch database, applying tags. - * The file is renamed to encode notmuch tags as maildir flags. */ -static void -add_file_to_database (notmuch_database_t *notmuch, const char *path, - tag_op_list_t *tag_ops) -{ - notmuch_message_t *message; - notmuch_status_t status; - - status = notmuch_database_add_message (notmuch, path, &message); - switch (status) { - case NOTMUCH_STATUS_SUCCESS: - case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID: - break; - default: - case NOTMUCH_STATUS_FILE_NOT_EMAIL: - case NOTMUCH_STATUS_READ_ONLY_DATABASE: - case NOTMUCH_STATUS_XAPIAN_EXCEPTION: - case NOTMUCH_STATUS_OUT_OF_MEMORY: - case NOTMUCH_STATUS_FILE_ERROR: - case NOTMUCH_STATUS_NULL_POINTER: - case NOTMUCH_STATUS_TAG_TOO_LONG: - case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: - case NOTMUCH_STATUS_UNBALANCED_ATOMIC: - case NOTMUCH_STATUS_LAST_STATUS: - fprintf (stderr, "Error: failed to add `%s' to notmuch database: %s\n", - path, notmuch_status_to_string (status)); - return; - } - - if (status == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) { - /* Don't change tags of an existing message. */ - status = notmuch_message_tags_to_maildir_flags (message); - if (status != NOTMUCH_STATUS_SUCCESS) - fprintf (stderr, "Error: failed to sync tags to maildir flags\n"); - } else { - tag_op_list_apply (message, tag_ops, TAG_FLAG_MAILDIR_SYNC); - } - - notmuch_message_destroy (message); -} - static notmuch_bool_t -insert_message (void *ctx, notmuch_database_t *notmuch, int fdin, - const char *dir, tag_op_list_t *tag_ops) +write_message (void *ctx, int fdin, const char *dir, char **newpath) { char *tmppath; - char *newpath; char *newdir; - int fdout; char *cleanup_path; + int fdout; - fdout = maildir_open_tmp_file (ctx, dir, &tmppath, &newpath, &newdir); + fdout = maildir_open_tmp_file (ctx, dir, &tmppath, newpath, &newdir); if (fdout < 0) return FALSE; @@ -365,20 +324,16 @@ insert_message (void *ctx, notmuch_database_t *notmuch, int fdin, * simply use rename() instead of link() and unlink(). * See also: http://wiki.dovecot.org/MailboxFormat/Maildir#Mail_delivery */ - if (rename (tmppath, newpath) != 0) { + if (rename (tmppath, *newpath) != 0) { fprintf (stderr, "Error: rename() failed: %s\n", strerror (errno)); goto FAIL; } - cleanup_path = newpath; + cleanup_path = *newpath; if (! sync_dir (newdir)) goto FAIL; - /* Even if adding the message to the notmuch database fails, - * the message is on disk and we consider the delivery completed. */ - add_file_to_database (notmuch, newpath, tag_ops); - return TRUE; FAIL: @@ -388,6 +343,52 @@ insert_message (void *ctx, notmuch_database_t *notmuch, int fdin, return FALSE; } +/* Add the specified message file to the notmuch database, applying tags. + * The file is renamed to encode notmuch tags as maildir flags. */ +static void +add_file_to_database (notmuch_database_t *notmuch, const char *path, + tag_op_list_t *tag_ops, notmuch_bool_t synchronize_flags) +{ + notmuch_message_t *message; + notmuch_status_t status; + + status = notmuch_database_add_message (notmuch, path, &message); + switch (status) { + case NOTMUCH_STATUS_SUCCESS: + case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID: + break; + default: + case NOTMUCH_STATUS_FILE_NOT_EMAIL: + case NOTMUCH_STATUS_READ_ONLY_DATABASE: + case NOTMUCH_STATUS_XAPIAN_EXCEPTION: + case NOTMUCH_STATUS_OUT_OF_MEMORY: + case NOTMUCH_STATUS_FILE_ERROR: + case NOTMUCH_STATUS_NULL_POINTER: + case NOTMUCH_STATUS_TAG_TOO_LONG: + case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: + case NOTMUCH_STATUS_UNBALANCED_ATOMIC: + case NOTMUCH_STATUS_LAST_STATUS: + fprintf (stderr, "Error: failed to add `%s' to notmuch database: %s\n", + path, notmuch_status_to_string (status)); + return; + } + + if (status == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) { + /* Don't change tags of an existing message. */ + if (synchronize_flags) { + status = notmuch_message_tags_to_maildir_flags (message); + if (status != NOTMUCH_STATUS_SUCCESS) + fprintf (stderr, "Error: failed to sync tags to maildir flags\n"); + } + } else { + tag_op_flag_t flags = synchronize_flags ? TAG_FLAG_MAILDIR_SYNC : 0; + + tag_op_list_apply (message, tag_ops, flags); + } + + notmuch_message_destroy (message); +} + int notmuch_insert_command (notmuch_config_t *config, int argc, char *argv[]) { @@ -400,10 +401,11 @@ notmuch_insert_command (notmuch_config_t *config, int argc, char *argv[]) char *query_string = NULL; const char *folder = NULL; notmuch_bool_t create_folder = FALSE; + notmuch_bool_t synchronize_flags; const char *maildir; + char *newpath; int opt_index; unsigned int i; - notmuch_bool_t ret; notmuch_opt_desc_t options[] = { { NOTMUCH_OPT_STRING, &folder, "folder", 0, 0 }, @@ -412,50 +414,57 @@ notmuch_insert_command (notmuch_config_t *config, int argc, char *argv[]) }; opt_index = parse_arguments (argc, argv, options, 1); - - if (opt_index < 0) { - /* diagnostics already printed */ - return 1; - } + if (opt_index < 0) + return EXIT_FAILURE; db_path = notmuch_config_get_database_path (config); new_tags = notmuch_config_get_new_tags (config, &new_tags_length); + synchronize_flags = notmuch_config_get_maildir_synchronize_flags (config); tag_ops = tag_op_list_create (config); if (tag_ops == NULL) { fprintf (stderr, "Out of memory.\n"); - return 1; + return EXIT_FAILURE; } for (i = 0; i < new_tags_length; i++) { + const char *error_msg; + + error_msg = illegal_tag (new_tags[i], FALSE); + if (error_msg) { + fprintf (stderr, "Error: tag '%s' in new.tags: %s\n", + new_tags[i], error_msg); + return EXIT_FAILURE; + } + if (tag_op_list_append (tag_ops, new_tags[i], FALSE)) - return 1; + return EXIT_FAILURE; } if (parse_tag_command_line (config, argc - opt_index, argv + opt_index, &query_string, tag_ops)) - return 1; + return EXIT_FAILURE; if (*query_string != '\0') { fprintf (stderr, "Error: unexpected query string: %s\n", query_string); - return 1; + return EXIT_FAILURE; } if (folder == NULL) { maildir = db_path; } else { - if (! check_folder_name (folder)) { - fprintf (stderr, "Error: bad folder name: %s\n", folder); - return 1; + if (! is_valid_folder_name (folder)) { + fprintf (stderr, "Error: invalid folder name: '%s'\n", folder); + return EXIT_FAILURE; } maildir = talloc_asprintf (config, "%s/%s", db_path, folder); if (! maildir) { fprintf (stderr, "Out of memory\n"); - return 1; + return EXIT_FAILURE; } if (create_folder && ! maildir_create_folder (config, maildir)) { fprintf (stderr, "Error: creating maildir %s: %s\n", maildir, strerror (errno)); - return 1; + return EXIT_FAILURE; } } @@ -469,11 +478,20 @@ notmuch_insert_command (notmuch_config_t *config, int argc, char *argv[]) if (notmuch_database_open (notmuch_config_get_database_path (config), NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much)) - return 1; + return EXIT_FAILURE; - ret = insert_message (config, notmuch, STDIN_FILENO, maildir, tag_ops); + /* Write the message to the Maildir new directory. */ + if (! write_message (config, STDIN_FILENO, maildir, &newpath)) { + notmuch_database_destroy (notmuch); + return EXIT_FAILURE; + } - notmuch_database_destroy (notmuch); + /* Add the message to the index. + * Even if adding the message to the notmuch database fails, + * the message is on disk and we consider the delivery completed. */ + add_file_to_database (notmuch, newpath, tag_ops, + synchronize_flags); - return (ret) ? 0 : 1; + notmuch_database_destroy (notmuch); + return EXIT_SUCCESS; }