1169695Skan/* Copyright (C) 1991, 1992, 1996, 1998, 2004 Free Software Foundation, Inc. 2169695Skan This file is derived from mkstemp.c from the GNU C Library. 3169695Skan 4169695Skan The GNU C Library is free software; you can redistribute it and/or 5169695Skan modify it under the terms of the GNU Library General Public License as 6169695Skan published by the Free Software Foundation; either version 2 of the 7169695Skan License, or (at your option) any later version. 8169695Skan 9169695Skan The GNU C Library is distributed in the hope that it will be useful, 10169695Skan but WITHOUT ANY WARRANTY; without even the implied warranty of 11169695Skan MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12169695Skan Library General Public License for more details. 13169695Skan 14169695Skan You should have received a copy of the GNU Library General Public 15169695Skan License along with the GNU C Library; see the file COPYING.LIB. If not, 16169695Skan write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 17169695Skan Boston, MA 02110-1301, USA. */ 18169695Skan 19169695Skan#ifdef HAVE_CONFIG_H 20169695Skan#include "config.h" 21169695Skan#endif 22169695Skan 23169695Skan#include <sys/types.h> 24169695Skan#ifdef HAVE_STDLIB_H 25169695Skan#include <stdlib.h> 26169695Skan#endif 27169695Skan#ifdef HAVE_STRING_H 28169695Skan#include <string.h> 29169695Skan#endif 30169695Skan#include <errno.h> 31169695Skan#include <stdio.h> 32169695Skan#include <fcntl.h> 33169695Skan#ifdef HAVE_UNISTD_H 34169695Skan#include <unistd.h> 35169695Skan#endif 36169695Skan#ifdef HAVE_SYS_TIME_H 37169695Skan#include <sys/time.h> 38169695Skan#endif 39169695Skan#include "ansidecl.h" 40169695Skan 41169695Skan/* We need to provide a type for gcc_uint64_t. */ 42169695Skan#ifdef __GNUC__ 43169695Skan__extension__ typedef unsigned long long gcc_uint64_t; 44169695Skan#else 45169695Skantypedef unsigned long gcc_uint64_t; 46169695Skan#endif 47169695Skan 48169695Skan#ifndef TMP_MAX 49169695Skan#define TMP_MAX 16384 50169695Skan#endif 51169695Skan 52169695Skan#ifndef O_BINARY 53169695Skan# define O_BINARY 0 54169695Skan#endif 55169695Skan 56169695Skan/* 57169695Skan 58169695Skan@deftypefn Replacement int mkstemps (char *@var{pattern}, int @var{suffix_len}) 59169695Skan 60169695SkanGenerate a unique temporary file name from @var{pattern}. 61169695Skan@var{pattern} has the form: 62169695Skan 63169695Skan@example 64169695Skan @var{path}/ccXXXXXX@var{suffix} 65169695Skan@end example 66169695Skan 67169695Skan@var{suffix_len} tells us how long @var{suffix} is (it can be zero 68169695Skanlength). The last six characters of @var{pattern} before @var{suffix} 69169695Skanmust be @samp{XXXXXX}; they are replaced with a string that makes the 70169695Skanfilename unique. Returns a file descriptor open on the file for 71169695Skanreading and writing. 72169695Skan 73169695Skan@end deftypefn 74169695Skan 75169695Skan*/ 76169695Skan 77169695Skanint 78169695Skanmkstemps (char *pattern, int suffix_len) 79169695Skan{ 80169695Skan static const char letters[] 81169695Skan = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 82169695Skan static gcc_uint64_t value; 83169695Skan#ifdef HAVE_GETTIMEOFDAY 84169695Skan struct timeval tv; 85169695Skan#endif 86169695Skan char *XXXXXX; 87169695Skan size_t len; 88169695Skan int count; 89169695Skan 90169695Skan len = strlen (pattern); 91169695Skan 92169695Skan if ((int) len < 6 + suffix_len 93169695Skan || strncmp (&pattern[len - 6 - suffix_len], "XXXXXX", 6)) 94169695Skan { 95169695Skan return -1; 96169695Skan } 97169695Skan 98169695Skan XXXXXX = &pattern[len - 6 - suffix_len]; 99169695Skan 100169695Skan#ifdef HAVE_GETTIMEOFDAY 101169695Skan /* Get some more or less random data. */ 102169695Skan gettimeofday (&tv, NULL); 103169695Skan value += ((gcc_uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid (); 104169695Skan#else 105169695Skan value += getpid (); 106169695Skan#endif 107169695Skan 108169695Skan for (count = 0; count < TMP_MAX; ++count) 109169695Skan { 110169695Skan gcc_uint64_t v = value; 111169695Skan int fd; 112169695Skan 113169695Skan /* Fill in the random bits. */ 114169695Skan XXXXXX[0] = letters[v % 62]; 115169695Skan v /= 62; 116169695Skan XXXXXX[1] = letters[v % 62]; 117169695Skan v /= 62; 118169695Skan XXXXXX[2] = letters[v % 62]; 119169695Skan v /= 62; 120169695Skan XXXXXX[3] = letters[v % 62]; 121169695Skan v /= 62; 122169695Skan XXXXXX[4] = letters[v % 62]; 123169695Skan v /= 62; 124169695Skan XXXXXX[5] = letters[v % 62]; 125169695Skan 126169695Skan fd = open (pattern, O_BINARY|O_RDWR|O_CREAT|O_EXCL, 0600); 127169695Skan if (fd >= 0) 128169695Skan /* The file does not exist. */ 129169695Skan return fd; 130169695Skan 131169695Skan /* This is a random value. It is only necessary that the next 132169695Skan TMP_MAX values generated by adding 7777 to VALUE are different 133169695Skan with (module 2^32). */ 134169695Skan value += 7777; 135169695Skan } 136169695Skan 137169695Skan /* We return the null string if we can't find a unique file name. */ 138169695Skan pattern[0] = '\0'; 139169695Skan return -1; 140169695Skan} 141