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;
return fd;
}
-/* Copy the contents of standard input (fdin) into fdout.
- * Returns TRUE if a non-empty file was written successfully.
- * Otherwise, return FALSE. */
+/*
+ * Copy fdin to fdout, return TRUE on success, and FALSE on errors and
+ * empty input.
+ */
static notmuch_bool_t
-copy_stdin (int fdin, int fdout)
+copy_fd (int fdout, int fdin)
{
notmuch_bool_t empty = TRUE;
return (!interrupted && !empty);
}
+static notmuch_bool_t
+write_message (void *ctx, int fdin, const char *dir, char **newpath)
+{
+ char *tmppath;
+ char *newdir;
+ char *cleanup_path;
+ int fdout;
+
+ fdout = maildir_open_tmp_file (ctx, dir, &tmppath, newpath, &newdir);
+ if (fdout < 0)
+ return FALSE;
+
+ cleanup_path = tmppath;
+
+ if (! copy_fd (fdout, fdin))
+ goto FAIL;
+
+ if (fsync (fdout) != 0) {
+ fprintf (stderr, "Error: fsync failed: %s\n", strerror (errno));
+ goto FAIL;
+ }
+
+ close (fdout);
+ fdout = -1;
+
+ /* Atomically move the new message file from the Maildir 'tmp' directory
+ * to the 'new' directory. We follow the Dovecot recommendation to
+ * simply use rename() instead of link() and unlink().
+ * See also: http://wiki.dovecot.org/MailboxFormat/Maildir#Mail_delivery
+ */
+ if (rename (tmppath, *newpath) != 0) {
+ fprintf (stderr, "Error: rename() failed: %s\n", strerror (errno));
+ goto FAIL;
+ }
+
+ cleanup_path = *newpath;
+
+ if (! sync_dir (newdir))
+ goto FAIL;
+
+ return TRUE;
+
+ FAIL:
+ if (fdout >= 0)
+ close (fdout);
+ unlink (cleanup_path);
+ 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
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,
- notmuch_bool_t synchronize_flags)
-{
- char *tmppath;
- char *newpath;
- char *newdir;
- int fdout;
- char *cleanup_path;
-
- fdout = maildir_open_tmp_file (ctx, dir, &tmppath, &newpath, &newdir);
- if (fdout < 0)
- return FALSE;
-
- cleanup_path = tmppath;
-
- if (! copy_stdin (fdin, fdout))
- goto FAIL;
-
- if (fsync (fdout) != 0) {
- fprintf (stderr, "Error: fsync failed: %s\n", strerror (errno));
- goto FAIL;
- }
-
- close (fdout);
- fdout = -1;
-
- /* Atomically move the new message file from the Maildir 'tmp' directory
- * to the 'new' directory. We follow the Dovecot recommendation to
- * simply use rename() instead of link() and unlink().
- * See also: http://wiki.dovecot.org/MailboxFormat/Maildir#Mail_delivery
- */
- if (rename (tmppath, newpath) != 0) {
- fprintf (stderr, "Error: rename() failed: %s\n", strerror (errno));
- goto FAIL;
- }
-
- 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, synchronize_flags);
-
- return TRUE;
-
- FAIL:
- if (fdout >= 0)
- close (fdout);
- unlink (cleanup_path);
- return FALSE;
-}
-
int
notmuch_insert_command (notmuch_config_t *config, int argc, char *argv[])
{
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 },
if (folder == NULL) {
maildir = db_path;
} else {
- if (! check_folder_name (folder)) {
- fprintf (stderr, "Error: bad folder name: %s\n", folder);
+ 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);
NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
return EXIT_FAILURE;
- ret = insert_message (config, notmuch, STDIN_FILENO, maildir, tag_ops,
- synchronize_flags);
+ /* Write the message to the Maildir new directory. */
+ if (! write_message (config, STDIN_FILENO, maildir, &newpath)) {
+ notmuch_database_destroy (notmuch);
+ return EXIT_FAILURE;
+ }
+
+ /* 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);
notmuch_database_destroy (notmuch);
-
- return ret ? EXIT_SUCCESS : EXIT_FAILURE;
+ return EXIT_SUCCESS;
}