m4-patches
[Top][All Lists]
Advanced

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

Re: branch-1_4 maketemp cleanup


From: Eric Blake
Subject: Re: branch-1_4 maketemp cleanup
Date: Sat, 21 Oct 2006 16:11:48 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Thunderbird/1.5.0.7 Mnenhy/0.7.4.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi Gary,

According to Gary V. Vaughan on 10/20/2006 8:29 PM:
> On 19 Oct 2006, at 18:00, Eric Blake wrote:
>>> Would it make sense to also implement a mkdtemp macro for head?
> 
> Sure, that seems like a great idea to me.

Done:

2006-10-21  Eric Blake  <address@hidden>

        * modules/m4.c (m4_make_temp): Change signature.
        (maketemp, mkstemp): Update callers.
        * modules/m4.h (m4_make_temp_func): New export.
        * modules/gnu.c (mkdtemp): New macro.
        * doc/m4.texinfo (Operation modes): Document interaction with
        --safer.
        (Mkdtemp): New node.
        * tests/builtins.at (mkdtemp): New test.
        (mkstemp): Check for umask effect.
        * NEWS: Document new builtin.

- --
Life is short - so eat dessert first!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.1 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD0DBQFFOpsk84KuGfSFAYARAvQFAJjKq92/c4a4ebU5twAwFarasj/+AJICFMj6
t6FYNAILngatiM1rB/aw
=94Qf
-----END PGP SIGNATURE-----
Index: NEWS
===================================================================
RCS file: /sources/m4/m4/NEWS,v
retrieving revision 1.28
diff -u -p -r1.28 NEWS
--- NEWS        19 Oct 2006 23:13:45 -0000      1.28
+++ NEWS        21 Oct 2006 22:06:31 -0000
@@ -50,13 +50,17 @@ promoted to 2.0.
   the include path, rather than always searching `.' first.
 
 * New `--safer' command-line option cripples the potentially unsafe
-  macros `debugfile', `syscmd', `esyscmd', `maketemp', and `mkstemp'.
+  macros `debugfile', `esyscmd', `maketemp', `mkdtemp', `mkstemp', and
+  `syscmd'.
 
 * The `maketemp' builtin now always warns that it is obsolete, even in GNU
   mode where it uses the same secure algorithm as `mkstemp', because of
   the recommendation of POSIX to obsolete `maketemp' as inherently
   insecure when obeying POSIX.
 
+* New builtin `mkdtemp' parallels `mkstemp', but allows the creation of
+  temporary directories instead of files.
+
 * New `-b'/`--batch' command line option to force non-interactive mode.
   Also, in addition to `-e'/`--interactive' requesting interactive mode, m4
   now follows the lead of sh, and automatically enters interactive mode
Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.70
diff -u -p -r1.70 m4.texinfo
--- doc/m4.texinfo      21 Oct 2006 15:23:56 -0000      1.70
+++ doc/m4.texinfo      21 Oct 2006 22:06:32 -0000
@@ -260,6 +260,7 @@ Macros for running shell commands
 * Esyscmd::                     Reading the output of commands
 * Sysval::                      Exit status
 * Mkstemp::                     Making temporary files
+* Mkdtemp::                     Making temporary directories
 
 Miscellaneous builtin macros
 
