1 /* Copyright (C) 1991, 1992, 1996, 1998 Free Software Foundation, Inc. 2 This file is derived from mkstemp.c from the GNU C Library. 3 4 The GNU C Library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Lesser General Public 6 License as published by the Free Software Foundation; either 7 version 2.1 of the License, or (at your option) any later version. 8 9 The GNU C Library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public 15 License along with the GNU C Library; if not, write to the Free 16 Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 Boston, MA 02110-1301, USA. 18 */ 19 20 #include <sys/types.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #include <errno.h> 24 #include <stdio.h> 25 #include <fcntl.h> 26 27 #ifdef _WIN32 28 #include <io.h> 29 #include <process.h> 30 #else 31 #include <unistd.h> 32 #include <sys/time.h> 33 #endif 34 35 /* We need to provide a type for gcc_uint64_t. */ 36 #ifdef __GNUC__ 37 __extension__ typedef unsigned long long gcc_uint64_t; 38 #else 39 typedef unsigned long gcc_uint64_t; 40 #endif 41 42 #ifndef TMP_MAX 43 #define TMP_MAX 16384 44 #endif 45 46 /* if O_BINARY is not defined, the system is probably not expecting any such flag */ 47 #ifndef O_BINARY 48 #define O_BINARY 0 49 #endif 50 51 /* 52 53 @deftypefn Replacement int mkstemps (char *@var{template}, int @var{suffix_len}) 54 55 Generate a unique temporary file name from @var{template}. 56 @var{template} has the form: 57 58 @example 59 @var{path}/ccXXXXXX@var{suffix} 60 @end example 61 62 @var{suffix_len} tells us how long @var{suffix} is (it can be zero 63 length). The last six characters of @var{template} before @var{suffix} 64 must be @samp{XXXXXX}; they are replaced with a string that makes the 65 filename unique. Returns a file descriptor open on the file for 66 reading and writing. 67 68 @end deftypefn 69 70 */ 71 72 int 73 mkstemps ( 74 char *template, 75 int suffix_len) 76 { 77 static const char letters[] 78 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 79 static gcc_uint64_t value; 80 #ifdef HAVE_GETTIMEOFDAY 81 struct timeval tv; 82 #endif 83 char *XXXXXX; 84 size_t len; 85 int count; 86 87 len = strlen (template); 88 89 if ((int) len < 6 + suffix_len 90 || strncmp (&template[len - 6 - suffix_len], "XXXXXX", 6)) 91 { 92 printf("wrong parameter\n"); 93 return -1; 94 } 95 96 XXXXXX = &template[len - 6 - suffix_len]; 97 98 #ifdef HAVE_GETTIMEOFDAY 99 /* Get some more or less random data. */ 100 gettimeofday (&tv, NULL); 101 value += ((gcc_uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid (); 102 #else 103 value += getpid (); 104 #endif 105 106 for (count = 0; count < TMP_MAX; ++count) 107 { 108 gcc_uint64_t v = value; 109 int fd; 110 111 /* Fill in the random bits. */ 112 XXXXXX[0] = letters[v % 62]; 113 v /= 62; 114 XXXXXX[1] = letters[v % 62]; 115 v /= 62; 116 XXXXXX[2] = letters[v % 62]; 117 v /= 62; 118 XXXXXX[3] = letters[v % 62]; 119 v /= 62; 120 XXXXXX[4] = letters[v % 62]; 121 v /= 62; 122 XXXXXX[5] = letters[v % 62]; 123 124 #ifdef VMS 125 fd = open (template, O_RDWR|O_CREAT|O_EXCL, 0600, "fop=tmd"); 126 #else 127 fd = open (template, O_RDWR|O_CREAT|O_EXCL|O_BINARY, 0600); 128 #endif 129 if (fd >= 0) 130 /* The file does not exist. */ 131 return fd; 132 133 /* This is a random value. It is only necessary that the next 134 TMP_MAX values generated by adding 7777 to VALUE are different 135 with (module 2^32). */ 136 value += 7777; 137 } 138 139 /* We return the null string if we can't find a unique file name. */ 140 template[0] = '\0'; 141 return -1; 142 } 143