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 29 Jun 2009 12:44:24 -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: 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 29 Jun 2009 12:44:24 -0000 @@ -23,27 +23,40 @@ /* FUNCTION -<>, <>---generate unused file name +<>, <>, <>---generate unused file name +<>---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 + #include 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 + #include char *mktemp(<[path]>) char *<[path]>; @@ -59,20 +72,24 @@ TRAD_SYNOPSIS char *<[path]>; DESCRIPTION -<> and <> attempt to generate a file name that is not -yet in use for any existing file. <> creates the file and -opens it for reading and writing; <> simply generates the file name. +<>, <>, and <> attempt to generate a file name +that is not yet in use for any existing file. <> and <> +create the file and open it for reading and writing; <> simply +generates the file name (making <> a security risk). <> +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 `<>' +information if you wish) ending with at least six `<>' characters. The generated filename will match the leading part of the name you supply, with the trailing `<>' characters replaced by some -combination of digits and letters. +combination of digits and letters. With <>, the `<>' +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 <> 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 <>. -<> returns a file descriptor to the newly created file, -unless it could not generate an unused filename, or the pattern you +<> returns the pointer <[path]> to the modified string if the +directory was created, otherwise it returns <>. + +<> and <> 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 <> or <>; the System -V Interface Definition requires <> as of Issue 2. +V Interface Definition requires <> as of Issue 2. POSIX 2001 +requires <>, and POSIX 2008 requires <>, but +<> is not standardized. -Supporting OS subroutines required: <>, <>, <>. +Supporting OS subroutines required: <>, <>, <>, <>. */ #include <_ansi.h> @@ -109,12 +131,15 @@ Supporting OS subroutines required: < 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 + int suffixlen) { register char *start, *trv; + char *end; #ifdef __USE_INTERNAL_STAT64 struct stat64 sbuf; #else @@ -125,11 +150,18 @@ _DEFUN(_gettemp, (ptr, path, doopen), pid = _getpid_r (ptr); for (trv = path; *trv; ++trv) /* extra X's get set to 0's */ continue; + trv -= suffixlen; + end = trv; while (*--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 +193,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 +221,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 +246,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 +286,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) */