@@ -646,11 +647,11 @@ format and meaning of @var{RESYNTAX-SPEC
 
 @item --safer
 Cripple the builtins @code{maketemp}, @code{mkstemp} (@pxref{Mkstemp}),
address@hidden (@pxref{Debugfile}), @code{syscmd} (@pxref{Syscmd}),
-and @code{esyscmd} (@pxref{Esyscmd}), since they can perform potentially
-unsafe actions.  An attempt to use these macros will result in an error.
-This option is intended to make it safer to preprocess an input file of
-unknown origin.
address@hidden (@pxref{Mkdtemp}), @code{debugfile} (@pxref{Debugfile}),
address@hidden (@pxref{Syscmd}), and @code{esyscmd} (@pxref{Esyscmd}),
+since they can perform potentially unsafe actions.  An attempt to use
+these macros will result in an error.  This option is intended to make
+it safer to preprocess an input file of unknown origin.
 @end table
 
 @node Dynamic loading features
@@ -2078,6 +2079,7 @@ regular expression.
 
 The expansion of @code{renamesyms} is void.
 The macro @code{renamesyms} is recognized only with parameters.
+This macro was added in M4 2.0.
 @end deffn
 
 Here is an example that performs the same renaming as the
@@ -2302,6 +2304,7 @@ programs.
 
 When given arguments, @code{m4symbols} returns the sorted subset of the
 @var{names} currently defined, and silently ignores the rest.
+This macro was added in M4 2.0.
 @end deffn
 
 @example
@@ -5147,6 +5150,7 @@ commands from within @code{m4}.
 * Esyscmd::                     Reading the output of commands
 * Sysval::                      Exit status
 * Mkstemp::                     Making temporary files
+* Mkdtemp::                     Making temporary directories
 @end menu
 
 @node Platform macros
@@ -5403,6 +5407,81 @@ syscmd(`echo foo??????')dnl
 @result{}foo??????
 @end example
 
address@hidden Mkdtemp
address@hidden Making temporary directories
+
address@hidden temporary directory
address@hidden directories, temporary
address@hidden @acronym{GNU} extensions
+Commands specified to @code{syscmd} or @code{esyscmd} might need a
+temporary directory, for holding multiple temporary files; such a
+directory can be created with @code{mkdtemp}:
+
address@hidden {Builtin (gnu)} mkdtemp (@var{template})
+Expands to a name of a new, empty directory, made from the string
address@hidden, which should end with the string @samp{XXXXXX}.  The six
address@hidden characters are then replaced with random characters matching
+the regular expression @samp{[a-zA-Z0-9._-]}, in order to make the name
+unique.  If fewer than six @samp{X} characters are found at the end of
address@hidden, the result will be longer than the template.  The
+created directory will have access permissions as if by @kbd{chmod
+=rwx,go=}, meaning that the current umask of the @code{m4} process is
+taken into account, and at most only the current user can read, write,
+and search the directory.
+
+The expansion is void and an error issued if a temporary directory could
+not be created.
+
+When the @option{--safer} option (@pxref{Operation modes, Invoking m4})
+is in effect, @code{mkdtemp} results in an error, since otherwise an
+input file could perform a mild denial-of-service attack by filling up a
+disk with multiple directories.
+
+The macro @code{mkdtemp} is recognized only with parameters.
+This macro was added in M4 2.0.
address@hidden deffn
+
+If you try this next example, you will most likely get different output
+for the directory names, since the replacement characters are randomly
+chosen:
+
address@hidden ignore
address@hidden
+$ @kbd{m4}
+mkdtemp(`/tmp/fooXXXXXX')
address@hidden/tmp/foo2h89Vo
+mkdtemp(`dir)
address@hidden
address@hidden example
+
address@hidden options: --safer
address@hidden status: 1
address@hidden
+$ @kbd{m4 --safer}
+mkdtemp(`/tmp/fooXXXXXX')
address@hidden:stdin:1: mkdtemp: disabled by --safer
address@hidden
address@hidden example
+
+Multiple calls with the same template will generate multiple
+directories.
+
address@hidden
+$ @kbd{m4}
+syscmd(`echo foo??????')dnl
address@hidden
+define(`dir1', mkdtemp(`fooXXXXXX'))dnl
+ifelse(esyscmd(`echo foo??????'), `foo??????', `no dir', `created')
address@hidden
+define(`dir2', mkdtemp(`fooXXXXXX'))dnl
+ifelse(dir1, dir2, `same', `different directories')
address@hidden directories
+syscmd(`rmdir 'dir1 dir2)
address@hidden
+sysval
address@hidden
address@hidden example
+
 @node Miscellaneous
 @chapter Miscellaneous builtin macros
 
Index: modules/gnu.c
===================================================================
RCS file: /sources/m4/m4/modules/gnu.c,v
retrieving revision 1.64
diff -u -p -r1.64 gnu.c
--- modules/gnu.c       13 Oct 2006 16:46:47 -0000      1.64
+++ modules/gnu.c       21 Oct 2006 22:06:32 -0000
@@ -55,6 +55,7 @@
   BUILTIN (esyscmd,    false,  true,   true,   1,      1  )    \
   BUILTIN (format,     false,  true,   false,  1,      -1 )    \
   BUILTIN (indir,      true,   true,   false,  1,      -1 )    \
+  BUILTIN (mkdtemp,    false,  true,   false,  1,      1  )    \
   BUILTIN (patsubst,   false,  true,   true,   2,      4  )    \
   BUILTIN (regexp,     false,  true,   true,   2,      4  )    \
   BUILTIN (renamesyms, false,  true,   false,  2,      3  )    \
@@ -570,6 +571,22 @@ M4BUILTIN_HANDLER (indir)
 }
 
 
+/* The builtin "mkdtemp" allows creation of temporary directories.  */
+
+/**
+ * mkdtemp(TEMPLATE)
+ **/
+M4BUILTIN_HANDLER (mkdtemp)
+{
+  M4_MODULE_IMPORT (m4, m4_make_temp);
+
+  if (m4_make_temp)
+    m4_make_temp (context, obs, M4ARG (0), M4ARG (1), true);
+  else
+    assert (!"Unable to import from m4 module");
+}
+
+
 /* Substitute all matches of a regexp occuring in a string.  Each match of
    the second argument (a regexp) in the first argument is changed to the
    third argument, with \& substituted by the matched text, and \N
Index: modules/m4.c
===================================================================
RCS file: /sources/m4/m4/modules/m4.c,v
retrieving revision 1.84
diff -u -p -r1.84 m4.c
--- modules/m4.c        19 Oct 2006 23:13:45 -0000      1.84
+++ modules/m4.c        21 Oct 2006 22:06:32 -0000
@@ -53,6 +53,8 @@ extern void m4_sysval_flush  (m4 *contex
 extern void m4_dump_symbols  (m4 *context, m4_dump_symbol_data *data, int argc,
                              m4_symbol_value **argv, bool complain);
 extern const char *m4_expand_ranges (const char *s, m4_obstack *obs);
+extern void m4_make_temp     (m4 *context, m4_obstack *obs, const char *macro,
+                             const char *name, bool dir);
 
 /* Maintain each of the builtins implemented in this modules along
    with their details in a single table for easy maintenance.
@@ -673,17 +675,17 @@ M4BUILTIN_HANDLER (sinclude)
 /* Use the first argument as at template for a temporary file name.
    FIXME - should we add a mkdtemp builtin in the gnu module, then
    export this function as a helper to that?  */
-static void
-m4_make_temp (m4 *context, m4_obstack *obs, int argc, m4_symbol_value **argv)
+void
+m4_make_temp (m4 *context, m4_obstack *obs, const char *macro,
+             const char *name, bool dir)
 {
   int fd;
   int len;
   int i;
-  const char *name = M4ARG (1);
 
   if (m4_get_safer_opt (context))
     {
-      m4_error (context, 0, 0, _("%s: disabled by --safer"), M4ARG (0));
+      m4_error (context, 0, 0, _("%s: disabled by --safer"), macro);
       return;
     }
 
@@ -699,16 +701,25 @@ m4_make_temp (m4 *context, m4_obstack *o
     obstack_1grow (obs, 'X');
   obstack_1grow (obs, '\0');
 
+  /* Make the temporary object.  */
   errno = 0;
-  fd = mkstemp (obstack_base (obs));
+  if (dir)
+    fd = mkdtemp (obstack_base (obs)) ? 0 : -1;
+  else
+    fd = mkstemp (obstack_base (obs));
   if (fd < 0)
     {
-      m4_error (context, 0, errno, _("%s: cannot create tempfile `%s'"),
-               M4ARG (0), name);
+      /* This use of _() will need to change if xgettext ever changes
+        its undocumented behavior of parsing both string options.  */
+
+      m4_error (context, 0, errno,
+               _(dir ? "%s: cannot create directory `%s'"
+                 : "%s: cannot create file `%s'"),
+               macro, name);
       obstack_free (obs, obstack_finish (obs));
     }
-  else
-     close (fd);
+  else if (! dir)
+    close (fd);
 }
 
 /* Use the first argument as at template for a temporary file name.  */
@@ -748,13 +759,13 @@ M4BUILTIN_HANDLER (maketemp)
        }
     }
   else
