This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: add mkstemps


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

According to Jeff Johnston on 6/30/2009 3:00 PM:
> Please post any updated patches you intend to check-in as it makes it
> hard to review based on
> my low ESP skills :)

Here's the latest draft of both patches:

2009-07-01  Eric Blake  <ebb9@byu.net>

	Add mkdtemp, mkstemps.
	* libc/stdio/mktemp.c: Fix documentation.
	(_gettemp): Add domkdir and length parameters.  Check for
	insufficient 'X' suffix.  Drop cygwin-specific code.
	(_mkstemp_r, _mktemp_r, mkstemp, mktemp): Adjust clients.
	(_mkdtemp_r, _mkstemps_r, mkdtemp, mkstemps): New functions.
	* libc/include/stdlib.h (_mkdtemp_r, _mkstemps_r, mkdtemp)
	(mkstemps): Declare them.

	Add fpurge.
	* libc/stdio/fpurge.c (fpurge, _fpurge_r): New file.
	* libc/stdio/Makefile.am (ELIX_4_SOURCES, CHEWOUT_FILES, fpurge):
	Build it.
	* libc/stdio/Makefile.in: Regenerated.
	* libc/include/stdio.h (fpurge, _fpurge_r): New declarations.
	* libc/stdio/stdio.tex: Build documentation.

- --
Don't work too hard, make some time for fun as well!

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

iEYEARECAAYFAkpKtYYACgkQ84KuGfSFAYCyuQCfYg24RwwVAIm454c0x20iANzX
JXkAoNGZSNpgyPTvj9/NaIxhLymmkngL
=j4qF
-----END PGP SIGNATURE-----
Index: libc/stdio/fpurge.c
===================================================================
RCS file: libc/stdio/fpurge.c
diff -N libc/stdio/fpurge.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libc/stdio/fpurge.c	1 Jul 2009 00:59:08 -0000
@@ -0,0 +1,90 @@
+/* Copyright (C) 2009 Eric Blake
+ * Permission to use, copy, modify, and distribute this software
+ * is freely granted, provided that this notice is preserved.
+ */
+
+/*
+FUNCTION
+<<fpurge>>---discard pending file I/O
+
+INDEX
+	fpurge
+INDEX
+	_fpurge_r
+
+ANSI_SYNOPSIS
+	#include <stdio.h>
+	int fpurge(FILE *<[fp]>);
+
+	int _fpurge_r(struct _reent *<[reent]>, FILE *<[fp]>);
+
+DESCRIPTION
+Use <<fpurge>> to clear all buffers of the given stream.  For output
+streams, this discards data not yet written to disk.  For input streams,
+this discards any data from <<ungetc>> and any data retrieved from disk
+but not yet read via <<getc>>.  This is more severe than <<fflush>>,
+and generally is only needed when manually altering the underlying file
+descriptor of a stream.
+
+The alternate function <<_fpurge_r>> is a reentrant version, where the
+extra argument <[reent]> is a pointer to a reentrancy structure, and
+<[fp]> must not be NULL.
+
+RETURNS
+<<fpurge>> returns <<0>> unless <[fp]> is not valid, in which case it
+returns <<EOF>> and sets <<errno>>.
+
+PORTABILITY
+These functions are not portable to any standard.
+
+No supporting OS subroutines are required.
+*/
+
+#include <_ansi.h>
+#include <stdio.h>
+#include <errno.h>
+#include "local.h"
+
+/* Discard I/O from a single file.  */
+
+int
+_DEFUN(_fpurge_r, (ptr, fp),
+       struct _reent *ptr _AND
+       register FILE * fp)
+{
+  int t;
+
+  CHECK_INIT (ptr, fp);
+
+  _flockfile (fp);
+
+  t = fp->_flags;
+  if (!t)
+    {
+      ptr->_errno = EBADF;
+      _funlockfile (fp);
+      return EOF;
+    }
+  fp->_p = fp->_bf._base;
+  if ((t & __SWR) == 0)
+    {
+      fp->_r = 0;
+      if (HASUB (fp))
+	FREEUB (ptr, fp);
+    }
+  else
+    fp->_w = t & (__SLBF | __SNBF) ? 0 : fp->_bf._size;
+  _funlockfile (fp);
+  return 0;
+}
+
+#ifndef _REENT_ONLY
+
+int
+_DEFUN(fpurge, (fp),
+       register FILE * fp)
+{
+  return _fpurge_r (_REENT, fp);
+}
+
+#endif /* _REENT_ONLY */
Index: libc/stdio/Makefile.am
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/Makefile.am,v
retrieving revision 1.31
diff -u -p -r1.31 Makefile.am
--- libc/stdio/Makefile.am	11 Mar 2009 11:53:22 -0000	1.31
+++ libc/stdio/Makefile.am	1 Jul 2009 00:59:08 -0000
@@ -121,6 +121,7 @@ ELIX_4_SOURCES = \
 	fgetws.c		\
 	fmemopen.c		\
 	fopencookie.c		\
