Eric Blake <ebb9 <at> byu.net> writes: > This currently gives exit status 1, because the atexit() handler recognizes > failure to print the file name to stdout, but leaves the temporary file > around. Should we go ahead and manually flush/close stdout, rather than > relying on close_stdout, so that we can then remove the just-created file if we > detect write failure? That way, if we fail to inform the user what just got > created, we are at least avoiding littering their file system with a random > file. > > Fortunately, 'mktemp >&-' does not make the mistake of printing the just- > created file as the contents of that file, since we close the fd returned by > mkstemp before printing anything.
How about the following? From: Eric Blake <e...@byu.net> Date: Wed, 4 Nov 2009 14:02:20 -0700 Subject: [PATCH] mktemp: don't leave file behind on write failure * src/mktemp.c (main): Remove just-created file if stdout had problems. * bootstrap.conf (gnulib_modules): Add remove. * tests/misc/close-stdout: Test it. * NEWS: Document it. --- NEWS | 4 ++++ bootstrap.conf | 1 + src/mktemp.c | 12 +++++++++++- tests/misc/close-stdout | 6 ++++++ 4 files changed, 22 insertions(+), 1 deletions(-) diff --git a/NEWS b/NEWS index 3f8baf0..4d1b4f5 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,10 @@ GNU coreutils NEWS -*- outline -*- This also affected sum, sha1sum, sha224sum, sha384sum and sha512sum. [the bug dates back to the initial implementation] + mktemp no longer leaves a temporary file behind if it was unable to + output the name of the file to stdout. + [the bug dates back to the initial implementation] + nice -n -1 PROGRAM now runs PROGRAM even when its internal setpriority call fails with errno == EACCES. [the bug dates back to the initial implementation] diff --git a/bootstrap.conf b/bootstrap.conf index 7960546..b3a82e0 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -180,6 +180,7 @@ gnulib_modules=" readutmp realloc regex + remove rename rmdir root-dev-ino diff --git a/src/mktemp.c b/src/mktemp.c index e645362..12acad8 100644 --- a/src/mktemp.c +++ b/src/mktemp.c @@ -23,6 +23,7 @@ #include "system.h" +#include "close-stream.h" #include "error.h" #include "filenamecat.h" #include "quote.h" @@ -322,7 +323,16 @@ main (int argc, char **argv) } if (status == EXIT_SUCCESS) - puts (dest_name); + { + 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 && close_stream (stdout)) + { + remove (dest_name); + error (EXIT_FAILURE, errno, _("write error")); + } + } #ifdef lint free (dest_name); diff --git a/tests/misc/close-stdout b/tests/misc/close-stdout index fec1add..852c3c8 100755 --- a/tests/misc/close-stdout +++ b/tests/misc/close-stdout @@ -50,12 +50,18 @@ if "$p/src/test" -w /dev/stdout >/dev/null && "$p/src/test" ! -w /dev/stdout >&-; then "$p/src/printf" 'foo' >&- 2>/dev/null && fail=1 cp --verbose a b >&- 2>/dev/null && fail=1 + rm -Rf tmpfile-?????? || fail=1 + mktemp tmpfile-XXXXXX >&- 2>/dev/null && fail=1 + test -e tmpfile-?????? && fail=1 fi # Likewise for /dev/full, if /dev/full works. if test -w /dev/full && test -c /dev/full; then "$p/src/printf" 'foo' >/dev/full 2>/dev/null && fail=1 cp --verbose a b >/dev/full 2>/dev/null && fail=1 + rm -Rf tmpdir-?????? || fail=1 + mktemp -d tmpdir-XXXXXX >/dev/full 2>/dev/null && fail=1 + test -e tmpdir-?????? && fail=1 fi Exit $fail -- 1.6.4.2