Submitted By: Robert Connolly (ashes) Date: 2009-06-02 Initial Package Version: 2.10.1 Upstream Status: Unknown Origin: gcc-4.4-20090526/libiberty/mkstemps.c plus modifications based on http://www.uclibc.org/cgi-bin/viewcvs.cgi/trunk/uClibc/libc/misc/\ internals/tempname.c?rev=8887&r1=5747&r2=8887 Description: Add mkstemps(3) to Glibc, and have it only use /dev/urandom for entropy. If /dev/urandom doesn't exist, or the temp file already exist, it will exit with EACCES. diff -Naur glibc-2.10.1.orig/manual/mkstemps.3 glibc-2.10.1/manual/mkstemps.3 --- glibc-2.10.1.orig/manual/mkstemps.3 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.10.1/manual/mkstemps.3 2009-06-02 20:47:52.562667256 +0000 @@ -0,0 +1,86 @@ +.\" $OpenBSD: mktemp.3,v 1.40 2007/05/10 22:46:36 espie Exp $ +.\" +.\" Copyright (c) 1989, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd June 4, 1993 +.Dt MKTEMP 3 +.Os +.Sh NAME +.Nm mkstemps +.Nd make temporary file name (unique) +.Sh SYNOPSIS +.Fd #include +.Ft int +.Fn mkstemps "char *template" "int suffixlen" +.Sh DESCRIPTION +.Pp +The +.Fn mkstemps +function acts the same as +.Fn mkstemp , +except it permits a suffix to exist in the template. +The template should be of the form +.Pa /tmp/tmpXXXXXXXXXXsuffix . +.Fn mkstemps +is told the length of the suffix string, i.e., +.Li strlen("suffix") . +.Pp +The +.Fn mkstemps +function return \-1 if no suitable file could be created. +If any call fails, an error code is placed in the global variable +.Va errno . +The +.Fn mkstemps +function may also set +.Va errno +to any value specified by the +.Xr open 2 +function or, +.Bl -tag -width Er +.It Bq Er EINVAL +The suffix length is longer than the template length. +.El +.Sh SEE ALSO +.Xr chmod 2 , +.Xr getpid 2 , +.Xr mkdir 2 , +.Xr open 2 , +.Xr stat 2 , +.Xr tempnam 3 , +.Xr tmpfile 3 , +.Xr tmpnam 3 +.Sh HISTORY +The +.Fn mkstemps +function appeared in +.Ox 2.3 . +.Sh BUGS +The +.Fn mkstemps +function are non-standard and should not be used if portability is required. diff -Naur glibc-2.10.1.orig/misc/Makefile glibc-2.10.1/misc/Makefile --- glibc-2.10.1.orig/misc/Makefile 2009-04-03 19:51:04.000000000 +0000 +++ glibc-2.10.1/misc/Makefile 2009-06-02 20:48:45.959379876 +0000 @@ -44,7 +44,7 @@ acct chroot fsync sync fdatasync reboot \ gethostid sethostid \ revoke vhangup \ - swapon swapoff mktemp mkstemp mkstemp64 mkdtemp \ + swapon swapoff mktemp mkstemp mkstemps mkstemp64 mkdtemp \ mkostemp mkostemp64 \ ualarm usleep \ gtty stty \ diff -Naur glibc-2.10.1.orig/misc/Versions glibc-2.10.1/misc/Versions --- glibc-2.10.1.orig/misc/Versions 2009-04-03 19:51:14.000000000 +0000 +++ glibc-2.10.1/misc/Versions 2009-06-02 20:49:21.950555464 +0000 @@ -53,7 +53,7 @@ jrand48; jrand48_r; lfind; lsearch; # m* - madvise; mkstemp; mktemp; mlock; mlockall; mmap; mount; mprotect; msync; + madvise; mkstemp; mkstemps; mktemp; mlock; mlockall; mmap; mount; mprotect; msync; munlock; munlockall; munmap; # o* diff -Naur glibc-2.10.1.orig/misc/mkstemps.c glibc-2.10.1/misc/mkstemps.c --- glibc-2.10.1.orig/misc/mkstemps.c 1970-01-01 00:00:00.000000000 +0000 +++ glibc-2.10.1/misc/mkstemps.c 2009-06-02 20:43:53.961772640 +0000 @@ -0,0 +1,164 @@ +/* Copyright (C) 1991, 1992, 1996, 1998, 2004 Free Software Foundation, Inc. + This file is derived from mkstemp.c from the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* Modified by Robert Connolly for Glibc. June 2, 2009. + Originally from gcc-4.4-20090526. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +#include +#include +#include +#include + +#ifndef _LIBC +# define __open open +# define __close close +# define __read read +#endif + +#ifndef TMP_MAX +#define TMP_MAX 238328 +#endif + +#ifndef O_BINARY +# define O_BINARY 0 +#endif + +/* + +@deftypefn Replacement int mkstemps (char *@var{pattern}, int @var{suffix_len}) + +Generate a unique temporary file name from @var{pattern}. +@var{pattern} has the form: + +@example + @var{path}/ccXXXXXX@var{suffix} +@end example + +@var{suffix_len} tells us how long @var{suffix} is (it can be zero +length). The last six characters of @var{pattern} before @var{suffix} +must be @samp{XXXXXX}; they are replaced with a string that makes the +filename unique. Returns a file descriptor open on the file for +reading and writing. + +@end deftypefn + +*/ + +static unsigned int fillrand(unsigned char *buf, unsigned int len) +{ + int fd; + unsigned int result = -1; + fd = __open("/dev/urandom", O_RDONLY); + if (fd >= 0) + { + result = __read(fd, buf, len); + __close(fd); + } + return result; +} + +int +mkstemps (char *pattern, int suffix_len) +{ + static const char letters[] + = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + char *XXXXXX; + static uint64_t value; + size_t len; + int count, i; + unsigned char randomness[6]; + unsigned int k; + + len = strlen (pattern); + + if ((int) len < 6 + suffix_len + || strncmp (&pattern[len - 6 - suffix_len], "XXXXXX", 6)) + { + return -1; + } + + XXXXXX = &pattern[len - 6 - suffix_len]; + + /* Get some random data. */ + if (fillrand(randomness, sizeof(randomness)) != sizeof(randomness)) + { + __set_errno (EACCES); + return -1; + } + for (i = 0 ; i < sizeof(randomness) ; i++) + { + k = ((randomness[i]) % 62); + XXXXXX[i] = letters[k]; + } + + for (count = 0; count < TMP_MAX; ++count) + { + int fd; + + fd = __open(pattern, O_BINARY|O_RDWR|O_CREAT|O_EXCL, 0600); + if (fd >= 0) + /* The file does not exist. */ + return fd; + if (errno != EEXIST +#ifdef EISDIR + && errno != EISDIR +#endif + ) + /* Fatal error (EPERM, ENOSPC etc). Doesn't make sense to loop. */ + break; + + /* This is a random value. It is only necessary that the next + TMP_MAX values generated by adding 7777 to VALUE are different + with (module 2^32). */ + value += 7777; + } + + /* We return the null string if we can't find a unique file name. */ + pattern[0] = '\0'; + return -1; +} +#ifdef TEST +int main() +{ + char template[]="/tmp/tempXXXXXXX.xyz"; + int fd = -1; + + if ((fd = mkstemps(template, 4)) != -1) + { + printf("%s\n", template); + //unlink(template); + close(fd); + } else { + fprintf(stderr, "Failed to create temp file.\n%s\n", + strerror(errno)); + } + return 0; +} +#endif diff -Naur glibc-2.10.1.orig/stdlib/stdlib.h glibc-2.10.1/stdlib/stdlib.h --- glibc-2.10.1.orig/stdlib/stdlib.h 2009-03-08 19:52:44.000000000 +0000 +++ glibc-2.10.1/stdlib/stdlib.h 2009-06-02 20:51:07.943899399 +0000 @@ -633,6 +633,7 @@ Returns TEMPLATE, or a null pointer if it cannot get a unique name. The directory is created mode 700. */ extern char *mkdtemp (char *__template) __THROW __nonnull ((1)) __wur; +extern int mkstemps(char *, int) __THROW __wur; #endif #ifdef __USE_GNU