This source file includes following definitions.
- hash32s
- utfile_mkstemps
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <ctype.h>
20 #include <signal.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #if defined(__sunos) && defined(SYSV)
27 # include <sys/param.h>
28 #endif
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <time.h>
32 #include <sys/time.h>
33 #include <stdint.h>
34 #include <unistd.h>
35
36 #define MAX_MKSTEMPS_TRIES 10000
37
38 #if defined(__MINGW64__) || defined(__MINGW32__)
39 # include "bsd_random.h"
40 # define random bsd_random
41 # define srandom bsd_srandom
42 #endif
43
44 #if defined(__MACH__) && defined(__APPLE__) && \
45 ( defined(__PPC__) || defined(_ARCH_PPC) )
46 # include <mach/clock.h>
47 # include <mach/mach.h>
48 # ifdef MACOSXPPC
49 # undef MACOSXPPC
50 # endif
51 # define MACOSXPPC 1
52 #endif
53
54
55 #undef FREE
56 #ifdef TESTING
57 # define FREE(p) free(p)
58 #else
59 # define FREE(p) do \
60 { \
61 free((p)); \
62 (p) = NULL; \
63 } while(0)
64 #endif
65
66 static char valid_file_name_chars[]
67 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
68
69 static inline uint32_t
70 hash32s(const void *buf, size_t len, uint32_t h)
71 {
72 const unsigned char *p = buf;
73
74 for (size_t i = 0; i < len; i++)
75 h = h * 31 + p[i];
76
77 h ^= h >> 17;
78 h *= UINT32_C(0xed5ad4bb);
79 h ^= h >> 11;
80 h *= UINT32_C(0xac4c1b51);
81 h ^= h >> 15;
82 h *= UINT32_C(0x31848bab);
83 h ^= h >> 14;
84
85 return h;
86 }
87
88
89
90
91
92
93 int
94 utfile_mkstemps(char *request_pattern, int suffix_length)
95 {
96 long pattern_length;
97 int st1ret;
98 char *mask_pointer;
99 struct timespec st1;
100
101 #ifdef MACOSXPPC
102 (void)st1;
103 #endif
104 char *pattern = strdup(request_pattern);
105 if (!pattern)
106 {
107 fprintf (stderr, "\rFATAL: Out of memory! Aborting at %s[%s:%d]\r\n",
108 __func__, __FILE__, __LINE__);
109 #if defined(USE_BACKTRACE)
110 # ifdef SIGUSR2
111 (void)raise(SIGUSR2);
112
113 # endif
114 #endif
115 abort();
116 }
117
118 pattern_length = (long) strlen(pattern);
119
120 #ifdef MACOSXPPC
121 # undef USE_MONOTONIC
122 #endif
123 #ifdef USE_MONOTONIC
124 st1ret = clock_gettime(CLOCK_MONOTONIC, &st1);
125 #else
126 # ifdef MACOSXPPC
127 clock_serv_t cclock;
128 mach_timespec_t mts;
129 host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
130 clock_get_time(cclock, &mts);
131 mach_port_deallocate(mach_task_self(), cclock);
132 st1.tv_sec = mts.tv_sec;
133 st1.tv_nsec = mts.tv_nsec;
134 st1ret = 0;
135 # else
136 st1ret = clock_gettime(CLOCK_REALTIME, &st1);
137 # endif
138 #endif
139 if (st1ret != 0)
140 {
141 fprintf (stderr, "\rFATAL: clock_gettime failure! Aborting at %s[%s:%d]\r\n",
142 __func__, __FILE__, __LINE__);
143 #if defined(USE_BACKTRACE)
144 # ifdef SIGUSR2
145 (void)raise(SIGUSR2);
146
147 # endif
148 #endif
149 abort();
150 }
151
152 uint32_t h = 0;
153 #if __STDC_VERSION__ < 201112L
154
155 void *(*mallocptr)() = malloc;
156 h = hash32s(&mallocptr, sizeof(mallocptr), h);
157 #endif
158 void *small = malloc(1);
159 h = hash32s(&small, sizeof(small), h);
160 FREE(small);
161 void *big = malloc(1UL << 20);
162 h = hash32s(&big, sizeof(big), h);
163 FREE(big);
164 void *ptr = &ptr;
165 h = hash32s(&ptr, sizeof(ptr), h);
166 time_t t = time(0);
167 h = hash32s(&t, sizeof(t), h);
168 for (int i = 0; i < 1000; i++)
169 {
170 unsigned long counter = 0;
171 clock_t start = clock();
172 while (clock() == start)
173 {
174 counter++;
175 }
176 h = hash32s(&start, sizeof(start), h);
177 h = hash32s(&counter, sizeof(counter), h);
178 }
179 int mypid = (int)getpid();
180 h = hash32s(&mypid, sizeof(mypid), h);
181 char rnd[4];
182 FILE *f = fopen("/dev/urandom", "rb");
183 if (f)
184 {
185 if (fread(rnd, sizeof(rnd), 1, f))
186 {
187 h = hash32s(rnd, sizeof(rnd), h);
188 }
189 fclose(f);
190 }
191 srandom(h);
192
193 if (( (long) pattern_length - 6 ) < (long) suffix_length)
194 {
195 FREE(pattern);
196 return ( -1 );
197 }
198
199 long mask_offset = (long) pattern_length - ( 6 + (long) suffix_length );
200
201 if (strncmp(&pattern[mask_offset], "XXXXXX", 6))
202 {
203 FREE(pattern);
204 return ( -1 );
205 }
206
207 mask_pointer = &pattern[mask_offset];
208
209 long valid_char_count = (long) strlen(valid_file_name_chars);
210
211 if (valid_char_count < 1)
212 {
213 FREE(pattern);
214 return ( -1 );
215 }
216
217 for (int count = 0; count < MAX_MKSTEMPS_TRIES; count++)
218 {
219 for (int mask_index = 0; mask_index < 6; mask_index++)
220 {
221 mask_pointer[mask_index]
222 = valid_file_name_chars[random() % valid_char_count];
223 }
224
225 int fd = open(pattern, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
226
227 if (fd >= 0)
228 {
229 FREE(pattern);
230 return ( fd );
231 }
232
233
234
235
236
237
238 if (( errno != EEXIST ) && ( errno != EISDIR ))
239 {
240 break;
241 }
242 }
243
244
245
246
247
248
249 FREE(pattern);
250 return ( -1 );
251 }