+	fpurge.c		\
 	fputwc.c		\
 	fputws.c		\
 	funopen.c		\
@@ -250,6 +251,7 @@ CHEWOUT_FILES = \
 	fmemopen.def		\
 	fopen.def		\
 	fopencookie.def		\
+	fpurge.def		\
 	fputc.def		\
 	fputs.def		\
 	fputwc.def		\
@@ -331,6 +333,7 @@ $(lpfx)findfp.$(oext): local.h
 $(lpfx)fmemopen.$(oext): local.h
 $(lpfx)fopen.$(oext): local.h
 $(lpfx)fopencookie.$(oext): local.h
+$(lpfx)fpurge.$(oext): local.h
 $(lpfx)fputs.$(oext): fvwrite.h
 $(lpfx)fputwc.$(oext): local.h
 $(lpfx)fputws.$(oext): local.h fvwrite.h
Index: libc/stdio/Makefile.in
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/Makefile.in,v
retrieving revision 1.45
diff -u -p -r1.45 Makefile.in
--- libc/stdio/Makefile.in	11 Mar 2009 11:53:22 -0000	1.45
+++ libc/stdio/Makefile.in	1 Jul 2009 00:59:08 -0000
@@ -38,7 +38,6 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-LIBOBJDIR =
 DIST_COMMON = $(srcdir)/../../Makefile.shared $(srcdir)/Makefile.in \
 	$(srcdir)/Makefile.am
 subdir = stdio
@@ -124,6 +123,7 @@ am__objects_1 = lib_a-clearerr.$(OBJEXT)
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	lib_a-fgetws.$(OBJEXT) \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	lib_a-fmemopen.$(OBJEXT) \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	lib_a-fopencookie.$(OBJEXT) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	lib_a-fpurge.$(OBJEXT) \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	lib_a-fputwc.$(OBJEXT) \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	lib_a-fputws.$(OBJEXT) \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	lib_a-funopen.$(OBJEXT) \
@@ -178,6 +178,7 @@ am__objects_4 = clearerr.lo fclose.lo fd
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	fgetws.lo \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	fmemopen.lo \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	fopencookie.lo \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	fpurge.lo \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	fputwc.lo \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	fputws.lo \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	funopen.lo \
@@ -263,6 +264,8 @@ ENABLE_NEWLIB_ICONV_TRUE = @ENABLE_NEWLI
 EXEEXT = @EXEEXT@
 FGREP = @FGREP@
 GREP = @GREP@
+HAVE_LONG_DOUBLE_FALSE = @HAVE_LONG_DOUBLE_FALSE@
+HAVE_LONG_DOUBLE_TRUE = @HAVE_LONG_DOUBLE_TRUE@
 HAVE_POSIX_DIR_FALSE = @HAVE_POSIX_DIR_FALSE@
 HAVE_POSIX_DIR_TRUE = @HAVE_POSIX_DIR_TRUE@
 HAVE_SIGNAL_DIR_FALSE = @HAVE_SIGNAL_DIR_FALSE@
@@ -329,8 +332,20 @@ STRIP = @STRIP@
 USE_LIBTOOL_FALSE = @USE_LIBTOOL_FALSE@
 USE_LIBTOOL_TRUE = @USE_LIBTOOL_TRUE@
 VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_AS = @ac_ct_AS@
 ac_ct_CC = @ac_ct_CC@
