]>
Commit | Line | Data |
---|---|---|
6ad85e8a | 1 | /* A reasonably functional tmpnam. */ |
30a4f2a8 | 2 | |
6ad85e8a | 3 | /* Originally by Tom Hageman, tom@basil.icce.rug.nl */ |
30a4f2a8 | 4 | |
6ad85e8a | 5 | /* |
6 | * This tmpnam() was changed by Gerben_Wierda@RnA.nl to serve as | |
7 | * tempnam() for squid-1.1.6. It ignores the directory parameter, every | |
8 | * temp file is written in /tmp. | |
9 | */ | |
30a4f2a8 | 10 | |
f7f3304a | 11 | #include "squid.h" |
27bc2077 | 12 | #include "compat/tempnam.h" |
a8f7d3ee | 13 | |
88738790 | 14 | #if HAVE_LIBC_H |
15 | #include <libc.h> | |
16 | #endif | |
6ad85e8a | 17 | #if HAVE_LIMITS_H |
18 | #include <limits.h> | |
30a4f2a8 | 19 | #endif |
20 | #if HAVE_UNISTD_H | |
21 | #include <unistd.h> | |
22 | #endif | |
23 | ||
6ad85e8a | 24 | #undef TMP_MAX |
30a4f2a8 | 25 | |
6ad85e8a | 26 | #define _tmp "/tmp/" |
27 | #define lengthof_tmp 5 | |
30a4f2a8 | 28 | |
6ad85e8a | 29 | #ifndef LONG_BIT |
30 | #define LONG_BIT (CHAR_BIT * 4) /* assume sizeof(long) == 4 */ | |
31 | #endif | |
30a4f2a8 | 32 | |
6ad85e8a | 33 | #define L_tmpmin (lengthof_tmp + 5) /* 5 chars for pid. */ |
30a4f2a8 | 34 | |
6ad85e8a | 35 | #if (L_tmpnam > L_tmpmin) |
36 | #if (L_tmpnam > L_tmpmin + LONG_BIT / 6) /* base 64 */ | |
37 | #define TMP_MAX ULONG_MAX | |
38 | #else | |
39 | #define TMP_MAX ((1L << (6 * (L_tmpnam - L_tmpmin))) - 1) | |
40 | #endif | |
41 | #else | |
42 | #ifndef L_tmpnam | |
43 | #error "tmpnam: L_tmpnam undefined" | |
44 | #else | |
45 | #error "tmpnam: L_tmpnam too small" | |
46 | #endif | |
47 | #endif | |
30a4f2a8 | 48 | |
b8d8561b | 49 | |
50 | static char * | |
6ad85e8a | 51 | _tmpnam(void) |
b8d8561b | 52 | { |
6ad85e8a | 53 | static const char digits[] = |
54 | #if (L_tmpnam >= L_tmpmin + LONG_BIT / 4) | |
26ac0430 | 55 | "0123456789abcdef"; |
6ad85e8a | 56 | #define TMP_BASE 16 |
57 | #else | |
26ac0430 | 58 | "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-"; |
6ad85e8a | 59 | #define TMP_BASE 64 |
60 | #endif | |
61 | static unsigned long lastcount = 0; | |
62 | static char buffer[L_tmpnam + 1]; | |
63 | char *s = buffer; | |
64 | unsigned long count = lastcount; | |
30a4f2a8 | 65 | pid_t pid = getpid(); |
30a4f2a8 | 66 | |
6ad85e8a | 67 | if (sizeof(_tmp) - 1 != lengthof_tmp) |
26ac0430 | 68 | abort(); /* Consistency error. */ |
30a4f2a8 | 69 | |
30a4f2a8 | 70 | for (;;) { |
26ac0430 AJ |
71 | register int i = L_tmpnam; |
72 | register unsigned long c; | |
73 | register unsigned int p; | |
74 | ||
75 | /* Build filename. (the hard way) */ | |
76 | s += i; | |
77 | *s = '\0'; | |
78 | ||
79 | c = (count == TMP_MAX) ? 0 : ++count; | |
80 | do { | |
81 | *--s = digits[c % TMP_BASE]; | |
82 | c /= TMP_BASE; | |
83 | } while (--i > L_tmpmin); | |
84 | ||
85 | p = (unsigned int) pid; | |
86 | do { | |
87 | *--s = digits[p % 10]; | |
88 | p /= 10; | |
89 | } while (--i > lengthof_tmp); | |
90 | ||
91 | do { | |
92 | *--s = _tmp[--i]; | |
93 | } while (i > 0); | |
94 | ||
95 | /* Check that the file doesn't exist. */ | |
96 | if (access(s, 0) != 0) | |
97 | break; | |
98 | ||
99 | /* It exists; retry unless we tried them all. */ | |
100 | if (count == lastcount) { | |
101 | s = NULL; | |
102 | break; | |
103 | } | |
30a4f2a8 | 104 | } |
105 | ||
6ad85e8a | 106 | lastcount = count; |
30a4f2a8 | 107 | |
6ad85e8a | 108 | return s; |
30a4f2a8 | 109 | } |
110 | ||
b8d8561b | 111 | char * |
112 | tempnam(const char *dir, const char *pfx) | |
113 | { | |
6ad85e8a | 114 | return _tmpnam(); |
30a4f2a8 | 115 | } |
116 | ||
6ad85e8a | 117 | #ifdef TEST |
118 | int | |
119 | main() | |
120 | { | |
121 | char *t; | |
122 | int n = 0; | |
123 | while ((t = tempnam(NULL, NULL))) { | |
26ac0430 AJ |
124 | printf("%s\n", t); |
125 | if (++n == 1000) | |
126 | break; | |
6ad85e8a | 127 | } |
128 | return 1; | |
129 | } | |
130 | #endif |