[Top][All Lists]
[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