+ac_ct_DLLTOOL = @ac_ct_DLLTOOL@
+ac_ct_DSYMUTIL = @ac_ct_DSYMUTIL@
 ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+ac_ct_LIPO = @ac_ct_LIPO@
+ac_ct_NMEDIT = @ac_ct_NMEDIT@
+ac_ct_OBJDUMP = @ac_ct_OBJDUMP@
+ac_ct_OTOOL = @ac_ct_OTOOL@
+ac_ct_OTOOL64 = @ac_ct_OTOOL64@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_READELF = @ac_ct_READELF@
+ac_ct_STRIP = @ac_ct_STRIP@
 aext = @aext@
 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
@@ -346,9 +361,6 @@ build_cpu = @build_cpu@
 build_os = @build_os@
 build_vendor = @build_vendor@
 datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
 exec_prefix = @exec_prefix@
 extra_dir = @extra_dir@
 host = @host@
@@ -356,14 +368,12 @@ host_alias = @host_alias@
 host_cpu = @host_cpu@
 host_os = @host_os@
 host_vendor = @host_vendor@
-htmldir = @htmldir@
 includedir = @includedir@
 infodir = @infodir@
 install_sh = @install_sh@
 libdir = @libdir@
 libexecdir = @libexecdir@
 libm_machine_dir = @libm_machine_dir@
-localedir = @localedir@
 localstatedir = @localstatedir@
 lpfx = @lpfx@
 lt_ECHO = @lt_ECHO@
@@ -373,10 +383,8 @@ mkdir_p = @mkdir_p@
 newlib_basedir = @newlib_basedir@
 oext = @oext@
 oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
-psdir = @psdir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 subdirs = @subdirs@
@@ -488,6 +496,7 @@ GENERAL_SOURCES = \
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	fgetws.c		\
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	fmemopen.c		\
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	fopencookie.c		\
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	fpurge.c		\
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	fputwc.c		\
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	fputws.c		\
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	funopen.c		\
@@ -558,6 +567,7 @@ CHEWOUT_FILES = \
 	fmemopen.def		\
 	fopen.def		\
 	fopencookie.def		\
+	fpurge.def		\
 	fputc.def		\
 	fputs.def		\
 	fputwc.def		\
@@ -1268,6 +1278,12 @@ lib_a-fopencookie.o: fopencookie.c
 lib_a-fopencookie.obj: fopencookie.c
 	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-fopencookie.obj `if test -f 'fopencookie.c'; then $(CYGPATH_W) 'fopencookie.c'; else $(CYGPATH_W) '$(srcdir)/fopencookie.c'; fi`
 
+lib_a-fpurge.o: fpurge.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-fpurge.o `test -f 'fpurge.c' || echo '$(srcdir)/'`fpurge.c
+
+lib_a-fpurge.obj: fpurge.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-fpurge.obj `if test -f 'fpurge.c'; then $(CYGPATH_W) 'fpurge.c'; else $(CYGPATH_W) '$(srcdir)/fpurge.c'; fi`
+
 lib_a-fputwc.o: fputwc.c
 	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-fputwc.o `test -f 'fputwc.c' || echo '$(srcdir)/'`fputwc.c
 
@@ -1413,7 +1429,7 @@ clean-libtool:
 	-rm -rf .libs _libs
 
 distclean-libtool:
-	-rm -f libtool config.lt
+	-rm -f libtool
 uninstall-info-am:
 
 ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
@@ -1627,6 +1643,7 @@ $(lpfx)findfp.$(oext): local.h
 $(lpfx)fmemopen.$(oext): local.h
 $(lpfx)fopen.$(oext): local.h
 $(lpfx)fopencookie.$(oext): local.h
+$(lpfx)fpurge.$(oext): local.h
 $(lpfx)fputs.$(oext): fvwrite.h
 $(lpfx)fputwc.$(oext): local.h
 $(lpfx)fputws.$(oext): local.h fvwrite.h
