On 07/19/2010 10:45 AM, Corinna Vinschen wrote:
>> Okay to commit, along with a corresponding patch to doc/new-features.sgml
>> and a cygwin-specific patch to newlib's stdlib.h?
> 
> Yep.  Thanks for the patch.  I CCed the newlib list.  The change to
> newlib's stdlib.h is preapproved (#ifndef __STRICT_ANSI__ just like
> mkstemp et al).

For the record, here's the (pre-approved) patches for newlib and cygwin
documentation that I'm pushing in tandem with the original cygwin patch.
 It also fixes a couple of minor problems I noticed while in the area -
cygwin's cat has been binary-only for some time now, and newlib's
stdlib.h was not robust to a user file that used #define warning prior
to including the system header.

> 
> Btw., would you mind to enhance newlib's libc/stdio/mktemp.c in the same
> manner (_ELIX_LEVEL >= 4)?

The mkostemp[s] additions are guarded by the same levels as mkstemps,
since all three interfaces are equally non-portable.

-- 
Eric Blake   [email protected]    +1-801-349-2682
Libvirt virtualization library http://libvirt.org
From 6659d25bad3c852afab62536814ab253437e9ff6 Mon Sep 17 00:00:00 2001
From: Eric Blake <[email protected]>
Date: Mon, 19 Jul 2010 11:38:33 -0600
Subject: [PATCH] Document mkostemp.

* textbinary.sgml (textbin-devel): Document temp file behavior.
* new-features.sgml (ov-new1.7.6): Document mkostemp[s].
---
 winsup/doc/ChangeLog         |    5 +++++
 winsup/doc/new-features.sgml |    4 ++++
 winsup/doc/textbinary.sgml   |    7 ++++++-
 3 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/winsup/doc/ChangeLog b/winsup/doc/ChangeLog
index ca4b196..442b231 100644
--- a/winsup/doc/ChangeLog
+++ b/winsup/doc/ChangeLog
@@ -1,3 +1,8 @@
+2010-07-19  Eric Blake  <[email protected]>
+
+       * textbinary.sgml (textbin-devel): Document temp file behavior.
+       * new-features.sgml (ov-new1.7.6): Document mkostemp[s].
+
 2010-06-27  Yaakov Selkowitz  <[email protected]>

        * Makefile.in: Use "xmlto pdf" instead of docbook2pdf.
diff --git a/winsup/doc/new-features.sgml b/winsup/doc/new-features.sgml
index 97c2809..8cef1f9 100644
--- a/winsup/doc/new-features.sgml
+++ b/winsup/doc/new-features.sgml
@@ -30,6 +30,10 @@ strings.  locale(1) prints these values just as on Linux.  
nl_langinfo(3)
 allows to fetch them.
 </para></listitem>

+<listitem><para>
+New interfaces mkostemp(3) and mkostemps(3) are added.
+</para></listitem>
+
 </itemizedlist>

 </sect2>
