[Patch v5 2/6] dump: when given output file name, write atomically
authorDavid Bremner <david@tethera.net>
Wed, 2 Apr 2014 01:16:17 +0000 (22:16 +2100)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 18:01:08 +0000 (10:01 -0800)
75/f64caf3af5163fb44ba16ce7ab4e835e8e9b01 [new file with mode: 0644]

diff --git a/75/f64caf3af5163fb44ba16ce7ab4e835e8e9b01 b/75/f64caf3af5163fb44ba16ce7ab4e835e8e9b01
new file mode 100644 (file)
index 0000000..322f5ea
--- /dev/null
@@ -0,0 +1,140 @@
+Return-Path: <bremner@tethera.net>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+       by olra.theworths.org (Postfix) with ESMTP id 3EB4B431FBD\r
+       for <notmuch@notmuchmail.org>; Tue,  1 Apr 2014 18:16:42 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: 0\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[none]\r
+       autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+       by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+       with ESMTP id v5WP+BNshXoG for <notmuch@notmuchmail.org>;\r
+       Tue,  1 Apr 2014 18:16:41 -0700 (PDT)\r
+Received: from yantan.tethera.net (yantan.tethera.net [199.188.72.155])\r
+       (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits))\r
+       (No client certificate requested)\r
+       by olra.theworths.org (Postfix) with ESMTPS id B06D4431FC2\r
+       for <notmuch@notmuchmail.org>; Tue,  1 Apr 2014 18:16:40 -0700 (PDT)\r
+Received: from remotemail by yantan.tethera.net with local (Exim 4.80)\r
+       (envelope-from <bremner@tethera.net>)\r
+       id 1WV9nE-00072u-Ef; Tue, 01 Apr 2014 22:16:40 -0300\r
+Received: (nullmailer pid 18501 invoked by uid 1000); Wed, 02 Apr 2014\r
+       01:16:26 -0000\r
+From: David Bremner <david@tethera.net>\r
+To: notmuch@notmuchmail.org\r
+Subject: [Patch v5 2/6] dump: when given output file name, write atomically\r
+Date: Tue,  1 Apr 2014 22:16:17 -0300\r
+Message-Id: <1396401381-18128-3-git-send-email-david@tethera.net>\r
+X-Mailer: git-send-email 1.9.0\r
+In-Reply-To: <1396401381-18128-1-git-send-email-david@tethera.net>\r
+References: <1396401381-18128-1-git-send-email-david@tethera.net>\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+       <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Wed, 02 Apr 2014 01:16:42 -0000\r
+\r
+It is useful to able to tell whether a dump completed successfully in\r
+situtions where we don't have access to the return code.\r
+---\r
+ notmuch-dump.c | 61 +++++++++++++++++++++++++++++++++++++++++++++-------------\r
+ 1 file changed, 48 insertions(+), 13 deletions(-)\r
+\r
+diff --git a/notmuch-dump.c b/notmuch-dump.c\r
+index 28342b7..05ed6b4 100644\r
+--- a/notmuch-dump.c\r
++++ b/notmuch-dump.c\r
+@@ -129,30 +129,65 @@ notmuch_database_dump (notmuch_database_t *notmuch,\r
+ {\r
+     gzFile output;\r
+     const char *mode = gzip_output ? "w9" : "wT";\r
++    const char *name_for_error = output_file_name ? output_file_name : "stdout";\r
\r
+-    int ret;\r
++    char *tempname = NULL;\r
++    int outfd = -1;\r
++\r
++    int ret = -1;\r
++\r
++    if (output_file_name) {\r
++      tempname = talloc_asprintf (notmuch, "%s.XXXXXX", output_file_name);\r
++      outfd = mkstemp (tempname);\r
++    } else {\r
++      outfd = fileno (stdout);\r
++    }\r
\r
+-    if (output_file_name)\r
+-      output = gzopen (output_file_name, mode);\r
+-    else\r
+-      output = gzdopen (fileno (stdout), mode);\r
++    if (outfd < 0) {\r
++      fprintf (stderr, "Bad output file %s\n", name_for_error);\r
++      goto DONE;\r
++    }\r
++\r
++    output = gzdopen (outfd, mode);\r
\r
+     if (output == NULL) {\r
+       fprintf (stderr, "Error opening %s for (gzip) writing: %s\n",\r
+-               output_file_name ? output_file_name : "stdout", strerror (errno));\r
+-      return EXIT_FAILURE;\r
++               name_for_error, strerror (errno));\r
++      goto DONE;\r
+     }\r
\r
+     ret = database_dump_file (notmuch, output, query_str, output_format);\r
++    if (ret) goto DONE;\r
\r
+-    if (gzflush (output, Z_FINISH)) {\r
+-      fprintf (stderr, "Error flushing output: %s\n",\r
+-               gzerror (output, NULL));\r
+-      return EXIT_FAILURE;\r
++    ret = gzflush (output, Z_FINISH);\r
++    if (ret) {\r
++      fprintf (stderr, "Error flushing output: %s\n", gzerror (output, NULL));\r
++      goto DONE;\r
+     }\r
\r
+-    if (output_file_name)\r
+-      gzclose_w (output);\r
++    ret = fdatasync (outfd);\r
++    if (ret) {\r
++      perror ("fdatasync");\r
++      goto DONE;\r
++    }\r
++\r
++    if (output_file_name) {\r
++      ret = gzclose_w (output);\r
++      if (ret != Z_OK) {\r
++          ret = EXIT_FAILURE;\r
++          goto DONE;\r
++      }\r
++\r
++      ret = rename (tempname, output_file_name);\r
++      if (ret) {\r
++          perror ("rename");\r
++          goto DONE;\r
++      }\r
++\r
++    }\r
++ DONE:\r
++    if (ret != EXIT_SUCCESS && output_file_name)\r
++      (void) unlink (tempname);\r
\r
+     return ret;\r
+ }\r
+-- \r
+1.9.0\r
+\r