-    m4_make_temp (context, obs, argc, argv);
+    m4_make_temp (context, obs, M4ARG (0), M4ARG (1), false);
 }
 
 /* Use the first argument as a template for a temporary file name.  */
 M4BUILTIN_HANDLER (mkstemp)
 {
-  m4_make_temp (context, obs, argc, argv);
+  m4_make_temp (context, obs, M4ARG (0), M4ARG (1), false);
 }
 
 /* Print all arguments on standard error.  */
Index: modules/m4.h
===================================================================
RCS file: /sources/m4/m4/modules/m4.h,v
retrieving revision 1.6
diff -u -p -r1.6 m4.h
--- modules/m4.h        1 May 2005 11:10:05 -0000       1.6
+++ modules/m4.h        21 Oct 2006 22:06:32 -0000
@@ -1,5 +1,5 @@
 /* GNU m4 -- A simple macro processor
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2006 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -39,8 +39,11 @@ typedef struct
 typedef void m4_sysval_flush_func (m4 *context);
 typedef void m4_set_sysval_func (int value);
 typedef void m4_dump_symbols_func (m4 *context, m4_dump_symbol_data *data,
-               int argc, m4_symbol_value **argv, bool complain);
-typedef const char *m4_expand_ranges_func  (const char *s, m4_obstack *obs);
+                                  int argc, m4_symbol_value **argv,
+                                  bool complain);
+typedef const char *m4_expand_ranges_func (const char *s, m4_obstack *obs);
+typedef void m4_make_temp_func (m4 *context, m4_obstack *obs,
+                               const char *macro, const char *name, bool dir);
 
 END_C_DECLS
 
Index: tests/builtins.at
===================================================================
RCS file: /sources/m4/m4/tests/builtins.at,v
retrieving revision 1.25
diff -u -p -r1.25 builtins.at
--- tests/builtins.at   19 Oct 2006 23:13:45 -0000      1.25
+++ tests/builtins.at   21 Oct 2006 22:06:32 -0000
@@ -495,6 +495,32 @@ AT_CHECK_M4([indir.m4], 0, expout)
 AT_CLEANUP
 
 
+## ------- ##
+## mkdtemp ##
+## ------- ##
+
+AT_SETUP([mkdtemp])
+
+dnl Check that on error, the expansion is void
+AT_DATA([[in]],
+[[mkdtemp(`no_such_dir/m4-fooXXXXXX')
+]])
+AT_CHECK_M4([in], [1], [[
+]], [[m4:in:1: mkdtemp: cannot create directory `no_such_dir/m4-fooXXXXXX': No 
such file or directory
+]])
+
+dnl Check that umask has an effect
+AT_DATA([[in]],
+[[substr(esyscmd(`ls -ld 'mkdtemp(`m4-fooXXXXXX')), `0', `10')
+]])
+AT_CHECK([m4 < in], [0], [[drwx------
+]])
+AT_CHECK([umask 700; m4 < in], [0], [[d---------
+]])
+
+AT_CLEANUP
+
+
 ## -------- ##
 ## maketemp ##
 ## -------- ##
@@ -506,7 +532,16 @@ AT_DATA([[in]],
 [[mkstemp(`no_such_dir/m4-fooXXXXXX')
 ]])
 AT_CHECK_M4([in], [1], [[
-]], [[m4:in:1: mkstemp: cannot create tempfile `no_such_dir/m4-fooXXXXXX': No 
such file or directory
+]], [[m4:in:1: mkstemp: cannot create file `no_such_dir/m4-fooXXXXXX': No such 
file or directory
+]])
+
+dnl Check that umask has an effect
+AT_DATA([[in]],
+[[substr(esyscmd(`ls -ld 'mkstemp(`m4-fooXXXXXX')), `0', `10')
+]])
+AT_CHECK([m4 < in], [0], [[-rw-------
+]])
+AT_CHECK([umask 700; m4 < in], [0], [[----------
 ]])
 
 dnl Check for Solaris compatibility of maketemp.  Hopefully the pid is

reply via email to

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