+ const char *key_p, *val_p;
+ char *key, *val;
+ size_t key_len,val_len;
+ const char *delim = " \t\n";
+ int ret = EXIT_FAILURE;
+
+ void *local = talloc_new(NULL);
+
+ key_p = strtok_len_c (line, delim, &key_len);
+ val_p = strtok_len_c (key_p+key_len, delim, &val_len);
+
+ key = talloc_strndup (local, key_p, key_len);
+ val = talloc_strndup (local, val_p, val_len);
+ if (hex_decode_inplace (key) != HEX_SUCCESS ||
+ hex_decode_inplace (val) != HEX_SUCCESS ) {
+ fprintf (stderr, "hex decoding failure on line %s\n", line);
+ goto DONE;
+ }
+
+ if (print_status_database ("notmuch restore", notmuch,
+ notmuch_database_set_config (notmuch, key, val)))
+ goto DONE;
+
+ ret = EXIT_SUCCESS;
+
+ DONE:
+ talloc_free (local);
+ return ret;
+}
+
+static regex_t regex;
+
+/* Non-zero return indicates an error in retrieving the message,
+ * or in applying the tags. Missing messages are reported, but not
+ * considered errors.
+ */
+static int
+tag_message (unused (void *ctx),
+ notmuch_database_t *notmuch,
+ const char *message_id,
+ tag_op_list_t *tag_ops,
+ tag_op_flag_t flags)
+{
+ notmuch_status_t status;
+ notmuch_message_t *message = NULL;
+ int ret = 0;
+
+ status = notmuch_database_find_message (notmuch, message_id, &message);
+ if (status) {
+ fprintf (stderr, "Error applying tags to message %s: %s\n",
+ message_id, notmuch_status_to_string (status));
+ return 1;
+ }
+ if (message == NULL) {
+ fprintf (stderr, "Warning: cannot apply tags to missing message: %s\n",
+ message_id);
+ /* We consider this a non-fatal error. */
+ return 0;
+ }
+
+ /* In order to detect missing messages, this check/optimization is
+ * intentionally done *after* first finding the message. */
+ if ((flags & TAG_FLAG_REMOVE_ALL) || tag_op_list_size (tag_ops))
+ ret = tag_op_list_apply (message, tag_ops, flags);
+
+ notmuch_message_destroy (message);
+
+ return ret;
+}
+
+/* Sup dump output is one line per message. We match a sequence of
+ * non-space characters for the message-id, then one or more
+ * spaces, then a list of space-separated tags as a sequence of
+ * characters within literal '(' and ')'. */
+
+static int
+parse_sup_line (void *ctx, char *line,
+ char **query_str, tag_op_list_t *tag_ops)
+{
+
+ regmatch_t match[3];
+ char *file_tags;