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