[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

announce: new program: mktemp

From: Jim Meyering
Subject: announce: new program: mktemp
Date: Sun, 07 Oct 2007 20:30:09 +0200

I've just pushed a new mktemp program for coreutils.
ChangeLog below.

Why reimplement mktemp:

    Improved portability, robustness, and security.

Several weeks ago, I wrote most of the following to Todd Miller,
author of another mktemp tool/package.  I'm including an edited
version of that message here:

  Subject: adding mktemp to coreutils

  Hi Todd,

  Thanks for writing mktemp!
  I've been frustrated that it is not more widely available, so looked
  at its man page and wrote a mostly-compatible mktemp program that I am
  nearly prepared to add to the GNU coreutils package.

  Some of the differences:

    uses an adaptation of glibc's mkstemp (I've changed it to use
      coreutils' randint code, which makes it more secure, and lets
      it degrade gracefully when e.g., /dev/urandom is not usable;
      also, glibc's mkstemp uses a larger alphabet: 62 vs. 52, and
      gives up after 62^3 stat calls rather than your 52^6, tho, imho
      that latter doesn't matter).  Likewise for mkdtemp.
    provides long-style options, e.g., --directory (-d), --quiet, etc.
    uses gnulib's infrastructure for things like error reporting,
      and gettext support, like the rest of coreutils
    detects write failures
    currently doesn't support fewer than 3 X's in a template.  But
      I've already spec'd out code to allow just one or two X's, with
      a heuristic to keep it reasonably safe and with a guarantee that
      it will complete after no more than 62^X_COUNT stat calls.
    most importantly, using the above mkstemp implementation, names are
      less predictable, and are not generated in sequence upon retry:

      compare yours:
        $ for i in . . .; do mktemp -u _.XXXXXXX; done
        $ for i in . . .; do mktemp -u _.XXXXXXX; done

      with the new one:
        $ for i in . . .; do ./mktemp -u _.XXXXXXX; done
        $ for i in . . .; do ./mktemp -u _.XXXXXXX; done

  This is to give you a heads-up, hoping that you see this as a good thing.
  I preferred to rewrite this one, since it's so small.  My "main" is only
  about 70 lines, after all, if you don't count the ~50 of boilerplate
  declarations and getopt option handling loop.

  I see now (after rewriting) that you own the mktemp.org domain,
  and have a dedicated bug-tracker.  On the other hand, the last
  release was 4 years ago.

  Please take this as a compliment on the utility of your mktemp program,
  and let me know what you think.



He replied that he'd be happy to see mktemp more widely used, and
didn't care which version people use, as long as they're compatible.

Then I learned that on Gentoo, that same mktemp program is built so that
it requires a suffix of at least six X's in any template, and uses only the
last six of those.  In that mode, it also uses glibc's mkstemp function,
so predictable names aren't a real problem.  However, relying directly on
stock mkstemp from glibc means "mktemp t.XXXXX" fails on such a system,
since the template has only five X's.

So I've made Coreutils' mktemp work just like Todd's, even though I
dislike the way the -t option makes mktemp use $TMPDIR (if set),
even though another directory may have been specified via "-p DIR".
That means that people who want mktemp to honor their "-p DIR"
option will have to ensure that TMPDIR is unset first.

To provide similar functionality, but in a more usable manner,
I have added a new option that works like this:

  --tmpdir[=DIR]   interpret TEMPLATE relative to DIR.  If DIR is
                     not specified, use $TMPDIR if set, else /tmp.
                     With this option, TEMPLATE must not be an absolute name.
                     Unlike with -t, TEMPLATE may contain slashes, but even
                     here, mktemp still creates only the final component.

In addition, I've listed the -p and -t options as "deprecated",
but expect to retain support for them for years.

As always, feedback is welcome.

Here's the full --help output:
(no .texi addition, yet)

Usage: src/mktemp [OPTION]... [TEMPLATE]
Create a temporary file or directory, safely, and print its name.
If TEMPLATE is not specified, use tmp.XXXXXXXXXX.

  -d, --directory  create a directory, not a file
  -q, --quiet      suppress diagnostics about file/dir-creation failure
  -u, --dry-run    do not create anything; merely print a name (unsafe)
  --tmpdir[=DIR]   interpret TEMPLATE relative to DIR.  If DIR is
                     not specified, use $TMPDIR if set, else /tmp.
                     With this option, TEMPLATE must not be an absolute name.
                     Unlike with -t, TEMPLATE may contain slashes, but even
                     here, mktemp still creates only the final component.

  -p DIR           use DIR as a prefix; implies -t [deprecated]
  -t               interpret TEMPLATE as a single file name component,
                     relative to a directory: $TMPDIR, if set; else the
                     directory specified via -p; else /tmp [deprecated]

      --help     display this help and exit
      --version  output version information and exit

Report bugs to <address@hidden>.

2007-10-07  Jim Meyering  <address@hidden>


        New program: mktemp.
        * NEWS: Mention this.
        * README: Add mktemp to the list.
        * AUTHORS: Add this: mktemp: Jim Meyering
        * src/mktemp.c: New file.
        * src/Makefile.am (bin_PROGRAMS): Add mktemp.
        (mktemp_LDADD): Add $(LIB_GETHRXTIME).
        * man/mktemp.x: New file.
        * man/Makefile.am (dist_man_MANS): Add mktemp.1.
        (mktemp.1): New dependency.
        * man/.cvsignore: Add mktemp.1.
        * man/.gitignore: New file.
        * src/.cvsignore, src/.gitignore: Add mktemp.
        * tests/misc/mktemp: New file.
        * tests/misc/Makefile.am (TESTS): Add mktemp.
        * tests/Coreutils.pm (run_tests): Give the POST-test function
        access to stdout and stderr contents, so it can verify that
        the named-on-stdout file/dir does indeed exist and has proper
        permissions, etc.
        * POTFILES.in: Add src/mktemp.c.


        Make tempname more random, via the randint module.
        * gl/modules/tempname (Depends-on): Add randint and stdbool.
        * gl/lib/tempname.c: Include randint.h and stdbool.h.
        (uint64_t): Remove definition.  Not needed.
        [_LIBC] (RANDOM_BITS): Remove this block, now that we have proper
        random bits.
        (check_x_suffix): New function.
        (gen_tempname_len): Rename from __gen_tempname.
        Add a parameter, x_suffix_len, telling how many X's there must be at
        the end of the template.
        Use pseudo-random numbers all the way, rather than adding 7777
        from one iteration to the next.
        (__gen_tempname): New function, to call gen_tempname_len, requiring a
        suffix length of 6.
        * gl/lib/tempname.h: Add prototype for gen_tempname_len.


        Convert coreutils' rand*.{c,h,m4} into modules.
        First step: move these files to gl/lib:
        * lib/rand-isaac.c, lib/rand-isaac.h
        * lib/randint.c, lib/randint.h
        * lib/randperm.c, lib/randperm.h
        * lib/randread.c, lib/randread.h
        Step 2: add modules/rand* and remove now-unneeded .m4 files.
        * gl/modules/randint: New file.
        * gl/modules/randperm: New file.
        * gl/modules/randread: New file.
        * m4/randint.m4: Remove file.
        * m4/randperm.m4: Remove file.
        * m4/randread.m4: Remove file.
        Step 3: use the new modules
        * bootstrap.conf (gnulib_modules): Add randint and randperm.
        * m4/prereq.m4 (gl_RANDINT, gl_RANDREAD, gl_RANDPERM): Don't require;
        These have been removed.
        (gl_ROOT_DEV_INO): Don't require; already handled via bootstrap.conf.


        Copy from gnulib the parts of tempname that we'll modify.
        * gl/lib/tempname.c: Copy from gnulib.
        * gl/lib/tempname.h: Likewise.
        * gl/modules/tempname: Likewise.
        Allow GPLv2 on temporarily(?)-imported file from gnulib/libc.
        * .x-sc_GPL_version: New file.
        * Makefile.am (EXTRA_DIST): Add .x-sc_GPL_version

reply via email to

[Prev in Thread] Current Thread [Next in Thread]