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