summaryrefslogtreecommitdiff
path: root/src/mktemp.c
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2009-11-05 09:05:03 -0700
committerEric Blake <ebb9@byu.net>2009-11-05 13:12:35 -0700
commitdde83c27b4e5c75063c304e5dcfada6950a6d7ee (patch)
treeb68f465970a1e87931fdd8a29769a019e341ac57 /src/mktemp.c
parent20e5a0d562cf698fab7be3d04c5f1c356faa2dbb (diff)
downloadcoreutils-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.
Diffstat (limited to 'src/mktemp.c')
-rw-r--r--src/mktemp.c20
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);