From dde83c27b4e5c75063c304e5dcfada6950a6d7ee Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Thu, 5 Nov 2009 09:05:03 -0700 Subject: mktemp: use more robust means to avoid double-close of stdout Reverts earlier patch - fflush() can succeed but fclose() fail for some cases of write failures, and we want to catch those. * src/mktemp.c (stdout_closed): New variable. (maybe_close_stdout): New function, borrowed from dd.c. (main): Track whether stdout has been closed. --- src/mktemp.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'src/mktemp.c') diff --git a/src/mktemp.c b/src/mktemp.c index 980ec3930..6ce40f133 100644 --- a/src/mktemp.c +++ b/src/mktemp.c @@ -128,6 +128,22 @@ mkdtemp_len (char *tmpl, size_t suff_len, size_t x_len, bool dry_run) x_len); } +/* True if we have already closed standard output. */ +static bool stdout_closed; + +/* Avoid closing stdout twice. Since we conditionally call + close_stream (stdout) in order to decide whether to clean up a + temporary file, the exit hook needs to know whether to do all of + close_stdout or just the stderr half. */ +static void +maybe_close_stdout (void) +{ + if (!stdout_closed) + close_stdout (); + else if (close_stream (stderr) != 0) + _exit (EXIT_FAILURE); +} + int main (int argc, char **argv) { @@ -153,7 +169,7 @@ main (int argc, char **argv) bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); - atexit (close_stdout); + atexit (maybe_close_stdout); while ((c = getopt_long (argc, argv, "dp:qtuV", longopts, NULL)) != -1) { @@ -325,7 +341,7 @@ main (int argc, char **argv) puts (dest_name); /* If we created a file, but then failed to output the file name, we should clean up the mess before failing. */ - if (!dry_run && (ferror (stdout) || fflush (stdout) != 0)) + if (!dry_run && (stdout_closed = true) && close_stream (stdout) != 0) { int saved_errno = errno; remove (dest_name); -- cgit v1.2.3-54-g00ecf