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