(root)/
gcc-13.2.0/
libiberty/
mkstemps.c
       1  /* Copyright (C) 1991-2023 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 Library General Public License as
       6     published by the Free Software Foundation; either version 2 of the
       7     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     Library General Public License for more details.
      13  
      14     You should have received a copy of the GNU Library General Public
      15     License along with the GNU C Library; see the file COPYING.LIB.  If not,
      16     write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
      17     Boston, MA 02110-1301, USA.  */
      18  
      19  #ifdef HAVE_CONFIG_H
      20  #include "config.h"
      21  #endif
      22  
      23  #include <sys/types.h>
      24  #ifdef HAVE_STDLIB_H
      25  #include <stdlib.h>
      26  #endif
      27  #ifdef HAVE_STRING_H
      28  #include <string.h>
      29  #endif
      30  #include <errno.h>
      31  #include <stdio.h>
      32  #include <fcntl.h>
      33  #ifdef HAVE_UNISTD_H
      34  #include <unistd.h>
      35  #endif
      36  #ifdef HAVE_SYS_TIME_H
      37  #include <sys/time.h>
      38  #elif HAVE_TIME_H
      39  #include <time.h>
      40  #endif
      41  #include "ansidecl.h"
      42  
      43  /* We need to provide a type for gcc_uint64_t.  */
      44  #ifdef __GNUC__
      45  __extension__ typedef unsigned long long gcc_uint64_t;
      46  #else
      47  typedef unsigned long gcc_uint64_t;
      48  #endif
      49  
      50  #ifndef TMP_MAX
      51  #define TMP_MAX 16384
      52  #endif
      53  
      54  #ifndef O_BINARY
      55  # define O_BINARY 0
      56  #endif
      57  
      58  /*
      59  
      60  @deftypefn Replacement int mkstemps (char *@var{pattern}, int @var{suffix_len})
      61  
      62  Generate a unique temporary file name from @var{pattern}.
      63  @var{pattern} has the form:
      64  
      65  @example
      66     @var{path}/ccXXXXXX@var{suffix}
      67  @end example
      68  
      69  @var{suffix_len} tells us how long @var{suffix} is (it can be zero
      70  length).  The last six characters of @var{pattern} before @var{suffix}
      71  must be @samp{XXXXXX}; they are replaced with a string that makes the
      72  filename unique.  Returns a file descriptor open on the file for
      73  reading and writing.
      74  
      75  @end deftypefn
      76  
      77  */
      78  
      79  int
      80  mkstemps (char *pattern, int suffix_len)
      81  {
      82    static const char letters[]
      83      = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
      84    static gcc_uint64_t value;
      85  #ifdef HAVE_GETTIMEOFDAY
      86    struct timeval tv;
      87  #endif
      88    char *XXXXXX;
      89    size_t len;
      90    int count;
      91  
      92    len = strlen (pattern);
      93  
      94    if ((int) len < 6 + suffix_len
      95        || strncmp (&pattern[len - 6 - suffix_len], "XXXXXX", 6))
      96      {
      97        return -1;
      98      }
      99  
     100    XXXXXX = &pattern[len - 6 - suffix_len];
     101  
     102  #ifdef HAVE_GETTIMEOFDAY
     103    /* Get some more or less random data.  */
     104    gettimeofday (&tv, NULL);
     105    value += ((gcc_uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid ();
     106  #else
     107    value += getpid ();
     108  #endif
     109  
     110    for (count = 0; count < TMP_MAX; ++count)
     111      {
     112        gcc_uint64_t v = value;
     113        int fd;
     114  
     115        /* Fill in the random bits.  */
     116        XXXXXX[0] = letters[v % 62];
     117        v /= 62;
     118        XXXXXX[1] = letters[v % 62];
     119        v /= 62;
     120        XXXXXX[2] = letters[v % 62];
     121        v /= 62;
     122        XXXXXX[3] = letters[v % 62];
     123        v /= 62;
     124        XXXXXX[4] = letters[v % 62];
     125        v /= 62;
     126        XXXXXX[5] = letters[v % 62];
     127  
     128        fd = open (pattern, O_BINARY|O_RDWR|O_CREAT|O_EXCL, 0600);
     129        if (fd >= 0)
     130  	/* The file does not exist.  */
     131  	return fd;
     132        if (errno != EEXIST
     133  #ifdef EISDIR
     134  	  && errno != EISDIR
     135  #endif
     136  	 )
     137  	/* Fatal error (EPERM, ENOSPC etc).  Doesn't make sense to loop.  */
     138  	break;
     139  
     140        /* This is a random value.  It is only necessary that the next
     141  	 TMP_MAX values generated by adding 7777 to VALUE are different
     142  	 with (module 2^32).  */
     143        value += 7777;
     144      }
     145  
     146    /* We return the null string if we can't find a unique file name.  */
     147    pattern[0] = '\0';
     148    return -1;
     149  }