]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/mktemp.cc
* Merge in cygwin-64bit-branch.
[newlib-cygwin.git] / winsup / cygwin / mktemp.cc
CommitLineData
5c288d43
CF
1/* mktemp.cc: mktemp functions
2
e5f37aa1 3This file is adapted for Cygwin from FreeBSD and newlib.
5c288d43
CF
4
5See the copyright at the bottom of this file. */
6
cb3f5f08
CF
7#include "winsup.h"
8#include "cygerrno.h"
cb3f5f08 9#include <fcntl.h>
e5f37aa1 10#include <sys/stat.h>
cb3f5f08
CF
11#include <unistd.h>
12
3083fa94 13static int _gettemp(char *, int *, int, size_t, int);
cb3f5f08
CF
14static uint32_t arc4random ();
15
16static const char padchar[] =
17"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
18
19extern "C" int
20mkstemp(char *path)
21{
22 int fd;
3083fa94 23 return _gettemp(path, &fd, 0, 0, O_BINARY) ? fd : -1;
cb3f5f08
CF
24}
25
26extern "C" char *
27mkdtemp(char *path)
28{
3083fa94 29 return _gettemp(path, NULL, 1, 0, 0) ? path : NULL;
e5f37aa1
CV
30}
31
32extern "C" int
33mkstemps(char *path, int len)
34{
35 int fd;
3083fa94
EB
36 return _gettemp(path, &fd, 0, len, O_BINARY) ? fd : -1;
37}
38
39extern "C" int
40mkostemp(char *path, int flags)
41{
42 int fd;
43 return _gettemp(path, &fd, 0, 0, flags & ~O_ACCMODE) ? fd : -1;
44}
45
46extern "C" int
47mkostemps(char *path, int len, int flags)
48{
49 int fd;
50 return _gettemp(path, &fd, 0, len, flags & ~O_ACCMODE) ? fd : -1;
cb3f5f08
CF
51}
52
cb3f5f08
CF
53extern "C" char *
54mktemp(char *path)
55{
3083fa94 56 return _gettemp(path, NULL, 0, 0, 0) ? path : (char *) NULL;
cb3f5f08
CF
57}
58
59static int
3083fa94 60_gettemp(char *path, int *doopen, int domkdir, size_t suffixlen, int flags)
cb3f5f08
CF
61{
62 char *start, *trv, *suffp;
63 char *pad;
64
65 if (doopen && domkdir)
66 {
67 set_errno (EINVAL);
68 return 0;
69 }
70
e5f37aa1
CV
71 trv = strchr (path, '\0');
72 if ((size_t) (trv - path) < suffixlen)
cb3f5f08
CF
73 {
74 set_errno (EINVAL);
75 return 0;
76 }
e5f37aa1
CV
77 trv -= suffixlen;
78 suffp = trv--;
cb3f5f08
CF
79
80 /* Fill space with random characters */
81 while (trv >= path && *trv == 'X')
82 {
83 uint32_t rand = arc4random () % (sizeof (padchar) - 1);
84 *trv-- = padchar[rand];
85 }
e5f37aa1
CV
86 if (suffp - trv < 6)
87 {
88 set_errno (EINVAL);
89 return 0;
90 }
cb3f5f08
CF
91 start = trv + 1;
92
93 /*
94 * check the target directory.
95 */
61522196 96 struct stat sbuf;
cb3f5f08
CF
97 if (doopen != NULL || domkdir)
98 {
99 for (; trv > path; trv--)
100 {
101 if (*trv == '/')
102 {
103 *trv = '\0';
104 int rval = stat64 (path, &sbuf);
105 *trv = '/';
106 if (rval != 0)
107 return 0;
108 if (!S_ISDIR (sbuf.st_mode))
109 {
110 set_errno (ENOTDIR);
111 return 0;
112 }
113 break;
114 }
115 }
116 }
117
118 for (;;)
119 {
120 if (doopen)
121 {
3083fa94 122 if ((*doopen = open (path, O_CREAT | O_EXCL | O_RDWR | flags,
d1efa4e8 123 S_IRUSR | S_IWUSR)) >= 0)
cb3f5f08
CF
124 return 1;
125 if (errno != EEXIST)
126 return 0;
127 }
128 else if (domkdir)
129 {
130 if (mkdir (path, 0700) == 0)
131 return 1;
132 if (errno != EEXIST)
133 return 0;
134 }
135 else if (lstat64 (path, &sbuf))
136 return errno == ENOENT;
137
138 /* If we have a collision, cycle through the space of filenames */
139 for (trv = start;;)
140 {
141 if (*trv == '\0' || trv == suffp)
142 return 0;
143 pad = strchr (padchar, *trv);
144 if (pad == NULL || *++pad == '\0')
145 *trv++ = padchar[0];
146 else
147 {
148 *trv++ = *pad;
149 break;
150 }
151 }
152 }
153 /*NOTREACHED*/
154}
155
156static uint32_t
157arc4random ()
158{
159 union
160 {
161 uint32_t rand;
162 char buf[sizeof (int) / 8];
163 } r;
164 int fd = open ("/dev/urandom", O_RDONLY);
165 read (fd, r.buf, 4);
166 close (fd);
167 return r.rand;
168}
169
170/*
171* Copyright (c) 1987, 1993
172* The Regents of the University of California. All rights reserved.
173*
174* Redistribution and use in source and binary forms, with or without
175* modification, are permitted provided that the following conditions
176* are met:
177* 1. Redistributions of source code must retain the above copyright
178* notice, this list of conditions and the following disclaimer.
179* 2. Redistributions in binary form must reproduce the above copyright
180* notice, this list of conditions and the following disclaimer in the
181* documentation and/or other materials provided with the distribution.
cb3f5f08
CF
182* 4. Neither the name of the University nor the names of its contributors
183* may be used to endorse or promote products derived from this software
184* without specific prior written permission.
185*
186* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
187* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
188* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
189* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
190* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
191* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
192* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
193* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
194* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
195* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
196* SUCH DAMAGE.
197*/
This page took 0.253411 seconds and 5 git commands to generate.