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