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