This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
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)));