bug-coreutils
[Top][All Lists]
Advanced

[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
        _.Mt31935
        _.fQ31936
        _.BW31937
        $ for i in . . .; do mktemp -u _.XXXXXXX; done
        _.If31967
        _.IJ31968
        _.lb31969

      with the new one:
        $ for i in . . .; do ./mktemp -u _.XXXXXXX; done
        _.2ojBe7Z
        _.0oB0isC
        _.yCyvyU8
        $ for i in . . .; do ./mktemp -u _.XXXXXXX; done
        _.W4GLDh7
        _.IwpMW0a
        _.vfNrmUz

  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.

  Regards,

  Jim
===========================

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>

http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=99b039fead8d72

        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.
        [po/ChangeLog]
        * POTFILES.in: Add src/mktemp.c.

http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=7eab7d027e624

        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.

http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=58a7ead41d056

        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.

http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commit;h=696f4a8042e11f6ca

        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]