@@ -157,6 +157,75 @@ int git_mkstemps(char *path, size_t len, const char *template, int suffix_len)
157157 return mkstemps (path , suffix_len );
158158}
159159
160+ /* Adapted from libiberty's mkstemp.c. */
161+
162+ #undef TMP_MAX
163+ #define TMP_MAX 16384
164+
165+ int gitmkstemps (char * pattern , int suffix_len )
166+ {
167+ static const char letters [] =
168+ "abcdefghijklmnopqrstuvwxyz"
169+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
170+ "0123456789" ;
171+ static const int num_letters = 62 ;
172+ uint64_t value ;
173+ struct timeval tv ;
174+ char * template ;
175+ size_t len ;
176+ int fd , count ;
177+
178+ len = strlen (pattern );
179+
180+ if (len < 6 + suffix_len ) {
181+ errno = EINVAL ;
182+ return -1 ;
183+ }
184+
185+ if (strncmp (& pattern [len - 6 - suffix_len ], "XXXXXX" , 6 )) {
186+ errno = EINVAL ;
187+ return -1 ;
188+ }
189+
190+ /*
191+ * Replace pattern's XXXXXX characters with randomness.
192+ * Try TMP_MAX different filenames.
193+ */
194+ gettimeofday (& tv , NULL );
195+ value = ((size_t )(tv .tv_usec << 16 )) ^ tv .tv_sec ^ getpid ();
196+ template = & pattern [len - 6 - suffix_len ];
197+ for (count = 0 ; count < TMP_MAX ; ++ count ) {
198+ uint64_t v = value ;
199+ /* Fill in the random bits. */
200+ template [0 ] = letters [v % num_letters ]; v /= num_letters ;
201+ template [1 ] = letters [v % num_letters ]; v /= num_letters ;
202+ template [2 ] = letters [v % num_letters ]; v /= num_letters ;
203+ template [3 ] = letters [v % num_letters ]; v /= num_letters ;
204+ template [4 ] = letters [v % num_letters ]; v /= num_letters ;
205+ template [5 ] = letters [v % num_letters ]; v /= num_letters ;
206+
207+ fd = open (pattern , O_CREAT | O_EXCL | O_RDWR , 0600 );
208+ if (fd > 0 )
209+ return fd ;
210+ /*
211+ * Fatal error (EPERM, ENOSPC etc).
212+ * It doesn't make sense to loop.
213+ */
214+ if (errno != EEXIST )
215+ break ;
216+ /*
217+ * This is a random value. It is only necessary that
218+ * the next TMP_MAX values generated by adding 7777 to
219+ * VALUE are different with (module 2^32).
220+ */
221+ value += 7777 ;
222+ }
223+ /* We return the null string if we can't find a unique file name. */
224+ pattern [0 ] = '\0' ;
225+ errno = EINVAL ;
226+ return -1 ;
227+ }
228+
160229int validate_headref (const char * path )
161230{
162231 struct stat st ;
0 commit comments