Index: libc/stdio/stdio.tex
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/stdio.tex,v
retrieving revision 1.14
diff -u -p -r1.14 stdio.tex
--- libc/stdio/stdio.tex	11 Mar 2009 11:53:22 -0000	1.14
+++ libc/stdio/stdio.tex	1 Jul 2009 00:59:08 -0000
@@ -42,6 +42,7 @@ structure.
 * fmemopen::    Open a stream around a fixed-length buffer
 * fopen::       Open a file
 * fopencookie:: Open a stream with custom callbacks
+* fpurge::      Discard all pending I/O on a stream
 * fputc::       Write a character on a stream or file
 * fputs::       Write a character string in a file or stream
 * fputwc::      Write a wide character to a file or stream
@@ -153,6 +154,9 @@ structure.
 @include stdio/fopencookie.def
 
 @page
+@include stdio/fpurge.def
+
+@page
 @include stdio/fputc.def
 
 @page
Index: libc/include/stdio.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/include/stdio.h,v
retrieving revision 1.57
diff -u -p -r1.57 stdio.h
--- libc/include/stdio.h	4 Apr 2009 15:44:19 -0000	1.57
+++ libc/include/stdio.h	1 Jul 2009 00:59:08 -0000
@@ -391,6 +391,7 @@ FILE *	_EXFUN(_fopen_r, (struct _reent *
 FILE *	_EXFUN(_freopen_r, (struct _reent *, const char *, const char *, FILE *));
 int	_EXFUN(_fprintf_r, (struct _reent *, FILE *, const char *, ...)
                _ATTRIBUTE ((__format__ (__printf__, 3, 4))));
+int	_EXFUN(_fpurge_r, (struct _reent *, FILE *));
 int	_EXFUN(_fputc_r, (struct _reent *, int, FILE *));
 int	_EXFUN(_fputs_r, (struct _reent *, const char *, FILE *));
 size_t	_EXFUN(_fread_r, (struct _reent *, _PTR, size_t _size, size_t _n, FILE *));
@@ -482,6 +483,9 @@ int	_EXFUN(_vsprintf_r, (struct _reent *
 int	_EXFUN(_vsscanf_r, (struct _reent *, const char *, const char *, __VALIST)
                _ATTRIBUTE ((__format__ (__scanf__, 3, 0))));
 
+/* Other extensions.  */
+
+int _EXFUN(fpurge, (FILE *));
 ssize_t _EXFUN(__getdelim, (char **, size_t *, int, FILE *));
 ssize_t _EXFUN(__getline, (char **, size_t *, FILE *));
 
Index: libc/stdio/mktemp.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/mktemp.c,v
retrieving revision 1.10
diff -u -p -r1.10 mktemp.c
--- libc/stdio/mktemp.c	14 Mar 2009 12:14:08 -0000	1.10
+++ libc/stdio/mktemp.c	1 Jul 2009 00:58:20 -0000
@@ -23,27 +23,40 @@
 
 /*
 FUNCTION
-<<mktemp>>, <<mkstemp>>---generate unused file name
+<<mktemp>>, <<mkstemp>>, <<mkstemps>>---generate unused file name
+<<mkdtemp>>---generate unused directory
 
 INDEX
 	mktemp
 INDEX
+	mkdtemp
+INDEX
 	mkstemp
 INDEX
+	mkstemps
+INDEX
 	_mktemp_r
 INDEX
+	_mkdtemp_r
+INDEX
 	_mkstemp_r
+INDEX
+	_mkstemps_r
 
 ANSI_SYNOPSIS
-	#include <stdio.h>
+	#include <stdlib.h>
 	char *mktemp(char *<[path]>);
+	char *mkdtemp(char *<[path]>);
 	int mkstemp(char *<[path]>);
+	int mkstemps(char *<[path]>, int <[suffixlen]>);
 
 	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]>);
 
 TRAD_SYNOPSIS
-	#include <stdio.h>
+	#include <stdlib.h>
 	char *mktemp(<[path]>)
 	char *<[path]>;
 
@@ -59,20 +72,24 @@ TRAD_SYNOPSIS
 	char *<[path]>;
 
 DESCRIPTION
-<<mktemp>> and <<mkstemp>> attempt to generate a file name that is not
-yet in use for any existing file.  <<mkstemp>> creates the file and
-opens it for reading and writing; <<mktemp>> simply generates the file name.
+<<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.
 
 You supply a simple pattern for the generated file name, as the string
 at <[path]>.  The pattern should be a valid filename (including path
-information if you wish) ending with some number of `<<X>>'
+information if you wish) ending with at least six `<<X>>'
 characters.  The generated filename will match the leading part of the
 name you supply, with the trailing `<<X>>' characters replaced by some
-combination of digits and letters.
+combination of digits and letters.  With <<mkstemps>>, the `<<X>>'
+characters end <[suffixlen]> bytes before the end of the string.
 
-The alternate functions <<_mktemp_r>> and <<_mkstemp_r>> are reentrant
-versions.  The extra argument <[reent]> is a pointer to a reentrancy
-structure.
+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.
 
 RETURNS
 <<mktemp>> returns the pointer <[path]> to the modified string
@@ -80,8 +97,11 @@ representing an unused filename, unless 
 the pattern you provided is not suitable for a filename; in that case,
 it returns <<NULL>>.
 
-<<mkstemp>> returns a file descriptor to the newly created file,
-unless it could not generate an unused filename, or the pattern you
+<<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>>.
 
@@ -94,9 +114,11 @@ instead.  It doesn't suffer the race con
 
 PORTABILITY
 ANSI C does not require either <<mktemp>> or <<mkstemp>>; the System
-V Interface Definition requires <<mktemp>> as of Issue 2.
+V Interface Definition requires <<mktemp>> as of Issue 2.  POSIX 2001
+requires <<mkstemp>>, and POSIX 2008 requires <<mkdtemp>>, but
+<<mkstemps>> is not standardized.
 
-Supporting OS subroutines required: <<getpid>>, <<open>>, <<stat>>.
+Supporting OS subroutines required: <<getpid>>, <<mkdir>>, <<open>>, <<stat>>.
 */
 
 #include <_ansi.h>
@@ -109,12 +131,15 @@ Supporting OS subroutines required: <<ge
 #include <ctype.h>
 
 static int
-_DEFUN(_gettemp, (ptr, path, doopen),
+_DEFUN(_gettemp, (ptr, path, doopen, domkdir, suffixlen),
        struct _reent *ptr _AND
        char *path         _AND
-       register int *doopen)
+       register int *doopen _AND
+       int domkdir        _AND
+       size_t suffixlen)
 {
   register char *start, *trv;
+  char *end;
 #ifdef __USE_INTERNAL_STAT64
   struct stat64 sbuf;
 #else
@@ -125,11 +150,23 @@ _DEFUN(_gettemp, (ptr, path, doopen),
   pid = _getpid_r (ptr);
   for (trv = path; *trv; ++trv)		/* extra X's get set to 0's */
     continue;
-  while (*--trv == 'X')
+  if (trv - path < suffixlen)
+    {
+      ptr->_errno = EINVAL;
+      return 0;
+    }
+  trv -= suffixlen;
+  end = trv;
+  while (path < trv && *--trv == 'X')
     {
       *trv = (pid % 10) + '0';
       pid /= 10;
     }
+  if (end - trv < 6)
+    {
+      ptr->_errno = EINVAL;
+      return 0;
+    }
 
   /*
    * Check the target directory; if you have six X's and it
@@ -161,16 +198,22 @@ _DEFUN(_gettemp, (ptr, path, doopen),
 
   for (;;)
     {
+#if !defined _ELIX_LEVEL || _ELIX_LEVEL >= 2
+      if (domkdir)
+	{
+	  if (_mkdir_r (ptr, path, 0700) == 0)
+	    return 1;
+	  if (ptr->_errno != EEXIST)
+	    return 0;
+	}
+      else
+#endif /* _ELIX_LEVEL */
       if (doopen)
 	{
 	  if ((*doopen = _open_r (ptr, path, O_CREAT | O_EXCL | O_RDWR, 0600))
 	      >= 0)
 	    return 1;
-#if defined(__CYGWIN__)
-	  if (ptr->_errno != EEXIST && ptr->_errno != EACCES)
-#else
 	  if (ptr->_errno != EEXIST)
-#endif
 	    return 0;
 	}
 #ifdef __USE_INTERNAL_STAT64
@@ -183,12 +226,13 @@ _DEFUN(_gettemp, (ptr, path, doopen),
       /* tricky little algorithm for backward compatibility */
       for (trv = start;;)
 	{
-	  if (!*trv)
+	  if (trv == end)
 	    return 0;
 	  if (*trv == 'z')
 	    *trv++ = 'a';
 	  else
 	    {
+	      /* Safe, since it only encounters 7-bit characters.  */
 	      if (isdigit (*trv))
 		*trv = 'a';
 	      else
@@ -207,15 +251,36 @@ _DEFUN(_mkstemp_r, (ptr, path),
 {
   int fd;
 
-  return (_gettemp (ptr, path, &fd) ? fd : -1);
+  return (_gettemp (ptr, path, &fd, 0, 0) ? fd : -1);
+}
+
+#if !defined _ELIX_LEVEL || _ELIX_LEVEL >= 2
+char *
+_DEFUN(_mkdtemp_r, (ptr, path),
+       struct _reent *ptr _AND
+       char *path)
+{
+  return (_gettemp (ptr, path, (int *) NULL, 1, 0) ? path : NULL);
+}
+
+int
+_DEFUN(_mkstemps_r, (ptr, path, len),
+       struct _reent *ptr _AND
+       char *path _AND
+       int len)
+{
+  int fd;
+
+  return (_gettemp (ptr, path, &fd, 0, len) ? fd : -1);
 }
+#endif /* _ELIX_LEVEL */
 
 char *
 _DEFUN(_mktemp_r, (ptr, path),
        struct _reent *ptr _AND
        char *path)
 {
-  return (_gettemp (ptr, path, (int *) NULL) ? path : (char *) NULL);
+  return (_gettemp (ptr, path, (int *) NULL, 0, 0) ? path : (char *) NULL);
 }
 
 #ifndef _REENT_ONLY
@@ -226,14 +291,33 @@ _DEFUN(mkstemp, (path),
 {
   int fd;
 
-  return (_gettemp (_REENT, path, &fd) ? fd : -1);
+  return (_gettemp (_REENT, path, &fd, 0, 0) ? fd : -1);
+}
+
+# if !defined _ELIX_LEVEL || _ELIX_LEVEL >= 2
+char *
+_DEFUN(mkdemp, (path),
+       char *path)
+{
+  return (_gettemp (_REENT, path, (int *) NULL, 1, 0) ? path : NULL);
+}
+
+int
+_DEFUN(mkstemps, (path, len),
+       char *path _AND
+       int len)
+{
+  int fd;
+
+  return (_gettemp (_REENT, path, &fd, 0, len) ? fd : -1);
 }
+# endif /* _ELIX_LEVEL */
 
 char *
 _DEFUN(mktemp, (path),
        char *path)
 {
-  return (_gettemp (_REENT, path, (int *) NULL) ? path : (char *) NULL);
+  return (_gettemp (_REENT, path, (int *) NULL, 0, 0) ? path : (char *) NULL);
 }
 
 #endif /* ! defined (_REENT_ONLY) */
Index: libc/include/stdlib.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/include/stdlib.h,v
retrieving revision 1.34
diff -u -p -r1.34 stdlib.h
--- libc/include/stdlib.h	24 Apr 2009 22:49:55 -0000	1.34
+++ libc/include/stdlib.h	1 Jul 2009 00:58:20 -0000
@@ -98,10 +98,14 @@ size_t	_EXFUN(wcstombs,(char *, const wc
 size_t	_EXFUN(_wcstombs_r,(struct _reent *, char *, const wchar_t *, size_t, _mbstate_t *));
 #ifndef __STRICT_ANSI__
 #ifndef _REENT_ONLY
+char *	_EXFUN(mkdtemp,(char *));
 int     _EXFUN(mkstemp,(char *));
+int     _EXFUN(mkstemps,(char *, int));
 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(_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"))));
 #endif
 _VOID	_EXFUN(qsort,(_PTR __base, size_t __nmemb, size_t __size, int(*_compar)(const _PTR, const _PTR)));

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]