Eric Blake <ebb9 <at> byu.net> writes:

> Now that glibc 2.11 has mkostemps, and I'm working on adding that to gnulib, 
it 
> would be nice to expose the idea of an explicit suffix to temporary file 
> names.  But rather than require the user to count how long their suffix is, I 
> imagine it would make more sense to give mktemp(1) some do-what-I-mean 
smarts.  

Before I do that, how about documenting what mktemp currently does.  The 
proposed patch documents the current behavior, although it probably needs some 
tweaks (and corresponding tweaks in mktemp.c) based this email.

mktemp --help is not very obvious that --tmpdir is implied if no TEMPLATE is 
given.

Right now, 'mktemp --help' claims that --tmpdir and -p are distinct, but the 
code says they are almost the same (they both set use_dest_dir=true and 
dest_dir_arg=optarg).  The only difference is that --tmpdir has an optional 
argument, while -p has a mandatory argument, so dest_dir_arg can be NULL if you 
use --tmpdir but not if you use -p.

By the way, the optional argument to --subdir has some interesting effects, 
because we are not consistent on whether we check optarg for being the empty 
string:

mkdir --subdir="$dir"
 => if $dir is empty, try $TMPDIR; if that is empty, use /tmp
mkdir --subdir="$dir" -t
 => if $TMPDIR is empty, use $dir; if that is empty, use .

In other words, the only thing that I can see -t doing is whether we first 
check $TMPDIR or the argument to -p/--tmpdir, and restricts us from using 
subdirectories in the template (is this restriction really necessary)?  It 
doesn't even print a deprecation warning or have a FIXME date with proposed 
removal.  So, what if we just undeprecate -t (by adding a long option), and 
document/implement things as follows:

  -p DIR, --tmpdir[=DIR]
                   interpret TEMPLATE relative to DIR.  If DIR is empty
                     or not supplied, use $TMPDIR if set, else /tmp
  -t, --favor-tmpdir
                   with -p, favor $TMPDIR over the DIR argument; otherwise
                     use $TMPDIR or /tmp instead of current directory

TEMPLATE may contain slashes, but intermediate directories must exist.
If -p or -t is specified, TEMPLATE must not be absolute.


Also, is there a cleanup hole?  For most code paths, an exit status of 1 means 
that the temporary file could not be created.  But consider:

mktemp >/dev/full

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.


At any rate, here's the proposed documentation patch:

From: Eric Blake <e...@byu.net>
Date: Tue, 3 Nov 2009 10:47:42 -0700
Subject: [PATCH] doc: document mktemp

* doc/coreutils.texi (mktemp invocation): New node.
---
 doc/coreutils.texi |  144 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 142 insertions(+), 2 deletions(-)

diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index ec5bcfb..1fd1bec 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -31,7 +31,6 @@
 @c FIXME: the following need documentation
 @c * [: (coreutils)[ invocation.                   File/string tests.
 @c * pinky: (coreutils)pinky invocation.           FIXME.
-...@c * mktemp: (coreutils)mktemp invocation.         FIXME.

 @dircategory Individual utilities
 @direntry
@@ -80,6 +79,7 @@
 * mkdir: (coreutils)mkdir invocation.           Create directories.
 * mkfifo: (coreutils)mkfifo invocation.         Create FIFOs (named pipes).
 * mknod: (coreutils)mknod invocation.           Create special files.
+* mktemp: (coreutils)mktemp invocation.         Create temporary files.
 * mv: (coreutils)mv invocation.                 Rename files.
 * nice: (coreutils)nice invocation.             Modify niceness.
 * nl: (coreutils)nl invocation.                 Number lines and write files.
@@ -193,7 +193,7 @@ Top
 * Printing text::                echo printf yes
 * Conditions::                   false true test expr
 * Redirection::                  tee
-* File name manipulation::       dirname basename pathchk
+* File name manipulation::       dirname basename pathchk mktemp
 * Working context::              pwd stty printenv tty
 * User information::             id logname whoami groups users who
 * System context::               date arch uname hostname hostid uptime
@@ -378,6 +378,7 @@ Top
 * basename invocation::          Strip directory and suffix from a file name
 * dirname invocation::           Strip non-directory suffix from a file name
 * pathchk invocation::           Check file name validity and portability
+* mktemp invocation::            Create temporary file or directory

 Working context

@@ -11876,6 +11877,7 @@ File name manipulation
 * basename invocation::         Strip directory and suffix from a file name.
 * dirname invocation::          Strip non-directory suffix from a file name.
 * pathchk invocation::          Check file name validity and portability.
+* mktemp invocation::           Create temporary file or directory.
 @end menu


@@ -12050,6 +12052,144 @@ pathchk invocation
 1 otherwise.
 @end display

+...@node mktemp invocation
+...@section @command{mktemp}: Create temporary file or directory
+
+...@pindex mktemp
+...@cindex file names, creating temporary
+...@cindex directory, creating temporary
+...@cindex temporary files and directories
+
+...@command{mktemp} manages the creation of temporary files and
+directories.  Synopsis:
+
+...@example
+mktemp [...@var{option}]@dots{} [...@var{template}]
+...@end example
+
+Safely create a temporary file or directory based on @var{template},
+and print its name.  If given, @var{template} must end in at least
+three consecutive @samp{X}.  If omitted, the template
+...@samp{tmp.xxxxxxxxxx} is used, and option @option{--tmpdir} is
+implied.
+
+When creating a file, the resulting file has read and write
+permissions for the current user, but no permissions for the group or
+others; these permissions are reduced if the current umask is more
+restrictive.
+
+Here are some examples (although note that if you repeat them, you
+will most likely get different file names):
+
+...@itemize @bullet
+
+...@item
+Create a temporary file in the current directory.
+...@example
+$ mktemp file.XXXX
+file.H47c
+...@end example
+
+...@item
+Create a secure fifo relative to the user's choice of @env{TMPDIR},
+but falling back to the current directory rather than @file{/tmp}.
+Note that @command{mktemp} does not create fifos, but can create a
+secure directory in which the fifo can live.  Exit the shell if the
+directory or fifo could not be created.
+...@example
+$ dir=$(mktemp -p "$...@{tmpdir:-...@}" -d dir-XXXX) || exit 1
+$ fifo=$dir/fifo
+$ mkfifo "$fifo" || @{ rmdir $dir; exit 1; @}
+...@end example
+
+...@item
+Create and use a temporary file if possible, but ignore failure.  The
+file will reside in the directory named by @env{TMPDIR}, if specified,
+or else in @file{/tmp}.
+...@example
+$ file=$(mktemp -q) && @{
+>   # Safe to use $file only within this block
+>   echo ... > $file
+>   rm $file
+> @}
+...@end example
+
+...@item
+Act as a semi-random character generator (it is not fully random,
+since it is impacted by the contents of the current directory).  To
+avoid security holes, do not use the resulting names to create a file.
+...@example
+$ mktemp -u XXX
+Gb9
+$ mktemp -u XXX
+nzC
+...@end example
+
+...@end itemize
+
+
+The program accepts the following options.  Also see @ref{Common options}.
+
+...@table @samp
+
+...@item -d
+...@itemx --directory
+...@opindex -d
+...@opindex --directory
+Create a directory rather than a file.  The directory will have read,
+write, and execute permissions for the current user, but no
+permissions for the group or others; these permissions are reduced if
+the current umask is more restrictive.
+
+...@item -q
+...@itemx --quiet
+...@opindex -q
+...@opindex --quiet
+Suppress diagnostics about failure to create a file or directory.  The
+exit status will still reflect whether a file was created.
+
+...@item -u
+...@itemx --dry-run
+...@opindex -u
+...@opindex --dry-run
+Generate a temporary name that does not name an existing file, without
+changing the file system contents.  Using the output of this command
+to create a new file is inherently unsafe, as there is a window of
+time between generating the name and using it where another process
+can create an object by the same name.
+
+...@item -p @var{dir}
+...@itemx --tempdi...@var{dir}]
+...@opindex -p
+...@opindex --tempdir
+Treat @var{template} relative to the directory @var{dir}.  If
+...@var{dir} is not specified (only possible with the long option
+...@option{--tempdir}) or is the empty string, use the value of
+...@env{tmpdir} if available, otherwise use @samp{/tmp}.  If this is
+specified, @var{template} must not be absolute.  However,
+...@var{template} can still contain slashes, although intermediate
+directories must already exist.
+
+...@item -t
+...@opindex -t
+Treat @var{template} as a single file relative to the value of
+...@env{tmpdir} if available, or to the directory specified by
+...@option{-p}, otherwise to @samp{/tmp}.  @var{template} must not
+contain slashes.  This option is deprecated; the use of @option{-p}
+without @option{-t} offers better defaults (by favoring the command
+line over @env{TMPDIR}) and more flexibility (by allowing intermediate
+directories).
+
+...@end table
+
+...@cindex exit status of @command{mktemp}
+Exit status:
+
+...@display
+0 if the file was created,
+1 otherwise.
+...@end display
+

 @node Working context
 @chapter Working context
-- 
1.6.4.2





Reply via email to