1218822Sdim/* Copyright (C) 1991, 1992, 1996, 1998, 2004 Free Software Foundation, Inc. 260484Sobrien This file is derived from mkstemp.c from the GNU C Library. 360484Sobrien 460484Sobrien The GNU C Library is free software; you can redistribute it and/or 560484Sobrien modify it under the terms of the GNU Library General Public License as 660484Sobrien published by the Free Software Foundation; either version 2 of the 760484Sobrien License, or (at your option) any later version. 860484Sobrien 960484Sobrien The GNU C Library is distributed in the hope that it will be useful, 1060484Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1160484Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1260484Sobrien Library General Public License for more details. 1360484Sobrien 1460484Sobrien You should have received a copy of the GNU Library General Public 1560484Sobrien License along with the GNU C Library; see the file COPYING.LIB. If not, 16218822Sdim write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 17218822Sdim Boston, MA 02110-1301, USA. */ 1860484Sobrien 1960484Sobrien#ifdef HAVE_CONFIG_H 2060484Sobrien#include "config.h" 2160484Sobrien#endif 2260484Sobrien 2377298Sobrien#include <sys/types.h> 2460484Sobrien#ifdef HAVE_STDLIB_H 2560484Sobrien#include <stdlib.h> 2660484Sobrien#endif 2760484Sobrien#ifdef HAVE_STRING_H 2860484Sobrien#include <string.h> 2960484Sobrien#endif 3060484Sobrien#include <errno.h> 3160484Sobrien#include <stdio.h> 3260484Sobrien#include <fcntl.h> 3360484Sobrien#ifdef HAVE_UNISTD_H 3460484Sobrien#include <unistd.h> 3560484Sobrien#endif 3660484Sobrien#ifdef HAVE_SYS_TIME_H 3760484Sobrien#include <sys/time.h> 3860484Sobrien#endif 3960484Sobrien#include "ansidecl.h" 4060484Sobrien 4160484Sobrien/* We need to provide a type for gcc_uint64_t. */ 4260484Sobrien#ifdef __GNUC__ 4377298Sobrien__extension__ typedef unsigned long long gcc_uint64_t; 4460484Sobrien#else 4560484Sobrientypedef unsigned long gcc_uint64_t; 4660484Sobrien#endif 4760484Sobrien 4860484Sobrien#ifndef TMP_MAX 4960484Sobrien#define TMP_MAX 16384 5060484Sobrien#endif 5160484Sobrien 52218822Sdim#ifndef O_BINARY 53218822Sdim# define O_BINARY 0 54218822Sdim#endif 55218822Sdim 5689857Sobrien/* 5760484Sobrien 58218822Sdim@deftypefn Replacement int mkstemps (char *@var{pattern}, int @var{suffix_len}) 5960484Sobrien 60218822SdimGenerate a unique temporary file name from @var{pattern}. 61218822Sdim@var{pattern} has the form: 6260484Sobrien 6389857Sobrien@example 6489857Sobrien @var{path}/ccXXXXXX@var{suffix} 6589857Sobrien@end example 6660484Sobrien 6789857Sobrien@var{suffix_len} tells us how long @var{suffix} is (it can be zero 68218822Sdimlength). The last six characters of @var{pattern} before @var{suffix} 6989857Sobrienmust be @samp{XXXXXX}; they are replaced with a string that makes the 7089857Sobrienfilename unique. Returns a file descriptor open on the file for 7189857Sobrienreading and writing. 7260484Sobrien 7389857Sobrien@end deftypefn 7489857Sobrien 7589857Sobrien*/ 7689857Sobrien 7760484Sobrienint 78218822Sdimmkstemps (char *pattern, int suffix_len) 7960484Sobrien{ 8060484Sobrien static const char letters[] 8160484Sobrien = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 8260484Sobrien static gcc_uint64_t value; 8360484Sobrien#ifdef HAVE_GETTIMEOFDAY 8460484Sobrien struct timeval tv; 8560484Sobrien#endif 8660484Sobrien char *XXXXXX; 8760484Sobrien size_t len; 8860484Sobrien int count; 8960484Sobrien 90218822Sdim len = strlen (pattern); 9160484Sobrien 9260484Sobrien if ((int) len < 6 + suffix_len 93218822Sdim || strncmp (&pattern[len - 6 - suffix_len], "XXXXXX", 6)) 9460484Sobrien { 9560484Sobrien return -1; 9660484Sobrien } 9760484Sobrien 98218822Sdim XXXXXX = &pattern[len - 6 - suffix_len]; 9960484Sobrien 10060484Sobrien#ifdef HAVE_GETTIMEOFDAY 10160484Sobrien /* Get some more or less random data. */ 10260484Sobrien gettimeofday (&tv, NULL); 10360484Sobrien value += ((gcc_uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid (); 10460484Sobrien#else 10560484Sobrien value += getpid (); 10660484Sobrien#endif 10760484Sobrien 10860484Sobrien for (count = 0; count < TMP_MAX; ++count) 10960484Sobrien { 11060484Sobrien gcc_uint64_t v = value; 11160484Sobrien int fd; 11260484Sobrien 11360484Sobrien /* Fill in the random bits. */ 11460484Sobrien XXXXXX[0] = letters[v % 62]; 11560484Sobrien v /= 62; 11660484Sobrien XXXXXX[1] = letters[v % 62]; 11760484Sobrien v /= 62; 11860484Sobrien XXXXXX[2] = letters[v % 62]; 11960484Sobrien v /= 62; 12060484Sobrien XXXXXX[3] = letters[v % 62]; 12160484Sobrien v /= 62; 12260484Sobrien XXXXXX[4] = letters[v % 62]; 12360484Sobrien v /= 62; 12460484Sobrien XXXXXX[5] = letters[v % 62]; 12560484Sobrien 126218822Sdim fd = open (pattern, O_BINARY|O_RDWR|O_CREAT|O_EXCL, 0600); 12760484Sobrien if (fd >= 0) 12860484Sobrien /* The file does not exist. */ 12960484Sobrien return fd; 13060484Sobrien 13160484Sobrien /* This is a random value. It is only necessary that the next 13260484Sobrien TMP_MAX values generated by adding 7777 to VALUE are different 13360484Sobrien with (module 2^32). */ 13460484Sobrien value += 7777; 13560484Sobrien } 13660484Sobrien 13760484Sobrien /* We return the null string if we can't find a unique file name. */ 138218822Sdim pattern[0] = '\0'; 13960484Sobrien return -1; 14060484Sobrien} 141