95{
97 *trv;
99 u_int pid;
100
101 /*
102 * To guarantee multiple calls generate unique names even if the file is
103 * not created. 676 different possibilities with 7 or more X's, 26 with 6
104 * or less.
105 */
106 static char xtra[2] = "aa";
107 int xcnt = 0;
108
110 /* doopen may be NULL */
111
112 pid = getpid();
113
114 /* Move to end of path and count trailing X's. */
115 for (trv = path; *trv; ++trv)
116 if (*trv == 'X')
117 xcnt++;
118 else
119 xcnt = 0;
120
121 /* Use at least one from xtra. Use 2 if more than 6 X's. */
122 if (xcnt > 0)
123 {
124 *--trv = xtra[0];
125 xcnt--;
126 }
127 if (xcnt > 5)
128 {
129 *--trv = xtra[1];
130 xcnt--;
131 }
132
133 /* Set remaining X's to pid digits with 0's to the left. */
134 for (; xcnt > 0; xcnt--)
135 {
136 *--trv = (pid % 10) + '0';
137 pid /= 10;
138 }
139
140 /* update xtra for next call. */
141 if (xtra[0] != 'z')
142 xtra[0]++;
143 else
144 {
145 xtra[0] = 'a';
146 if (xtra[1] != 'z')
147 xtra[1]++;
148 else
149 xtra[1] = 'a';
150 }
151
152 /*
153 * check the target directory; if you have six X's and it doesn't exist
154 * this runs for a *very* long time.
155 */
156 for (
start = trv + 1;; --trv)
157 {
158 if (trv <= path)
159 break;
160 if (*trv == '/')
161 {
163
164 *trv = '0円';
165 e =
stat(path, &sbuf);
166 *trv = '/';
168 return doopen == NULL && !domkdir;
170 {
171 errno = ENOTDIR;
172 return doopen == NULL && !domkdir;
173 }
174 break;
175 }
176 }
177
178 for (;;)
179 {
180 if (doopen)
181 {
182 if ((*doopen =
183 open(path, O_CREAT | O_EXCL | O_RDWR, 0600)) >= 0)
184 return 1;
185 if (errno != EEXIST)
186 return 0;
187 }
188 else if (domkdir)
189 {
190 if (
mkdir(path, 0700) >= 0)
191 return 1;
192 if (errno != EEXIST)
193 return 0;
194 }
195 else if (
lstat(path, &sbuf))
196 return errno == ENOENT ? 1 : 0;
197
198 /* tricky little algorithm for backward compatibility */
200 {
201 if (!*trv)
202 return 0;
203 if (*trv == 'z')
204 *trv++ = 'a';
205 else
206 {
207 if (isdigit((unsigned char) *trv))
208 *trv = 'a';
209 else
210 ++*trv;
211 break;
212 }
213 }
214 }
215 /* NOTREACHED */
216}