1*5173eb0aSchristos /* Copyright (C) 1991-2024 Free Software Foundation, Inc. 298b9484cSchristos This file is derived from mkstemp.c from the GNU C Library. 398b9484cSchristos 498b9484cSchristos The GNU C Library is free software; you can redistribute it and/or 598b9484cSchristos modify it under the terms of the GNU Library General Public License as 698b9484cSchristos published by the Free Software Foundation; either version 2 of the 798b9484cSchristos License, or (at your option) any later version. 898b9484cSchristos 998b9484cSchristos The GNU C Library is distributed in the hope that it will be useful, 1098b9484cSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 1198b9484cSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1298b9484cSchristos Library General Public License for more details. 1398b9484cSchristos 1498b9484cSchristos You should have received a copy of the GNU Library General Public 1598b9484cSchristos License along with the GNU C Library; see the file COPYING.LIB. If not, 1698b9484cSchristos write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 1798b9484cSchristos Boston, MA 02110-1301, USA. */ 1898b9484cSchristos 1998b9484cSchristos #ifdef HAVE_CONFIG_H 2098b9484cSchristos #include "config.h" 2198b9484cSchristos #endif 2298b9484cSchristos 2398b9484cSchristos #include <sys/types.h> 2498b9484cSchristos #ifdef HAVE_STDLIB_H 2598b9484cSchristos #include <stdlib.h> 2698b9484cSchristos #endif 2798b9484cSchristos #ifdef HAVE_STRING_H 2898b9484cSchristos #include <string.h> 2998b9484cSchristos #endif 3098b9484cSchristos #include <errno.h> 3198b9484cSchristos #include <stdio.h> 3298b9484cSchristos #include <fcntl.h> 3398b9484cSchristos #ifdef HAVE_UNISTD_H 3498b9484cSchristos #include <unistd.h> 3598b9484cSchristos #endif 3698b9484cSchristos #ifdef HAVE_SYS_TIME_H 3798b9484cSchristos #include <sys/time.h> 38212397c6Schristos #elif HAVE_TIME_H 39212397c6Schristos #include <time.h> 4098b9484cSchristos #endif 4198b9484cSchristos #include "ansidecl.h" 4298b9484cSchristos 4398b9484cSchristos /* We need to provide a type for gcc_uint64_t. */ 4498b9484cSchristos #ifdef __GNUC__ 4598b9484cSchristos __extension__ typedef unsigned long long gcc_uint64_t; 4698b9484cSchristos #else 4798b9484cSchristos typedef unsigned long gcc_uint64_t; 4898b9484cSchristos #endif 4998b9484cSchristos 5098b9484cSchristos #ifndef TMP_MAX 5198b9484cSchristos #define TMP_MAX 16384 5298b9484cSchristos #endif 5398b9484cSchristos 5498b9484cSchristos #ifndef O_BINARY 5598b9484cSchristos # define O_BINARY 0 5698b9484cSchristos #endif 5798b9484cSchristos 5898b9484cSchristos /* 5998b9484cSchristos 6098b9484cSchristos @deftypefn Replacement int mkstemps (char *@var{pattern}, int @var{suffix_len}) 6198b9484cSchristos 6298b9484cSchristos Generate a unique temporary file name from @var{pattern}. 6398b9484cSchristos @var{pattern} has the form: 6498b9484cSchristos 6598b9484cSchristos @example 6698b9484cSchristos @var{path}/ccXXXXXX@var{suffix} 6798b9484cSchristos @end example 6898b9484cSchristos 6998b9484cSchristos @var{suffix_len} tells us how long @var{suffix} is (it can be zero 7098b9484cSchristos length). The last six characters of @var{pattern} before @var{suffix} 7198b9484cSchristos must be @samp{XXXXXX}; they are replaced with a string that makes the 7298b9484cSchristos filename unique. Returns a file descriptor open on the file for 7398b9484cSchristos reading and writing. 7498b9484cSchristos 7598b9484cSchristos @end deftypefn 7698b9484cSchristos 7798b9484cSchristos */ 7898b9484cSchristos 7998b9484cSchristos int 8098b9484cSchristos mkstemps (char *pattern, int suffix_len) 8198b9484cSchristos { 8298b9484cSchristos static const char letters[] 8398b9484cSchristos = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 8498b9484cSchristos static gcc_uint64_t value; 8598b9484cSchristos #ifdef HAVE_GETTIMEOFDAY 8698b9484cSchristos struct timeval tv; 8798b9484cSchristos #endif 8898b9484cSchristos char *XXXXXX; 8998b9484cSchristos size_t len; 9098b9484cSchristos int count; 9198b9484cSchristos 9298b9484cSchristos len = strlen (pattern); 9398b9484cSchristos 9498b9484cSchristos if ((int) len < 6 + suffix_len 9598b9484cSchristos || strncmp (&pattern[len - 6 - suffix_len], "XXXXXX", 6)) 9698b9484cSchristos { 9798b9484cSchristos return -1; 9898b9484cSchristos } 9998b9484cSchristos 10098b9484cSchristos XXXXXX = &pattern[len - 6 - suffix_len]; 10198b9484cSchristos 10298b9484cSchristos #ifdef HAVE_GETTIMEOFDAY 10398b9484cSchristos /* Get some more or less random data. */ 10498b9484cSchristos gettimeofday (&tv, NULL); 10598b9484cSchristos value += ((gcc_uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid (); 10698b9484cSchristos #else 10798b9484cSchristos value += getpid (); 10898b9484cSchristos #endif 10998b9484cSchristos 11098b9484cSchristos for (count = 0; count < TMP_MAX; ++count) 11198b9484cSchristos { 11298b9484cSchristos gcc_uint64_t v = value; 11398b9484cSchristos int fd; 11498b9484cSchristos 11598b9484cSchristos /* Fill in the random bits. */ 11698b9484cSchristos XXXXXX[0] = letters[v % 62]; 11798b9484cSchristos v /= 62; 11898b9484cSchristos XXXXXX[1] = letters[v % 62]; 11998b9484cSchristos v /= 62; 12098b9484cSchristos XXXXXX[2] = letters[v % 62]; 12198b9484cSchristos v /= 62; 12298b9484cSchristos XXXXXX[3] = letters[v % 62]; 12398b9484cSchristos v /= 62; 12498b9484cSchristos XXXXXX[4] = letters[v % 62]; 12598b9484cSchristos v /= 62; 12698b9484cSchristos XXXXXX[5] = letters[v % 62]; 12798b9484cSchristos 12898b9484cSchristos fd = open (pattern, O_BINARY|O_RDWR|O_CREAT|O_EXCL, 0600); 12998b9484cSchristos if (fd >= 0) 13098b9484cSchristos /* The file does not exist. */ 13198b9484cSchristos return fd; 13298b9484cSchristos if (errno != EEXIST 13398b9484cSchristos #ifdef EISDIR 13498b9484cSchristos && errno != EISDIR 13598b9484cSchristos #endif 13698b9484cSchristos ) 13798b9484cSchristos /* Fatal error (EPERM, ENOSPC etc). Doesn't make sense to loop. */ 13898b9484cSchristos break; 13998b9484cSchristos 14098b9484cSchristos /* This is a random value. It is only necessary that the next 14198b9484cSchristos TMP_MAX values generated by adding 7777 to VALUE are different 14298b9484cSchristos with (module 2^32). */ 14398b9484cSchristos value += 7777; 14498b9484cSchristos } 14598b9484cSchristos 14698b9484cSchristos /* We return the null string if we can't find a unique file name. */ 14798b9484cSchristos pattern[0] = '\0'; 14898b9484cSchristos return -1; 14998b9484cSchristos } 150