diff options
author | Eric Blake <ebb9@byu.net> | 2009-11-05 09:05:03 -0700 |
---|---|---|
committer | Eric Blake <ebb9@byu.net> | 2009-11-05 13:12:35 -0700 |
commit | dde83c27b4e5c75063c304e5dcfada6950a6d7ee (patch) | |
tree | b68f465970a1e87931fdd8a29769a019e341ac57 | |
parent | 20e5a0d562cf698fab7be3d04c5f1c356faa2dbb (diff) | |
download | coreutils-dde83c27b4e5c75063c304e5dcfada6950a6d7ee.tar.xz |
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.
-rw-r--r-- | src/mktemp.c | 20 |
1 files changed, 18 insertions, 2 deletions
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); |