diff --git a/winsup/doc/textbinary.sgml b/winsup/doc/textbinary.sgml
index 98aa2b1..7f4aae5 100644
--- a/winsup/doc/textbinary.sgml
+++ b/winsup/doc/textbinary.sgml
@@ -23,7 +23,7 @@ standard input and output) as text.  All other programs (such 
as
 would use binary mode.  In practice with Cygwin, programs that deal
 explicitly with object files specify binary mode (this is the case of
 <command>od</command>, which is helpful to diagnose CR problems).  Most
-other programs (such as <command>cat</command>, <command>cmp</command>,
+other programs (such as <command>sed</command>, <command>cmp</command>,
 <command>tr</command>) use the default mode.</para>

 </sect2>
@@ -113,6 +113,11 @@ specified with the flag <literal>O_BINARY</literal> and 
text mode with
 <literal>O_TEXT</literal>. These symbols are defined in
 <filename>fcntl.h</filename>.</para>

+<para>The <function>mkstemp()</function> and <function>mkstemps()</function>
+calls force binary mode.  Use <function>mkostemp()</function> or
+<function>mkostemps()</function> with the same flags
+as <function>open()</function> for more control on temporary files.</para>
+
 <para>In the <function>fopen()</function> and <function>popen()</function>
 function calls, binary mode can be specified by adding a <literal>b</literal>
 to the mode string. Text mode is specified by adding a <literal>t</literal>
-- 
1.7.1

From 50d0ac35a7506d2ec6f8daae175fec0f5f5d06c9 Mon Sep 17 00:00:00 2001
From: Eric Blake <[email protected]>
Date: Mon, 19 Jul 2010 11:23:15 -0600
Subject: [PATCH] Add mkostemp[s].

* libc/stdio/mktemp.c (_gettemp): Add parameter, all callers
changed.
(mkostemp, _mkostemp_r, mkostemps, _mkostemps_r): New interfaces,
for ELIX level 4.
* libc/include/stdlib.h (mktemp): Avoid namespace issues.
(mkostemp, mkostemps): Declare.
---
 newlib/ChangeLog             |    9 +++
 newlib/libc/include/stdlib.h |    8 ++-
 newlib/libc/stdio/mktemp.c   |  122 +++++++++++++++++++++++++++++++++---------
 3 files changed, 112 insertions(+), 27 deletions(-)

diff --git a/newlib/ChangeLog b/newlib/ChangeLog
index 18591ce..35a7cef 100644
--- a/newlib/ChangeLog
+++ b/newlib/ChangeLog
@@ -1,3 +1,12 @@
+2010-07-19  Eric Blake  <[email protected]>
+
+       * libc/stdio/mktemp.c (_gettemp): Add parameter, all callers
+       changed.
+       (mkostemp, _mkostemp_r, mkostemps, _mkostemps_r): New interfaces,
+       for ELIX level 4.
+       * libc/include/stdlib.h (mktemp): Avoid namespace issues.
+       (mkostemp, mkostemps): Declare.
+
 2010-07-13  Corinna Vinschen  <[email protected]>

        * libc/include/signal.h (sighandler_t): Only define if _POSIX_SOURCE
diff --git a/newlib/libc/include/stdlib.h b/newlib/libc/include/stdlib.h
index 453bb50..0bd2c7d 100644
--- a/newlib/libc/include/stdlib.h
+++ b/newlib/libc/include/stdlib.h
@@ -103,14 +103,18 @@ size_t    _EXFUN(_wcstombs_r,(struct _reent *, char *, 
const wchar_t *, size_t, _mb
 #ifndef __STRICT_ANSI__
 #ifndef _REENT_ONLY
 char * _EXFUN(mkdtemp,(char *));
+int    _EXFUN(mkostemp,(char *, int));
+int    _EXFUN(mkostemps,(char *, int, int));
 int    _EXFUN(mkstemp,(char *));
 int    _EXFUN(mkstemps,(char *, int));
-char * _EXFUN(mktemp,(char *) _ATTRIBUTE ((warning ("the use of `mktemp' is 
dangerous; use `mkstemp' instead"))));
+char * _EXFUN(mktemp,(char *) _ATTRIBUTE ((__warning__ ("the use of `mktemp' 
is dangerous; use `mkstemp' instead"))));
 #endif
 char * _EXFUN(_mkdtemp_r, (struct _reent *, char *));
+int    _EXFUN(_mkostemp_r, (struct _reent *, char *, int));
+int    _EXFUN(_mkostemps_r, (struct _reent *, char *, int, int));
 int    _EXFUN(_mkstemp_r, (struct _reent *, char *));
 int    _EXFUN(_mkstemps_r, (struct _reent *, char *, int));
-char * _EXFUN(_mktemp_r, (struct _reent *, char *) _ATTRIBUTE ((warning ("the 
use of `mktemp' is dangerous; use `mkstemp' instead"))));
+char * _EXFUN(_mktemp_r, (struct _reent *, char *) _ATTRIBUTE ((__warning__ 
("the use of `mktemp' is dangerous; use `mkstemp' instead"))));
 #endif
 _VOID  _EXFUN(qsort,(_PTR __base, size_t __nmemb, size_t __size, 
int(*_compar)(const _PTR, const _PTR)));
 int    _EXFUN(rand,(_VOID));
diff --git a/newlib/libc/stdio/mktemp.c b/newlib/libc/stdio/mktemp.c
index cfd74ad..1c5d76d 100644
--- a/newlib/libc/stdio/mktemp.c
+++ b/newlib/libc/stdio/mktemp.c
@@ -23,7 +23,8 @@

 /*
 FUNCTION
-<<mktemp>>, <<mkstemp>>, <<mkstemps>>---generate unused file name
+<<mktemp>>, <<mkstemp>>, <<mkostemp>>, <<mkstemps>>,
+<<mkostemps>>---generate unused file name
 <<mkdtemp>>---generate unused directory

 INDEX
@@ -35,6 +36,10 @@ INDEX
 INDEX
        mkstemps
 INDEX
+       mkostemp
+INDEX
+       mkostemps
+INDEX
        _mktemp_r
 INDEX
        _mkdtemp_r
@@ -42,6 +47,10 @@ INDEX
        _mkstemp_r
 INDEX
        _mkstemps_r
+INDEX
+       _mkostemp_r
+INDEX
+       _mkostemps_r

 ANSI_SYNOPSIS
        #include <stdlib.h>
@@ -49,19 +58,29 @@ ANSI_SYNOPSIS
        char *mkdtemp(char *<[path]>);
        int mkstemp(char *<[path]>);
        int mkstemps(char *<[path]>, int <[suffixlen]>);
+       int mkostemp(char *<[path]>, int <[flags]>);
+       int mkostemps(char *<[path]>, int <[suffixlen]>, int <[flags]>);

        char *_mktemp_r(struct _reent *<[reent]>, char *<[path]>);
        char *_mkdtemp_r(struct _reent *<[reent]>, char *<[path]>);
        int *_mkstemp_r(struct _reent *<[reent]>, char *<[path]>);
        int *_mkstemps_r(struct _reent *<[reent]>, char *<[path]>, int <[len]>);
+       int *_mkostemp_r(struct _reent *<[reent]>, char *<[path]>,
+                        int <[flags]>);
+       int *_mkostemps_r(struct _reent *<[reent]>, char *<[path]>, int <[len]>,
+                         int <[flags]>);

 DESCRIPTION
 <<mktemp>>, <<mkstemp>>, and <<mkstemps>> attempt to generate a file name
 that is not yet in use for any existing file.  <<mkstemp>> and <<mkstemps>>
 create the file and open it for reading and writing; <<mktemp>> simply
-generates the file name (making <<mktemp>> a security risk).  <<mkdtemp>>
-attempts to create a directory instead of a file, with a permissions
-mask of 0700.
+generates the file name (making <<mktemp>> a security risk).  <<mkostemp>>
+and <<mkostemps>> allow the addition of other <<open>> flags, such
+as <<O_CLOEXEC>>, <<O_APPEND>>, or <<O_SYNC>>.  On platforms with a
+separate text mode, <<mkstemp>> forces <<O_BINARY>>, while <<mkostemp>>
+allows the choice between <<O_BINARY>>, <<O_TEXT>>, or 0 for default.
+<<mkdtemp>> attempts to create a directory instead of a file, with a
+permissions mask of 0700.

 You supply a simple pattern for the generated file name, as the string
 at <[path]>.  The pattern should be a valid filename (including path
@@ -72,22 +91,25 @@ combination of digits and letters.  With <<mkstemps>>, the 
`<<X>>'
 characters end <[suffixlen]> bytes before the end of the string.

 The alternate functions <<_mktemp_r>>, <<_mkdtemp_r>>, <<_mkstemp_r>>,
-and <<_mkstemps_r>> are reentrant versions.  The extra argument <[reent]>
-is a pointer to a reentrancy structure.
+<<_mkostemp_r>>, <<_mkostemps_r>>, and <<_mkstemps_r>> are reentrant
+versions.  The extra argument <[reent]> is a pointer to a reentrancy
+structure.

 RETURNS
 <<mktemp>> returns the pointer <[path]> to the modified string
 representing an unused filename, unless it could not generate one, or
 the pattern you provided is not suitable for a filename; in that case,
-it returns <<NULL>>.
+it returns <<NULL>>.  Be aware that there is an inherent race between
+generating the name and attempting to create a file by that name;
+you are advised to use <<O_EXCL|O_CREAT>>.

 <<mkdtemp>> returns the pointer <[path]> to the modified string if the
 directory was created, otherwise it returns <<NULL>>.

-<<mkstemp>> and <<mkstemps>> return a file descriptor to the newly created
-file, unless it could not generate an unused filename, or the pattern you
-provided is not suitable for a filename; in that case, it returns
-<<-1>>.
+<<mkstemp>>, <<mkstemps>>, <<mkostemp>>, and <<mkostemps>> return a file
+descriptor to the newly created file, unless it could not generate an
+unused filename, or the pattern you provided is not suitable for a
+filename; in that case, it returns <<-1>>.

 NOTES
 Never use <<mktemp>>.  The generated filenames are easy to guess and
@@ -99,8 +121,9 @@ instead.  It doesn't suffer the race condition.
 PORTABILITY
 ANSI C does not require either <<mktemp>> or <<mkstemp>>; the System
 V Interface Definition requires <<mktemp>> as of Issue 2.  POSIX 2001
-requires <<mkstemp>>, and POSIX 2008 requires <<mkdtemp>>, but
-<<mkstemps>> is not standardized.
+requires <<mkstemp>>, and POSIX 2008 requires <<mkdtemp>> while
+deprecating <<mktemp>>.  <<mkstemps>>, <<mkostemp>>, and <<mkostemps>>
+are not standardized.

 Supporting OS subroutines required: <<getpid>>, <<mkdir>>, <<open>>, <<stat>>.
 */
@@ -116,12 +139,13 @@ Supporting OS subroutines required: <<getpid>>, 
<<mkdir>>, <<open>>, <<stat>>.
 #include <ctype.h>

 static int
-_DEFUN(_gettemp, (ptr, path, doopen, domkdir, suffixlen),
+_DEFUN(_gettemp, (ptr, path, doopen, domkdir, suffixlen, flags),
        struct _reent *ptr _AND
        char *path         _AND
        register int *doopen _AND
        int domkdir        _AND
-       size_t suffixlen)
+       size_t suffixlen   _AND
+       int flags)
 {
   register char *start, *trv;
   char *end;
@@ -200,8 +224,8 @@ _DEFUN(_gettemp, (ptr, path, doopen, domkdir, suffixlen),
 #endif /* _ELIX_LEVEL */
       if (doopen)
        {
-         if ((*doopen = _open_r (ptr, path, O_CREAT | O_EXCL | O_RDWR, 0600))
-             >= 0)
+         if ((*doopen = _open_r (ptr, path, O_CREAT | O_EXCL | O_RDWR | flags,
+                                 0600)) >= 0)
            return 1;
          if (ptr->_errno != EEXIST)
            return 0;
@@ -234,6 +258,10 @@ _DEFUN(_gettemp, (ptr, path, doopen, domkdir, suffixlen),
   /*NOTREACHED*/
 }

+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
 int
 _DEFUN(_mkstemp_r, (ptr, path),
        struct _reent *ptr _AND
@@ -241,7 +269,7 @@ _DEFUN(_mkstemp_r, (ptr, path),
 {
   int fd;

-  return (_gettemp (ptr, path, &fd, 0, 0) ? fd : -1);
+  return (_gettemp (ptr, path, &fd, 0, 0, O_BINARY) ? fd : -1);
 }

 #if !defined _ELIX_LEVEL || _ELIX_LEVEL >= 4
@@ -250,7 +278,7 @@ _DEFUN(_mkdtemp_r, (ptr, path),
        struct _reent *ptr _AND
        char *path)
 {
-  return (_gettemp (ptr, path, (int *) NULL, 1, 0) ? path : NULL);
+  return (_gettemp (ptr, path, (int *) NULL, 1, 0, 0) ? path : NULL);
 }

 int
@@ -261,7 +289,30 @@ _DEFUN(_mkstemps_r, (ptr, path, len),
 {
   int fd;

-  return (_gettemp (ptr, path, &fd, 0, len) ? fd : -1);
+  return (_gettemp (ptr, path, &fd, 0, len, O_BINARY) ? fd : -1);
+}
+
+int
+_DEFUN(_mkostemp_r, (ptr, path, flags),
+       struct _reent *ptr _AND
+       char *path _AND
+       int flags)
+{
+  int fd;
+
+  return (_gettemp (ptr, path, &fd, 0, 0, flags & ~O_ACCMODE) ? fd : -1);
+}
+
+int
+_DEFUN(_mkostemps_r, (ptr, path, len, flags),
+       struct _reent *ptr _AND
+       char *path _AND
+       int len _AND
+       int flags)
+{
+  int fd;
+
+  return (_gettemp (ptr, path, &fd, 0, len, flags & ~O_ACCMODE) ? fd : -1);
 }
 #endif /* _ELIX_LEVEL */

@@ -270,7 +321,7 @@ _DEFUN(_mktemp_r, (ptr, path),
        struct _reent *ptr _AND
        char *path)
 {
-  return (_gettemp (ptr, path, (int *) NULL, 0, 0) ? path : (char *) NULL);
+  return (_gettemp (ptr, path, (int *) NULL, 0, 0, 0) ? path : (char *) NULL);
 }

 #ifndef _REENT_ONLY
@@ -281,7 +332,7 @@ _DEFUN(mkstemp, (path),
 {
   int fd;

-  return (_gettemp (_REENT, path, &fd, 0, 0) ? fd : -1);
+  return (_gettemp (_REENT, path, &fd, 0, 0, O_BINARY) ? fd : -1);
 }

 # if !defined _ELIX_LEVEL || _ELIX_LEVEL >= 4
@@ -289,7 +340,7 @@ char *
 _DEFUN(mkdtemp, (path),
        char *path)
 {
-  return (_gettemp (_REENT, path, (int *) NULL, 1, 0) ? path : NULL);
+  return (_gettemp (_REENT, path, (int *) NULL, 1, 0, 0) ? path : NULL);
 }

 int
@@ -299,7 +350,28 @@ _DEFUN(mkstemps, (path, len),
 {
   int fd;

-  return (_gettemp (_REENT, path, &fd, 0, len) ? fd : -1);
+  return (_gettemp (_REENT, path, &fd, 0, len, O_BINARY) ? fd : -1);
+}
+
+int
+_DEFUN(mkostemp, (path, flags),
+       char *path _AND
+       int flags)
+{
+  int fd;
+
+  return (_gettemp (_REENT, path, &fd, 0, 0, flags & ~O_ACCMODE) ? fd : -1);
+}
+
+int
+_DEFUN(mkostemps, (path, len, flags),
+       char *path _AND
+       int len _AND
+       int flags)
+{
+  int fd;
+
+  return (_gettemp (_REENT, path, &fd, 0, len, flags & ~O_ACCMODE) ? fd : -1);
 }
 # endif /* _ELIX_LEVEL */

@@ -307,7 +379,7 @@ char *
 _DEFUN(mktemp, (path),
        char *path)
 {
-  return (_gettemp (_REENT, path, (int *) NULL, 0, 0) ? path : (char *) NULL);
+  return (_gettemp (_REENT, path, (int *) NULL, 0, 0, 0) ? path : (char *) 
NULL);
 }

 #endif /* ! defined (_REENT_ONLY) */
-- 
1.7.1

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to