mktemp, mkstemp, mkstemps, mkdtemp - make temporary file
name (unique)
#include <unistd.h>
char *
mktemp(char *template);
int
mkstemp(char *template);
int
mkstemps(char *template, int suffixlen);
char *
mkdtemp(char *template);
The mktemp() function takes the given file name template and
overwrites a
portion of it to create a file name. This file name is
unique and suitable
for use by the application. The template may be any
file name with
some number of `X's appended to it, for example
/tmp/temp.XXXX. The
trailing `X's are replaced with the current process number
and/or a
unique letter combination. The number of unique file names
mktemp() can
return depends on the number of `X's provided; six `X's
will result in
mktemp() testing roughly 26 ** 6 combinations. At least 6
`X's should be
used, though 10 is much better.
The mkstemp() function makes the same replacement to the
template and
creates the template file, mode 0600, returning a file descriptor opened
for reading and writing. This avoids the race between testing for a
file's existence and opening it for use.
The mkstemps() function acts the same as mkstemp(), except
it permits a
suffix to exist in the template. The template should be of
the form
/tmp/tmpXXXXXXXXXXsuffix. mkstemps() is told the length of
the suffix
string, i.e., strlen("suffix");
The mkdtemp() function makes the same replacement to the
template as in
mktemp() and creates the template directory, mode 0700.
The mktemp() and mkdtemp() functions return a pointer to the
template on
success and NULL on failure. The mkstemp() function returns
-1 if no
suitable file could be created. If either call fails an error code is
placed in the global variable errno.
Quite often a programmer will want to replace a use of
mktemp() with
mkstemp(), usually to avoid the problems described above.
Doing this
correctly requires a good understanding of the code in question.
For instance, code of this form:
char sfn[15] = "";
FILE *sfp;
strlcpy(sfn, "/tmp/ed.XXXXXXXXXX", sizeof sfn);
if (mktemp(sfn) == NULL || (sfp = fopen(sfn, "w+")) ==
NULL) {
fprintf(stderr, "%s: %s0, sfn, strerror(errno));
return (NULL);
}
return (sfp);
should be rewritten like this:
char sfn[15] = "";
FILE *sfp;
int fd = -1;
strlcpy(sfn, "/tmp/ed.XXXXXXXXXX", sizeof sfn);
if ((fd = mkstemp(sfn)) == -1 ||
(sfp = fdopen(fd, "w+")) == NULL) {
if (fd != -1) {
unlink(sfn);
close(fd);
}
fprintf(stderr, "%s: %s0, sfn, strerror(errno));
return (NULL);
}
return (sfp);
Often one will find code which uses mktemp() very early on,
perhaps to
globally initialize the template nicely, but the code which
calls open(2)
or fopen(3) on that filename will occur much later. (In almost all cases,
the use of fopen(3) will mean that the flags O_CREAT |
O_EXCL are not
given to open(2), and thus a symbolic link race becomes possible, hence
making necessary the use of fdopen(3) as seen above.) Furthermore, one
must be careful about code which opens, closes, and then reopens the
file in question. Finally, one must ensure that upon error
the temporary
file is removed correctly.
There are also cases where modifying the code to use
mktemp(), in concert
with open(2) using the flags O_CREAT | O_EXCL, is better, as
long as the
code retries a new template if open(2) fails with an errno
of EEXIST.
The mkstemp() and mkdtemp() functions may set errno to one
of the following
values:
[ENOTDIR] The pathname portion of the template is not an
existing directory.
The mkstemp() and mkdtemp() functions may also set errno to
any value
specified by the stat(2) function.
The mkstemp() function may also set errno to any value specified by the
open(2) function.
The mkstemps() function may also set errno to any value
specified by the
open(2) function or,
[EINVAL] The suffix length is longer than the template
length.
The mkdtemp() function may also set errno to any value specified by the
mkdir(2) function.
chmod(2), getpid(2), mkdir(2), open(2), stat(2), tempnam(3),
tmpfile(3),
tmpnam(3)
A mktemp() function appeared in Version 7 AT&T UNIX. The
mkdtemp() function
appeared in OpenBSD 2.2. The mkstemp() function appeared in 4.4BSD.
The mkstemps() function appeared in OpenBSD 2.3.
For mktemp() there is an obvious race between file name selection and
file creation and deletion: the program is typically written
to call
tmpnam(3), tempnam(3), or mktemp(). Subsequently, the program calls
open(2) or fopen(3) and erroneously opens a file (or symbolic link, FIFO
or other device) that the attacker has created in the expected file location.
Hence mkstemp() is recommended, since it atomically
creates the
file. An attacker can guess the filenames produced by
mktemp(). Whenever
it is possible, mkstemp() or mkdtemp() should be used instead.
For this reason, ld(1) will output a warning message whenever it links
code that uses mktemp().
The mkdtemp() and mkstemps() functions are non-standard and
should not be
used if portability is required.
OpenBSD 3.6 June 4, 1993
[ Back ] |