1 /* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
2    This file is part of 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, Suite 500,
17    Boston, MA 02110-1335, USA.  */
18 
19 #define __PROFTPD_SUPPORT_LIBRARY
20 
21 #include <conf.h>
22 #include <libsupp.h>
23 
24 #ifndef HAVE_MKSTEMP
25 
26 /* These are the characters used in temporary filenames.  */
27 static const char letters[] =
28 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
29 
30 /* Generate a temporary file name based on TMPL.  TMPL must match the
31    rules for mk[s]temp (i.e. end in "XXXXXX").  The name constructed
32    does not exist at the time of the call to mkstemp().  TMPL is
33    overwritten with the result.  Creates the file and returns a read-write
34    fd; the file is mode 0600 modulo umask.
35 
36    We use a clever algorithm to get hard-to-predict names. */
mkstemp(char * tmpl)37 int mkstemp (char *tmpl) {
38   int len;
39   char *XXXXXX;
40   static uint64_t value;
41   struct timeval tv;
42   int count, fd;
43   int save_errno = errno;
44 
45   len = strlen (tmpl);
46   if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
47     {
48       errno = EINVAL;
49       return -1;
50     }
51 
52   /* This is where the Xs start.  */
53   XXXXXX = &tmpl[len - 6];
54 
55   /* Get some more or less random data.  */
56   gettimeofday (&tv, NULL);
57   value += ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid ();
58 
59   for (count = 0; count < TMP_MAX; value += 7777, ++count)
60     {
61       uint64_t v = value;
62 
63       /* Fill in the random bits.  */
64       XXXXXX[0] = letters[v % 62];
65       v /= 62;
66       XXXXXX[1] = letters[v % 62];
67       v /= 62;
68       XXXXXX[2] = letters[v % 62];
69       v /= 62;
70       XXXXXX[3] = letters[v % 62];
71       v /= 62;
72       XXXXXX[4] = letters[v % 62];
73       v /= 62;
74       XXXXXX[5] = letters[v % 62];
75 
76 /* NOTE: this, or test for _LARGEFILE_SOURCE in order to use the O_LARGEFILE
77  *  open flag
78  */
79 
80 #ifdef _LARGEFILE_SOURCE
81       fd = open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, 0600);
82 #else
83       fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, 0600);
84 #endif
85       if (fd >= 0)
86 	{
87           errno = save_errno;
88           return fd;
89         }
90       else if (errno != EEXIST)
91         /* Any other error will apply also to other names we might
92            try, and there are 2^32 or so of them, so give up now. */
93         return -1;
94     }
95 
96   /* We got out of the loop because we ran out of combinations to try.  */
97   errno = EEXIST;
98   return -1;
99 }
100 
101 #else /* HAVE_MKSTEMP */
102 void
pr_os_already_has_mkstemp(void)103 pr_os_already_has_mkstemp(void)
104 {
105 }
106 #endif /* HAVE_MKSTEMP */
107