xref: /titanic_41/usr/src/lib/libast/common/comp/omitted.c (revision da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968)
1*da2e3ebdSchin #pragma prototyped noticed
2*da2e3ebdSchin 
3*da2e3ebdSchin /*
4*da2e3ebdSchin  * workarounds to bring the native interface close to posix and x/open
5*da2e3ebdSchin  */
6*da2e3ebdSchin 
7*da2e3ebdSchin #if defined(__STDPP__directive) && defined(__STDPP__hide)
8*da2e3ebdSchin __STDPP__directive pragma pp:hide utime utimes
9*da2e3ebdSchin #else
10*da2e3ebdSchin #define utime		______utime
11*da2e3ebdSchin #define utimes		______utimes
12*da2e3ebdSchin #endif
13*da2e3ebdSchin 
14*da2e3ebdSchin #include <ast.h>
15*da2e3ebdSchin #include <error.h>
16*da2e3ebdSchin #include <tm.h>
17*da2e3ebdSchin 
18*da2e3ebdSchin #include "FEATURE/omitted"
19*da2e3ebdSchin 
20*da2e3ebdSchin #undef	OMITTED
21*da2e3ebdSchin 
22*da2e3ebdSchin #if _win32_botch
23*da2e3ebdSchin 
24*da2e3ebdSchin #define	OMITTED	1
25*da2e3ebdSchin 
26*da2e3ebdSchin #include <ls.h>
27*da2e3ebdSchin #include <utime.h>
28*da2e3ebdSchin 
29*da2e3ebdSchin #if __CYGWIN__
30*da2e3ebdSchin #include <ast_windows.h>
31*da2e3ebdSchin #if _win32_botch_execve || _lib_spawn_mode
32*da2e3ebdSchin #define CONVERT		1
33*da2e3ebdSchin #endif
34*da2e3ebdSchin #endif
35*da2e3ebdSchin 
36*da2e3ebdSchin #if defined(__STDPP__directive) && defined(__STDPP__hide)
37*da2e3ebdSchin __STDPP__directive pragma pp:nohide utime utimes
38*da2e3ebdSchin #else
39*da2e3ebdSchin #undef	utime
40*da2e3ebdSchin #undef	utimes
41*da2e3ebdSchin #endif
42*da2e3ebdSchin 
43*da2e3ebdSchin #ifndef MAX_PATH
44*da2e3ebdSchin #define MAX_PATH	PATH_MAX
45*da2e3ebdSchin #endif
46*da2e3ebdSchin 
47*da2e3ebdSchin /*
48*da2e3ebdSchin  * these workarounds assume each system call foo() has a _foo() entry
49*da2e3ebdSchin  * which is true for __CYGWIN__ and __EMX__ (both gnu based)
50*da2e3ebdSchin  *
51*da2e3ebdSchin  * the workarounds handle:
52*da2e3ebdSchin  *
53*da2e3ebdSchin  *	(1) .exe suffix inconsistencies
54*da2e3ebdSchin  *	(2) /bin/sh reference in execve() and spawnve()
55*da2e3ebdSchin  *	(3) bogus getpagesize() return values
56*da2e3ebdSchin  *	(4) a fork() bug that screws up shell fork()+script
57*da2e3ebdSchin  *
58*da2e3ebdSchin  * NOTE: Not all workarounds can be handled by unix syscall intercepts.
59*da2e3ebdSchin  *	 In particular, { ksh nmake } have workarounds for case-ignorant
60*da2e3ebdSchin  *	 filesystems and { libast } has workarounds for win32 locale info.
61*da2e3ebdSchin  */
62*da2e3ebdSchin 
63*da2e3ebdSchin #undef _pathconf
64*da2e3ebdSchin #undef pathconf
65*da2e3ebdSchin #undef stat
66*da2e3ebdSchin 
67*da2e3ebdSchin extern int		_access(const char*, int);
68*da2e3ebdSchin extern unsigned int	_alarm(unsigned int);
69*da2e3ebdSchin extern int		_chmod(const char*, mode_t);
70*da2e3ebdSchin extern int		_close(int);
71*da2e3ebdSchin extern pid_t		_execve(const char*, char* const*, char* const*);
72*da2e3ebdSchin extern int		_link(const char*, const char*);
73*da2e3ebdSchin extern int		_open(const char*, int, ...);
74*da2e3ebdSchin extern long		_pathconf(const char*, int);
75*da2e3ebdSchin extern ssize_t		_read(int, void*, size_t);
76*da2e3ebdSchin extern int		_rename(const char*, const char*);
77*da2e3ebdSchin extern pid_t		_spawnve(int, const char*, char* const*, char* const*);
78*da2e3ebdSchin extern int		_stat(const char*, struct stat*);
79*da2e3ebdSchin extern int		_unlink(const char*);
80*da2e3ebdSchin extern int		_utime(const char*, const struct utimbuf*);
81*da2e3ebdSchin extern int		_utimes(const char*, const struct timeval*);
82*da2e3ebdSchin extern ssize_t		_write(int, const void*, size_t);
83*da2e3ebdSchin 
84*da2e3ebdSchin #if defined(__EXPORT__)
85*da2e3ebdSchin #define extern	__EXPORT__
86*da2e3ebdSchin #endif
87*da2e3ebdSchin 
88*da2e3ebdSchin static char*
suffix(register const char * path)89*da2e3ebdSchin suffix(register const char* path)
90*da2e3ebdSchin {
91*da2e3ebdSchin 	register const char*	s = path + strlen(path);
92*da2e3ebdSchin 	register int		c;
93*da2e3ebdSchin 
94*da2e3ebdSchin 	while (s > path)
95*da2e3ebdSchin 		if ((c = *--s) == '.')
96*da2e3ebdSchin 			return (char*)s + 1;
97*da2e3ebdSchin 		else if (c == '/' || c == '\\')
98*da2e3ebdSchin 			break;
99*da2e3ebdSchin 	return 0;
100*da2e3ebdSchin }
101*da2e3ebdSchin 
102*da2e3ebdSchin static int
execrate(const char * path,char * buf,int size,int physical)103*da2e3ebdSchin execrate(const char* path, char* buf, int size, int physical)
104*da2e3ebdSchin {
105*da2e3ebdSchin 	char*	s;
106*da2e3ebdSchin 	int	n;
107*da2e3ebdSchin 	int	oerrno;
108*da2e3ebdSchin 
109*da2e3ebdSchin 	if (suffix(path))
110*da2e3ebdSchin 		return 0;
111*da2e3ebdSchin 	oerrno = errno;
112*da2e3ebdSchin 	if (physical || strlen(path) >= size || !(s = pathcanon(strcpy(buf, path), PATH_PHYSICAL|PATH_DOTDOT|PATH_EXISTS)))
113*da2e3ebdSchin 		snprintf(buf, size, "%s.exe", path);
114*da2e3ebdSchin 	else if (!suffix(buf) && ((buf + size) - s) >= 4)
115*da2e3ebdSchin 		strcpy(s, ".exe");
116*da2e3ebdSchin 	errno = oerrno;
117*da2e3ebdSchin 	return 1;
118*da2e3ebdSchin }
119*da2e3ebdSchin 
120*da2e3ebdSchin /*
121*da2e3ebdSchin  * return 0 if path is magic, -1 otherwise
122*da2e3ebdSchin  * ux!=0 set to 1 if path is unix executable
123*da2e3ebdSchin  * ux!=0 also retains errno for -1 return
124*da2e3ebdSchin  */
125*da2e3ebdSchin 
126*da2e3ebdSchin static int
magic(const char * path,int * ux)127*da2e3ebdSchin magic(const char* path, int* ux)
128*da2e3ebdSchin {
129*da2e3ebdSchin 	int		fd;
130*da2e3ebdSchin 	int		r;
131*da2e3ebdSchin 	int		n;
132*da2e3ebdSchin 	int		m;
133*da2e3ebdSchin 	int		oerrno;
134*da2e3ebdSchin #if CONVERT
135*da2e3ebdSchin 	unsigned char	buf[512];
136*da2e3ebdSchin #else
137*da2e3ebdSchin 	unsigned char	buf[2];
138*da2e3ebdSchin #endif
139*da2e3ebdSchin 
140*da2e3ebdSchin 	oerrno = errno;
141*da2e3ebdSchin 	if ((fd = _open(path, O_RDONLY, 0)) >= 0)
142*da2e3ebdSchin 	{
143*da2e3ebdSchin #if CONVERT
144*da2e3ebdSchin 		if (ux)
145*da2e3ebdSchin 			n = sizeof(buf);
146*da2e3ebdSchin 		else
147*da2e3ebdSchin #endif
148*da2e3ebdSchin 			n = 2;
149*da2e3ebdSchin 		r = (m = _read(fd, buf, n)) >= 2 && (buf[1] == 0x5a && (buf[0] == 0x4c || buf[0] == 0x4d) || ux && buf[0] == '#' && buf[1] == '!' && (*ux = 1) && !(ux = 0)) ? 0 : -1;
150*da2e3ebdSchin 		close(fd);
151*da2e3ebdSchin 		if (ux)
152*da2e3ebdSchin 		{
153*da2e3ebdSchin 			if (r)
154*da2e3ebdSchin 				oerrno = ENOEXEC;
155*da2e3ebdSchin 			else if (m > 61 && (n = buf[60] | (buf[61]<<8) + 92) < (m - 1))
156*da2e3ebdSchin 				*ux = (buf[n] | (buf[n+1]<<8)) == 3;
157*da2e3ebdSchin 			else
158*da2e3ebdSchin 				*ux = 0;
159*da2e3ebdSchin 		}
160*da2e3ebdSchin 	}
161*da2e3ebdSchin 	else if (!ux)
162*da2e3ebdSchin 		r = -1;
163*da2e3ebdSchin 	else if (errno == ENOENT)
164*da2e3ebdSchin 	{
165*da2e3ebdSchin 		oerrno = errno;
166*da2e3ebdSchin 		r = -1;
167*da2e3ebdSchin 	}
168*da2e3ebdSchin 	else
169*da2e3ebdSchin 	{
170*da2e3ebdSchin 		r = 0;
171*da2e3ebdSchin 		*ux = 0;
172*da2e3ebdSchin 	}
173*da2e3ebdSchin 	errno = oerrno;
174*da2e3ebdSchin 	return r;
175*da2e3ebdSchin }
176*da2e3ebdSchin 
177*da2e3ebdSchin #if _win32_botch_access
178*da2e3ebdSchin 
179*da2e3ebdSchin extern int
access(const char * path,int op)180*da2e3ebdSchin access(const char* path, int op)
181*da2e3ebdSchin {
182*da2e3ebdSchin 	int	r;
183*da2e3ebdSchin 	int	oerrno;
184*da2e3ebdSchin 	char	buf[PATH_MAX];
185*da2e3ebdSchin 
186*da2e3ebdSchin 	oerrno = errno;
187*da2e3ebdSchin 	if ((r = _access(path, op)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
188*da2e3ebdSchin 	{
189*da2e3ebdSchin 		errno = oerrno;
190*da2e3ebdSchin 		r = _access(buf, op);
191*da2e3ebdSchin 	}
192*da2e3ebdSchin 	return r;
193*da2e3ebdSchin }
194*da2e3ebdSchin 
195*da2e3ebdSchin #endif
196*da2e3ebdSchin 
197*da2e3ebdSchin #if _win32_botch_alarm
198*da2e3ebdSchin 
199*da2e3ebdSchin extern unsigned int
alarm(unsigned int s)200*da2e3ebdSchin alarm(unsigned int s)
201*da2e3ebdSchin {
202*da2e3ebdSchin 	unsigned int		n;
203*da2e3ebdSchin 	unsigned int		r;
204*da2e3ebdSchin 
205*da2e3ebdSchin 	static unsigned int	a;
206*da2e3ebdSchin 
207*da2e3ebdSchin 	n = (unsigned int)time(NiL);
208*da2e3ebdSchin 	if (a <= n)
209*da2e3ebdSchin 		r = 0;
210*da2e3ebdSchin 	else
211*da2e3ebdSchin 		r = a - n;
212*da2e3ebdSchin 	a = n + s - 1;
213*da2e3ebdSchin 	(void)_alarm(s);
214*da2e3ebdSchin 	return r;
215*da2e3ebdSchin }
216*da2e3ebdSchin 
217*da2e3ebdSchin #endif
218*da2e3ebdSchin 
219*da2e3ebdSchin #if _win32_botch_chmod
220*da2e3ebdSchin 
221*da2e3ebdSchin extern int
chmod(const char * path,mode_t mode)222*da2e3ebdSchin chmod(const char* path, mode_t mode)
223*da2e3ebdSchin {
224*da2e3ebdSchin 	int	r;
225*da2e3ebdSchin 	int	oerrno;
226*da2e3ebdSchin 	char	buf[PATH_MAX];
227*da2e3ebdSchin 
228*da2e3ebdSchin 	if ((r = _chmod(path, mode)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
229*da2e3ebdSchin 	{
230*da2e3ebdSchin 		errno = oerrno;
231*da2e3ebdSchin 		return _chmod(buf, mode);
232*da2e3ebdSchin 	}
233*da2e3ebdSchin 	if (!(r = _chmod(path, mode)) &&
234*da2e3ebdSchin 	    (mode & (S_IXUSR|S_IXGRP|S_IXOTH)) &&
235*da2e3ebdSchin 	    !suffix(path) &&
236*da2e3ebdSchin 	    (strlen(path) + 4) < sizeof(buf))
237*da2e3ebdSchin 	{
238*da2e3ebdSchin 		oerrno = errno;
239*da2e3ebdSchin 		if (!magic(path, NiL))
240*da2e3ebdSchin 		{
241*da2e3ebdSchin 			snprintf(buf, sizeof(buf), "%s.exe", path);
242*da2e3ebdSchin 			_rename(path, buf);
243*da2e3ebdSchin 		}
244*da2e3ebdSchin 		errno = oerrno;
245*da2e3ebdSchin 	}
246*da2e3ebdSchin 	return r;
247*da2e3ebdSchin }
248*da2e3ebdSchin 
249*da2e3ebdSchin #endif
250*da2e3ebdSchin 
251*da2e3ebdSchin #if _win32_botch_execve || _lib_spawn_mode
252*da2e3ebdSchin 
253*da2e3ebdSchin #if _lib_spawn_mode
254*da2e3ebdSchin 
255*da2e3ebdSchin /*
256*da2e3ebdSchin  * can anyone get const prototype args straight?
257*da2e3ebdSchin  */
258*da2e3ebdSchin 
259*da2e3ebdSchin #define execve		______execve
260*da2e3ebdSchin #define spawnve		______spawnve
261*da2e3ebdSchin 
262*da2e3ebdSchin #include <process.h>
263*da2e3ebdSchin 
264*da2e3ebdSchin #undef	execve
265*da2e3ebdSchin #undef	spawnve
266*da2e3ebdSchin 
267*da2e3ebdSchin #endif
268*da2e3ebdSchin 
269*da2e3ebdSchin #if CONVERT
270*da2e3ebdSchin 
271*da2e3ebdSchin /*
272*da2e3ebdSchin  * this intercept converts dos env vars to unix
273*da2e3ebdSchin  * we'd rather intercept main but can't twist cc to do it
274*da2e3ebdSchin  * getuid() gets ksh to do the right thing and
275*da2e3ebdSchin  * that's our main concern
276*da2e3ebdSchin  *
277*da2e3ebdSchin  *	DOSPATHVARS='a b c'	convert { a b c }
278*da2e3ebdSchin  */
279*da2e3ebdSchin 
280*da2e3ebdSchin extern uid_t		_getuid(void);
281*da2e3ebdSchin 
282*da2e3ebdSchin static int		convertinit;
283*da2e3ebdSchin 
284*da2e3ebdSchin /*
285*da2e3ebdSchin  * convertvars[0] names the list of env var names
286*da2e3ebdSchin  * convertvars[i] are not converted
287*da2e3ebdSchin  */
288*da2e3ebdSchin 
289*da2e3ebdSchin static const char*	convertvars[] = { "DOSPATHVARS", "PATH" };
290*da2e3ebdSchin 
291*da2e3ebdSchin static int
convert(register const char * d,const char * s)292*da2e3ebdSchin convert(register const char* d, const char* s)
293*da2e3ebdSchin {
294*da2e3ebdSchin 	register const char*	t;
295*da2e3ebdSchin 	register const char*	v;
296*da2e3ebdSchin 	int			i;
297*da2e3ebdSchin 
298*da2e3ebdSchin 	for (i = 0; i < elementsof(convertvars); i++)
299*da2e3ebdSchin 	{
300*da2e3ebdSchin 		for (v = convertvars[i], t = s; *t && *t == *v; t++, v++);
301*da2e3ebdSchin 		if (*t == '=' && *v == 0)
302*da2e3ebdSchin 			return 0;
303*da2e3ebdSchin 	}
304*da2e3ebdSchin 	for (;;)
305*da2e3ebdSchin 	{
306*da2e3ebdSchin 		while (*d == ' ' || *d == '\t')
307*da2e3ebdSchin 			d++;
308*da2e3ebdSchin 		if (!*d)
309*da2e3ebdSchin 			break;
310*da2e3ebdSchin 		for (t = s; *t && *t == *d; d++, t++);
311*da2e3ebdSchin 		if (*t == '=' && (*d == ' ' || *d == '\t' || *d == 0))
312*da2e3ebdSchin 			return t - s + 1;
313*da2e3ebdSchin 		while (*d && *d != ' ' && *d != '\t')
314*da2e3ebdSchin 			d++;
315*da2e3ebdSchin 	}
316*da2e3ebdSchin 	return 0;
317*da2e3ebdSchin }
318*da2e3ebdSchin 
319*da2e3ebdSchin uid_t
getuid(void)320*da2e3ebdSchin getuid(void)
321*da2e3ebdSchin {
322*da2e3ebdSchin 	register char*		d;
323*da2e3ebdSchin 	register char*		s;
324*da2e3ebdSchin 	register char*		t;
325*da2e3ebdSchin 	register char**		e;
326*da2e3ebdSchin 	int			n;
327*da2e3ebdSchin 	int			m;
328*da2e3ebdSchin 
329*da2e3ebdSchin 	if (!convertinit++ && (d = getenv(convertvars[0])))
330*da2e3ebdSchin 		for (e = environ; s = *e; e++)
331*da2e3ebdSchin 			if ((n = convert(d, s)) && (m = cygwin_win32_to_posix_path_list_buf_size(s + n)) > 0)
332*da2e3ebdSchin 			{
333*da2e3ebdSchin 				if (!(t = malloc(n + m + 1)))
334*da2e3ebdSchin 					break;
335*da2e3ebdSchin 				*e = t;
336*da2e3ebdSchin 				memcpy(t, s, n);
337*da2e3ebdSchin 				cygwin_win32_to_posix_path_list(s + n, t + n);
338*da2e3ebdSchin 			}
339*da2e3ebdSchin 	return _getuid();
340*da2e3ebdSchin }
341*da2e3ebdSchin 
342*da2e3ebdSchin #endif
343*da2e3ebdSchin 
344*da2e3ebdSchin #ifndef _P_OVERLAY
345*da2e3ebdSchin #define _P_OVERLAY	(-1)
346*da2e3ebdSchin #endif
347*da2e3ebdSchin 
348*da2e3ebdSchin #define DEBUG		1
349*da2e3ebdSchin 
350*da2e3ebdSchin static pid_t
runve(int mode,const char * path,char * const * argv,char * const * envv)351*da2e3ebdSchin runve(int mode, const char* path, char* const* argv, char* const* envv)
352*da2e3ebdSchin {
353*da2e3ebdSchin 	register char*	s;
354*da2e3ebdSchin 	register char**	p;
355*da2e3ebdSchin 	register char**	v;
356*da2e3ebdSchin 
357*da2e3ebdSchin 	void*		m1;
358*da2e3ebdSchin 	void*		m2;
359*da2e3ebdSchin 	pid_t		pid;
360*da2e3ebdSchin 	int		oerrno;
361*da2e3ebdSchin 	int		ux;
362*da2e3ebdSchin 	int		n;
363*da2e3ebdSchin #if defined(_P_DETACH) && defined(_P_NOWAIT)
364*da2e3ebdSchin 	int		pgrp;
365*da2e3ebdSchin #endif
366*da2e3ebdSchin #if CONVERT
367*da2e3ebdSchin 	char*		d;
368*da2e3ebdSchin 	char*		t;
369*da2e3ebdSchin 	int		m;
370*da2e3ebdSchin #endif
371*da2e3ebdSchin 	struct stat	st;
372*da2e3ebdSchin 	char		buf[PATH_MAX];
373*da2e3ebdSchin 	char		tmp[PATH_MAX];
374*da2e3ebdSchin 
375*da2e3ebdSchin #if DEBUG
376*da2e3ebdSchin 	static int	trace;
377*da2e3ebdSchin #endif
378*da2e3ebdSchin 
379*da2e3ebdSchin #if defined(_P_DETACH) && defined(_P_NOWAIT)
380*da2e3ebdSchin 	if (mode == _P_DETACH)
381*da2e3ebdSchin 	{
382*da2e3ebdSchin 		/*
383*da2e3ebdSchin 		 * 2004-02-29 cygwin _P_DETACH is useless:
384*da2e3ebdSchin 		 *	spawn*() returns 0 instead of the spawned pid
385*da2e3ebdSchin 		 *	spawned { pgid sid } are the same as the parent
386*da2e3ebdSchin 		 */
387*da2e3ebdSchin 
388*da2e3ebdSchin 		mode = _P_NOWAIT;
389*da2e3ebdSchin 		pgrp = 1;
390*da2e3ebdSchin 	}
391*da2e3ebdSchin 	else
392*da2e3ebdSchin 		pgrp = 0;
393*da2e3ebdSchin #endif
394*da2e3ebdSchin 	if (!envv)
395*da2e3ebdSchin 		envv = (char* const*)environ;
396*da2e3ebdSchin 	m1 = m2 = 0;
397*da2e3ebdSchin 	oerrno = errno;
398*da2e3ebdSchin #if DEBUG
399*da2e3ebdSchin 	if (!trace)
400*da2e3ebdSchin 		trace = (s = getenv("_AST_exec_trace")) ? *s : 'n';
401*da2e3ebdSchin #endif
402*da2e3ebdSchin 	if (execrate(path, buf, sizeof(buf), 0))
403*da2e3ebdSchin 	{
404*da2e3ebdSchin 		if (!_stat(buf, &st))
405*da2e3ebdSchin 			path = (const char*)buf;
406*da2e3ebdSchin 		else
407*da2e3ebdSchin 			errno = oerrno;
408*da2e3ebdSchin 	}
409*da2e3ebdSchin 	if (path != (const char*)buf && _stat(path, &st))
410*da2e3ebdSchin 		return -1;
411*da2e3ebdSchin 	if (!S_ISREG(st.st_mode) || !(st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
412*da2e3ebdSchin 	{
413*da2e3ebdSchin 		errno = EACCES;
414*da2e3ebdSchin 		return -1;
415*da2e3ebdSchin 	}
416*da2e3ebdSchin 	if (magic(path, &ux))
417*da2e3ebdSchin 	{
418*da2e3ebdSchin #if _CYGWIN_fork_works
419*da2e3ebdSchin 		errno = ENOEXEC;
420*da2e3ebdSchin 		return -1;
421*da2e3ebdSchin #else
422*da2e3ebdSchin 		ux = 1;
423*da2e3ebdSchin 		p = (char**)argv;
424*da2e3ebdSchin 		while (*p++);
425*da2e3ebdSchin 		if (!(v = (char**)malloc((p - (char**)argv + 2) * sizeof(char*))))
426*da2e3ebdSchin 		{
427*da2e3ebdSchin 			errno = EAGAIN;
428*da2e3ebdSchin 			return -1;
429*da2e3ebdSchin 		}
430*da2e3ebdSchin 		m1 = v;
431*da2e3ebdSchin 		p = v;
432*da2e3ebdSchin 		*p++ = (char*)path;
433*da2e3ebdSchin 		*p++ = (char*)path;
434*da2e3ebdSchin 		path = (const char*)pathshell();
435*da2e3ebdSchin 		if (*argv)
436*da2e3ebdSchin 			argv++;
437*da2e3ebdSchin 		while (*p++ = (char*)*argv++);
438*da2e3ebdSchin 		argv = (char* const*)v;
439*da2e3ebdSchin #endif
440*da2e3ebdSchin 	}
441*da2e3ebdSchin 
442*da2e3ebdSchin 	/*
443*da2e3ebdSchin 	 * the win32 dll search order is
444*da2e3ebdSchin 	 *	(1) the directory of path
445*da2e3ebdSchin 	 *	(2) .
446*da2e3ebdSchin 	 *	(3) /c/(WINNT|WINDOWS)/system32 /c/(WINNT|WINDOWS)
447*da2e3ebdSchin 	 *	(4) the directories on $PATH
448*da2e3ebdSchin 	 * there are no cygwin dlls in (3), so if (1) and (2) fail
449*da2e3ebdSchin 	 * to produce the required dlls its up to (4)
450*da2e3ebdSchin 	 *
451*da2e3ebdSchin 	 * the standard allows PATH to be anything once the path
452*da2e3ebdSchin 	 * to an executable is determined; this code ensures that PATH
453*da2e3ebdSchin 	 * contains /bin so that at least the cygwin dll, required
454*da2e3ebdSchin 	 * by all cygwin executables, will be found
455*da2e3ebdSchin 	 */
456*da2e3ebdSchin 
457*da2e3ebdSchin 	if (p = (char**)envv)
458*da2e3ebdSchin 	{
459*da2e3ebdSchin 		n = 1;
460*da2e3ebdSchin 		while (s = *p++)
461*da2e3ebdSchin 			if (strneq(s, "PATH=", 5))
462*da2e3ebdSchin 			{
463*da2e3ebdSchin 				s += 5;
464*da2e3ebdSchin 				do
465*da2e3ebdSchin 				{
466*da2e3ebdSchin 					s = pathcat(tmp, s, ':', NiL, "");
467*da2e3ebdSchin 					if (streq(tmp, "/usr/bin/") || streq(tmp, "/bin/"))
468*da2e3ebdSchin 					{
469*da2e3ebdSchin 						n = 0;
470*da2e3ebdSchin 						break;
471*da2e3ebdSchin 					}
472*da2e3ebdSchin 				} while (s);
473*da2e3ebdSchin 				if (n)
474*da2e3ebdSchin 				{
475*da2e3ebdSchin 					n = 0;
476*da2e3ebdSchin 					snprintf(tmp, sizeof(tmp), "%s:/bin", *(p - 1));
477*da2e3ebdSchin 					*(p - 1) = tmp;
478*da2e3ebdSchin 				}
479*da2e3ebdSchin 				break;
480*da2e3ebdSchin 			}
481*da2e3ebdSchin 		if (n)
482*da2e3ebdSchin 		{
483*da2e3ebdSchin 			n = p - (char**)envv + 1;
484*da2e3ebdSchin 			p = (char**)envv;
485*da2e3ebdSchin 			if (v = (char**)malloc(n * sizeof(char*)))
486*da2e3ebdSchin 			{
487*da2e3ebdSchin 				m2 = v;
488*da2e3ebdSchin 				envv = (char* const*)v;
489*da2e3ebdSchin 				*v++ = strcpy(tmp, "PATH=/bin");
490*da2e3ebdSchin 				while (*v++ = *p++);
491*da2e3ebdSchin 			}
492*da2e3ebdSchin 		}
493*da2e3ebdSchin #if CONVERT
494*da2e3ebdSchin 		if (!ux && (d = getenv(convertvars[0])))
495*da2e3ebdSchin 			for (p = (char**)envv; s = *p; p++)
496*da2e3ebdSchin 				if ((n = convert(d, s)) && (m = cygwin_posix_to_win32_path_list_buf_size(s + n)) > 0)
497*da2e3ebdSchin 				{
498*da2e3ebdSchin 					if (!(t = malloc(n + m + 1)))
499*da2e3ebdSchin 						break;
500*da2e3ebdSchin 					*p = t;
501*da2e3ebdSchin 					memcpy(t, s, n);
502*da2e3ebdSchin 					cygwin_posix_to_win32_path_list(s + n, t + n);
503*da2e3ebdSchin 				}
504*da2e3ebdSchin #endif
505*da2e3ebdSchin 	}
506*da2e3ebdSchin 
507*da2e3ebdSchin #if DEBUG
508*da2e3ebdSchin 	if (trace == 'a' || trace == 'e')
509*da2e3ebdSchin 	{
510*da2e3ebdSchin 		sfprintf(sfstderr, "%s %s [", mode == _P_OVERLAY ? "_execve" : "_spawnve", path);
511*da2e3ebdSchin 		for (n = 0; argv[n]; n++)
512*da2e3ebdSchin 			sfprintf(sfstderr, " '%s'", argv[n]);
513*da2e3ebdSchin 		if (trace == 'e')
514*da2e3ebdSchin 		{
515*da2e3ebdSchin 			sfprintf(sfstderr, " ] [");
516*da2e3ebdSchin 			for (n = 0; envv[n]; n++)
517*da2e3ebdSchin 				sfprintf(sfstderr, " '%s'", envv[n]);
518*da2e3ebdSchin 		}
519*da2e3ebdSchin 		sfprintf(sfstderr, " ]\n");
520*da2e3ebdSchin 		sfsync(sfstderr);
521*da2e3ebdSchin 	}
522*da2e3ebdSchin #endif
523*da2e3ebdSchin #if _lib_spawn_mode
524*da2e3ebdSchin 	if (mode != _P_OVERLAY)
525*da2e3ebdSchin 	{
526*da2e3ebdSchin 		pid = _spawnve(mode, path, argv, envv);
527*da2e3ebdSchin #if defined(_P_DETACH) && defined(_P_NOWAIT)
528*da2e3ebdSchin 		if (pid > 0 && pgrp)
529*da2e3ebdSchin 			setpgid(pid, 0);
530*da2e3ebdSchin #endif
531*da2e3ebdSchin 	}
532*da2e3ebdSchin 	else
533*da2e3ebdSchin #endif
534*da2e3ebdSchin 	{
535*da2e3ebdSchin #if defined(_P_DETACH) && defined(_P_NOWAIT)
536*da2e3ebdSchin 		if (pgrp)
537*da2e3ebdSchin 			setpgid(0, 0);
538*da2e3ebdSchin #endif
539*da2e3ebdSchin 		pid = _execve(path, argv, envv);
540*da2e3ebdSchin 	}
541*da2e3ebdSchin 	if (m1)
542*da2e3ebdSchin 		free(m1);
543*da2e3ebdSchin 	if (m2)
544*da2e3ebdSchin 		free(m2);
545*da2e3ebdSchin 	return pid;
546*da2e3ebdSchin }
547*da2e3ebdSchin 
548*da2e3ebdSchin #if _win32_botch_execve
549*da2e3ebdSchin 
550*da2e3ebdSchin extern pid_t
execve(const char * path,char * const * argv,char * const * envv)551*da2e3ebdSchin execve(const char* path, char* const* argv, char* const* envv)
552*da2e3ebdSchin {
553*da2e3ebdSchin 	return runve(_P_OVERLAY, path, argv, envv);
554*da2e3ebdSchin }
555*da2e3ebdSchin 
556*da2e3ebdSchin #endif
557*da2e3ebdSchin 
558*da2e3ebdSchin #if _lib_spawn_mode
559*da2e3ebdSchin 
560*da2e3ebdSchin extern pid_t
spawnve(int mode,const char * path,char * const * argv,char * const * envv)561*da2e3ebdSchin spawnve(int mode, const char* path, char* const* argv, char* const* envv)
562*da2e3ebdSchin {
563*da2e3ebdSchin 	return runve(mode, path, argv, envv);
564*da2e3ebdSchin }
565*da2e3ebdSchin 
566*da2e3ebdSchin #endif
567*da2e3ebdSchin 
568*da2e3ebdSchin #endif
569*da2e3ebdSchin 
570*da2e3ebdSchin #if _win32_botch_getpagesize
571*da2e3ebdSchin 
572*da2e3ebdSchin extern size_t
getpagesize(void)573*da2e3ebdSchin getpagesize(void)
574*da2e3ebdSchin {
575*da2e3ebdSchin 	return 64 * 1024;
576*da2e3ebdSchin }
577*da2e3ebdSchin 
578*da2e3ebdSchin #endif
579*da2e3ebdSchin 
580*da2e3ebdSchin #if _win32_botch_link
581*da2e3ebdSchin 
582*da2e3ebdSchin extern int
link(const char * fp,const char * tp)583*da2e3ebdSchin link(const char* fp, const char* tp)
584*da2e3ebdSchin {
585*da2e3ebdSchin 	int	r;
586*da2e3ebdSchin 	int	oerrno;
587*da2e3ebdSchin 	char	fb[PATH_MAX];
588*da2e3ebdSchin 	char	tb[PATH_MAX];
589*da2e3ebdSchin 
590*da2e3ebdSchin 	oerrno = errno;
591*da2e3ebdSchin 	if ((r = _link(fp, tp)) && errno == ENOENT && execrate(fp, fb, sizeof(fb), 1))
592*da2e3ebdSchin 	{
593*da2e3ebdSchin 		if (execrate(tp, tb, sizeof(tb), 1))
594*da2e3ebdSchin 			tp = tb;
595*da2e3ebdSchin 		errno = oerrno;
596*da2e3ebdSchin 		r = _link(fb, tp);
597*da2e3ebdSchin 	}
598*da2e3ebdSchin 	return r;
599*da2e3ebdSchin }
600*da2e3ebdSchin 
601*da2e3ebdSchin #endif
602*da2e3ebdSchin 
603*da2e3ebdSchin #if _win32_botch_open || _win32_botch_copy
604*da2e3ebdSchin 
605*da2e3ebdSchin #if _win32_botch_copy
606*da2e3ebdSchin 
607*da2e3ebdSchin /*
608*da2e3ebdSchin  * this should intercept the important cases
609*da2e3ebdSchin  * dup*() and exec*() fd's will not be intercepted
610*da2e3ebdSchin  */
611*da2e3ebdSchin 
612*da2e3ebdSchin typedef struct Exe_test_s
613*da2e3ebdSchin {
614*da2e3ebdSchin 	int		test;
615*da2e3ebdSchin 	ino_t		ino;
616*da2e3ebdSchin 	char		path[PATH_MAX];
617*da2e3ebdSchin } Exe_test_t;
618*da2e3ebdSchin 
619*da2e3ebdSchin static Exe_test_t*	exe[16];
620*da2e3ebdSchin 
621*da2e3ebdSchin extern int
close(int fd)622*da2e3ebdSchin close(int fd)
623*da2e3ebdSchin {
624*da2e3ebdSchin 	int		r;
625*da2e3ebdSchin 	int		oerrno;
626*da2e3ebdSchin 	struct stat	st;
627*da2e3ebdSchin 	char		buf[PATH_MAX];
628*da2e3ebdSchin 
629*da2e3ebdSchin 	if (fd >= 0 && fd < elementsof(exe) && exe[fd])
630*da2e3ebdSchin 	{
631*da2e3ebdSchin 		r = exe[fd]->test;
632*da2e3ebdSchin 		exe[fd]->test = 0;
633*da2e3ebdSchin 		if (r > 0 && !fstat(fd, &st) && st.st_ino == exe[fd]->ino)
634*da2e3ebdSchin 		{
635*da2e3ebdSchin 			if (r = _close(fd))
636*da2e3ebdSchin 				return r;
637*da2e3ebdSchin 			oerrno = errno;
638*da2e3ebdSchin 			if (!stat(exe[fd]->path, &st) && st.st_ino == exe[fd]->ino)
639*da2e3ebdSchin 			{
640*da2e3ebdSchin 				snprintf(buf, sizeof(buf), "%s.exe", exe[fd]->path);
641*da2e3ebdSchin 				_rename(exe[fd]->path, buf);
642*da2e3ebdSchin 			}
643*da2e3ebdSchin 			errno = oerrno;
644*da2e3ebdSchin 			return 0;
645*da2e3ebdSchin 		}
646*da2e3ebdSchin 	}
647*da2e3ebdSchin 	return _close(fd);
648*da2e3ebdSchin }
649*da2e3ebdSchin 
650*da2e3ebdSchin extern ssize_t
write(int fd,const void * buf,size_t n)651*da2e3ebdSchin write(int fd, const void* buf, size_t n)
652*da2e3ebdSchin {
653*da2e3ebdSchin 	if (fd >= 0 && fd < elementsof(exe) && exe[fd] && exe[fd]->test < 0)
654*da2e3ebdSchin 		exe[fd]->test = n >= 2 && ((unsigned char*)buf)[1] == 0x5a && (((unsigned char*)buf)[0] == 0x4c || ((unsigned char*)buf)[0] == 0x4d) && !lseek(fd, (off_t)0, SEEK_CUR);
655*da2e3ebdSchin 	return _write(fd, buf, n);
656*da2e3ebdSchin }
657*da2e3ebdSchin 
658*da2e3ebdSchin #endif
659*da2e3ebdSchin 
660*da2e3ebdSchin extern int
open(const char * path,int flags,...)661*da2e3ebdSchin open(const char* path, int flags, ...)
662*da2e3ebdSchin {
663*da2e3ebdSchin 	int		fd;
664*da2e3ebdSchin 	int		mode;
665*da2e3ebdSchin 	int		oerrno;
666*da2e3ebdSchin 	char		buf[PATH_MAX];
667*da2e3ebdSchin #if _win32_botch_copy
668*da2e3ebdSchin 	struct stat	st;
669*da2e3ebdSchin #endif
670*da2e3ebdSchin 	va_list		ap;
671*da2e3ebdSchin 
672*da2e3ebdSchin 	va_start(ap, flags);
673*da2e3ebdSchin 	mode = (flags & O_CREAT) ? va_arg(ap, int) : 0;
674*da2e3ebdSchin 	oerrno = errno;
675*da2e3ebdSchin 	fd = _open(path, flags, mode);
676*da2e3ebdSchin #if _win32_botch_open
677*da2e3ebdSchin 	if (fd < 0 && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
678*da2e3ebdSchin 	{
679*da2e3ebdSchin 		errno = oerrno;
680*da2e3ebdSchin 		fd = _open(buf, flags, mode);
681*da2e3ebdSchin 	}
682*da2e3ebdSchin #endif
683*da2e3ebdSchin #if _win32_botch_copy
684*da2e3ebdSchin 	if (fd >= 0 && fd < elementsof(exe) && strlen(path) < PATH_MAX &&
685*da2e3ebdSchin 	    (flags & (O_CREAT|O_TRUNC)) == (O_CREAT|O_TRUNC) && (mode & 0111))
686*da2e3ebdSchin 	{
687*da2e3ebdSchin 		if (!suffix(path) && !fstat(fd, &st) && (exe[fd] || (exe[fd] = (Exe_test_t*)malloc(sizeof(Exe_test_t)))))
688*da2e3ebdSchin 		{
689*da2e3ebdSchin 			exe[fd]->test = -1;
690*da2e3ebdSchin 			exe[fd]->ino = st.st_ino;
691*da2e3ebdSchin 			strcpy(exe[fd]->path, path);
692*da2e3ebdSchin 		}
693*da2e3ebdSchin 		errno = oerrno;
694*da2e3ebdSchin 	}
695*da2e3ebdSchin #endif
696*da2e3ebdSchin 	va_end(ap);
697*da2e3ebdSchin 	return fd;
698*da2e3ebdSchin }
699*da2e3ebdSchin 
700*da2e3ebdSchin #endif
701*da2e3ebdSchin 
702*da2e3ebdSchin #if _win32_botch_pathconf
703*da2e3ebdSchin 
704*da2e3ebdSchin extern long
pathconf(const char * path,int op)705*da2e3ebdSchin pathconf(const char* path, int op)
706*da2e3ebdSchin {
707*da2e3ebdSchin 	if (_access(path, F_OK))
708*da2e3ebdSchin 		return -1;
709*da2e3ebdSchin 	return _pathconf(path, op);
710*da2e3ebdSchin }
711*da2e3ebdSchin 
712*da2e3ebdSchin #endif
713*da2e3ebdSchin 
714*da2e3ebdSchin #if _win32_botch_rename
715*da2e3ebdSchin 
716*da2e3ebdSchin extern int
rename(const char * fp,const char * tp)717*da2e3ebdSchin rename(const char* fp, const char* tp)
718*da2e3ebdSchin {
719*da2e3ebdSchin 	int	r;
720*da2e3ebdSchin 	int	oerrno;
721*da2e3ebdSchin 	char	fb[PATH_MAX];
722*da2e3ebdSchin 	char	tb[PATH_MAX];
723*da2e3ebdSchin 
724*da2e3ebdSchin 	oerrno = errno;
725*da2e3ebdSchin 	if ((r = _rename(fp, tp)) && errno == ENOENT && execrate(fp, fb, sizeof(fb), 1))
726*da2e3ebdSchin 	{
727*da2e3ebdSchin 		if (execrate(tp, tb, sizeof(tb), 1))
728*da2e3ebdSchin 			tp = tb;
729*da2e3ebdSchin 		errno = oerrno;
730*da2e3ebdSchin 		r = _rename(fb, tp);
731*da2e3ebdSchin 	}
732*da2e3ebdSchin 	return r;
733*da2e3ebdSchin }
734*da2e3ebdSchin 
735*da2e3ebdSchin #endif
736*da2e3ebdSchin 
737*da2e3ebdSchin #if _win32_botch_stat
738*da2e3ebdSchin 
739*da2e3ebdSchin extern int
stat(const char * path,struct stat * st)740*da2e3ebdSchin stat(const char* path, struct stat* st)
741*da2e3ebdSchin {
742*da2e3ebdSchin 	int	r;
743*da2e3ebdSchin 	int	oerrno;
744*da2e3ebdSchin 	char	buf[PATH_MAX];
745*da2e3ebdSchin 
746*da2e3ebdSchin 	oerrno = errno;
747*da2e3ebdSchin 	if ((r = _stat(path, st)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
748*da2e3ebdSchin 	{
749*da2e3ebdSchin 		errno = oerrno;
750*da2e3ebdSchin 		r = _stat(buf, st);
751*da2e3ebdSchin 	}
752*da2e3ebdSchin 	return r;
753*da2e3ebdSchin }
754*da2e3ebdSchin 
755*da2e3ebdSchin #endif
756*da2e3ebdSchin 
757*da2e3ebdSchin #if _win32_botch_truncate
758*da2e3ebdSchin 
759*da2e3ebdSchin extern int
truncate(const char * path,off_t offset)760*da2e3ebdSchin truncate(const char* path, off_t offset)
761*da2e3ebdSchin {
762*da2e3ebdSchin 	int	r;
763*da2e3ebdSchin 	int	oerrno;
764*da2e3ebdSchin 	char	buf[PATH_MAX];
765*da2e3ebdSchin 
766*da2e3ebdSchin 	oerrno = errno;
767*da2e3ebdSchin 	if ((r = _truncate(path, offset)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
768*da2e3ebdSchin 	{
769*da2e3ebdSchin 		errno = oerrno;
770*da2e3ebdSchin 		r = _truncate(buf, offset);
771*da2e3ebdSchin 	}
772*da2e3ebdSchin 	return r;
773*da2e3ebdSchin }
774*da2e3ebdSchin 
775*da2e3ebdSchin #endif
776*da2e3ebdSchin 
777*da2e3ebdSchin #if _win32_botch_unlink
778*da2e3ebdSchin 
779*da2e3ebdSchin extern int
unlink(const char * path)780*da2e3ebdSchin unlink(const char* path)
781*da2e3ebdSchin {
782*da2e3ebdSchin 	int		r;
783*da2e3ebdSchin 	int		drive;
784*da2e3ebdSchin 	int		mask;
785*da2e3ebdSchin 	int		suffix;
786*da2e3ebdSchin 	int		stop;
787*da2e3ebdSchin 	int		oerrno;
788*da2e3ebdSchin 	unsigned long	base;
789*da2e3ebdSchin 	char		buf[PATH_MAX];
790*da2e3ebdSchin 	char		tmp[MAX_PATH];
791*da2e3ebdSchin 
792*da2e3ebdSchin #define DELETED_DIR_1	7
793*da2e3ebdSchin #define DELETED_DIR_2	16
794*da2e3ebdSchin 
795*da2e3ebdSchin 	static char	deleted[] = "%c:\\temp\\.deleted\\%08x.%03x";
796*da2e3ebdSchin 
797*da2e3ebdSchin 	static int	count = 0;
798*da2e3ebdSchin 
799*da2e3ebdSchin #if __CYGWIN__
800*da2e3ebdSchin 
801*da2e3ebdSchin 	DWORD		fattr = FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE;
802*da2e3ebdSchin 	DWORD		share = FILE_SHARE_DELETE;
803*da2e3ebdSchin 	HANDLE		hp;
804*da2e3ebdSchin 	struct stat	st;
805*da2e3ebdSchin 	char		nat[MAX_PATH];
806*da2e3ebdSchin 
807*da2e3ebdSchin 	oerrno = errno;
808*da2e3ebdSchin 	if (lstat(path, &st) || !S_ISREG(st.st_mode))
809*da2e3ebdSchin 		goto try_unlink;
810*da2e3ebdSchin 	cygwin_conv_to_full_win32_path(path, nat);
811*da2e3ebdSchin 	if (!strncasecmp(nat + 1, ":\\temp\\", 7))
812*da2e3ebdSchin 		goto try_unlink;
813*da2e3ebdSchin 	drive = nat[0];
814*da2e3ebdSchin 	path = (const char*)nat;
815*da2e3ebdSchin 	for (;;)
816*da2e3ebdSchin 	{
817*da2e3ebdSchin 		hp = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL);
818*da2e3ebdSchin 		if (hp != INVALID_HANDLE_VALUE)
819*da2e3ebdSchin 		{
820*da2e3ebdSchin 			CloseHandle(hp);
821*da2e3ebdSchin 			errno = oerrno;
822*da2e3ebdSchin 			return 0;
823*da2e3ebdSchin 		}
824*da2e3ebdSchin 		if (GetLastError() != ERROR_FILE_NOT_FOUND)
825*da2e3ebdSchin 			break;
826*da2e3ebdSchin 		if (path == (const char*)buf || !execrate(path, buf, sizeof(buf), 1))
827*da2e3ebdSchin 		{
828*da2e3ebdSchin 			errno = ENOENT;
829*da2e3ebdSchin 			return -1;
830*da2e3ebdSchin 		}
831*da2e3ebdSchin 		path = (const char*)buf;
832*da2e3ebdSchin 	}
833*da2e3ebdSchin #else
834*da2e3ebdSchin 	if (_access(path, 0))
835*da2e3ebdSchin #if _win32_botch_access
836*da2e3ebdSchin 	{
837*da2e3ebdSchin 		if (errno != ENOENT || !execrate(path, buf, sizeof(buf), 1) || _access(buf, 0))
838*da2e3ebdSchin 			return -1;
839*da2e3ebdSchin 		path = (const char*)buf;
840*da2e3ebdSchin 	}
841*da2e3ebdSchin #else
842*da2e3ebdSchin 		return -1;
843*da2e3ebdSchin #endif
844*da2e3ebdSchin 	drive = 'C':
845*da2e3ebdSchin #endif
846*da2e3ebdSchin 
847*da2e3ebdSchin 	/*
848*da2e3ebdSchin 	 * rename to a `deleted' path just in case the file is open
849*da2e3ebdSchin 	 * otherwise directory readers may choke on phantom entries
850*da2e3ebdSchin 	 */
851*da2e3ebdSchin 
852*da2e3ebdSchin 	base = ((getuid() & 0xffff) << 16) | (time(NiL) & 0xffff);
853*da2e3ebdSchin 	suffix = (getpid() & 0xfff) + count++;
854*da2e3ebdSchin 	snprintf(tmp, sizeof(tmp), deleted, drive, base, suffix);
855*da2e3ebdSchin 	if (!_rename(path, tmp))
856*da2e3ebdSchin 	{
857*da2e3ebdSchin 		path = (const char*)tmp;
858*da2e3ebdSchin 		goto try_delete;
859*da2e3ebdSchin 	}
860*da2e3ebdSchin 	if (errno != ENOTDIR && errno != ENOENT)
861*da2e3ebdSchin 		goto try_unlink;
862*da2e3ebdSchin 	tmp[DELETED_DIR_2] = 0;
863*da2e3ebdSchin 	if (_access(tmp, 0))
864*da2e3ebdSchin 	{
865*da2e3ebdSchin 		mask = umask(0);
866*da2e3ebdSchin 		tmp[DELETED_DIR_1] = 0;
867*da2e3ebdSchin 		if (_access(tmp, 0) && _mkdir(tmp, S_IRWXU|S_IRWXG|S_IRWXO))
868*da2e3ebdSchin 		{
869*da2e3ebdSchin 			umask(mask);
870*da2e3ebdSchin 			goto try_unlink;
871*da2e3ebdSchin 		}
872*da2e3ebdSchin 		tmp[DELETED_DIR_1] = '\\';
873*da2e3ebdSchin 		r = _mkdir(tmp, S_IRWXU|S_IRWXG|S_IRWXO);
874*da2e3ebdSchin 		umask(mask);
875*da2e3ebdSchin 		if (r)
876*da2e3ebdSchin 			goto try_unlink;
877*da2e3ebdSchin 		errno = 0;
878*da2e3ebdSchin 	}
879*da2e3ebdSchin 	tmp[DELETED_DIR_2] = '\\';
880*da2e3ebdSchin 	if (!errno && !_rename(path, tmp))
881*da2e3ebdSchin 	{
882*da2e3ebdSchin 		path = (const char*)tmp;
883*da2e3ebdSchin 		goto try_delete;
884*da2e3ebdSchin 	}
885*da2e3ebdSchin #if !__CYGWIN__
886*da2e3ebdSchin 	if (errno == ENOENT)
887*da2e3ebdSchin 	{
888*da2e3ebdSchin #if !_win32_botch_access
889*da2e3ebdSchin 		if (execrate(path, buf, sizeof(buf), 1) && !_rename(buf, tmp))
890*da2e3ebdSchin 			path = (const char*)tmp;
891*da2e3ebdSchin #endif
892*da2e3ebdSchin 		goto try_unlink;
893*da2e3ebdSchin 	}
894*da2e3ebdSchin #endif
895*da2e3ebdSchin 	stop = suffix;
896*da2e3ebdSchin 	do
897*da2e3ebdSchin 	{
898*da2e3ebdSchin 		snprintf(tmp, sizeof(tmp), deleted, drive, base, suffix);
899*da2e3ebdSchin 		if (!_rename(path, tmp))
900*da2e3ebdSchin 		{
901*da2e3ebdSchin 			path = (const char*)tmp;
902*da2e3ebdSchin 			goto try_delete;
903*da2e3ebdSchin 		}
904*da2e3ebdSchin 		if (++suffix > 0xfff)
905*da2e3ebdSchin 			suffix = 0;
906*da2e3ebdSchin 	} while (suffix != stop);
907*da2e3ebdSchin  try_delete:
908*da2e3ebdSchin #if __CYGWIN__
909*da2e3ebdSchin 	hp = CreateFile(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL);
910*da2e3ebdSchin 	if (hp != INVALID_HANDLE_VALUE)
911*da2e3ebdSchin 	{
912*da2e3ebdSchin 		CloseHandle(hp);
913*da2e3ebdSchin 		errno = oerrno;
914*da2e3ebdSchin 		return 0;
915*da2e3ebdSchin 	}
916*da2e3ebdSchin #endif
917*da2e3ebdSchin  try_unlink:
918*da2e3ebdSchin 	errno = oerrno;
919*da2e3ebdSchin 	return _unlink(path);
920*da2e3ebdSchin }
921*da2e3ebdSchin 
922*da2e3ebdSchin #endif
923*da2e3ebdSchin 
924*da2e3ebdSchin #if _win32_botch_utime
925*da2e3ebdSchin 
926*da2e3ebdSchin #if __CYGWIN__
927*da2e3ebdSchin 
928*da2e3ebdSchin /*
929*da2e3ebdSchin  * cygwin refuses to set st_ctime for some operations
930*da2e3ebdSchin  * this rejects that refusal
931*da2e3ebdSchin  */
932*da2e3ebdSchin 
933*da2e3ebdSchin static void
ctime_now(const char * path)934*da2e3ebdSchin ctime_now(const char* path)
935*da2e3ebdSchin {
936*da2e3ebdSchin 	HANDLE		hp;
937*da2e3ebdSchin 	SYSTEMTIME	st;
938*da2e3ebdSchin 	FILETIME	ct;
939*da2e3ebdSchin 	WIN32_FIND_DATA	ff;
940*da2e3ebdSchin 	struct stat	fs;
941*da2e3ebdSchin 	int		oerrno;
942*da2e3ebdSchin 	char		tmp[MAX_PATH];
943*da2e3ebdSchin 
944*da2e3ebdSchin 	if (_stat(path, &fs) || (fs.st_mode & S_IWUSR) || _chmod(path, (fs.st_mode | S_IWUSR) & S_IPERM))
945*da2e3ebdSchin 		fs.st_mode = 0;
946*da2e3ebdSchin 	cygwin_conv_to_win32_path(path, tmp);
947*da2e3ebdSchin 	hp = CreateFile(tmp, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
948*da2e3ebdSchin 	if (hp && hp != INVALID_HANDLE_VALUE)
949*da2e3ebdSchin 	{
950*da2e3ebdSchin 		GetSystemTime(&st);
951*da2e3ebdSchin 		SystemTimeToFileTime(&st, &ct);
952*da2e3ebdSchin 		SetFileTime(hp, &ct, 0, 0);
953*da2e3ebdSchin 		CloseHandle(hp);
954*da2e3ebdSchin 	}
955*da2e3ebdSchin 	if (fs.st_mode)
956*da2e3ebdSchin 		_chmod(path, fs.st_mode & S_IPERM);
957*da2e3ebdSchin 	errno = oerrno;
958*da2e3ebdSchin }
959*da2e3ebdSchin 
960*da2e3ebdSchin #else
961*da2e3ebdSchin 
962*da2e3ebdSchin #define ctime_now(p)
963*da2e3ebdSchin 
964*da2e3ebdSchin #endif
965*da2e3ebdSchin 
966*da2e3ebdSchin extern int
utimes(const char * path,const struct timeval * ut)967*da2e3ebdSchin utimes(const char* path, const struct timeval* ut)
968*da2e3ebdSchin {
969*da2e3ebdSchin 	int	r;
970*da2e3ebdSchin 	int	oerrno;
971*da2e3ebdSchin 	char	buf[PATH_MAX];
972*da2e3ebdSchin 
973*da2e3ebdSchin 	oerrno = errno;
974*da2e3ebdSchin 	if ((r = _utimes(path, ut)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
975*da2e3ebdSchin 	{
976*da2e3ebdSchin 		errno = oerrno;
977*da2e3ebdSchin 		r = _utimes(path = buf, ut);
978*da2e3ebdSchin 	}
979*da2e3ebdSchin 	if (!r)
980*da2e3ebdSchin 		ctime_now(path);
981*da2e3ebdSchin 	return r;
982*da2e3ebdSchin }
983*da2e3ebdSchin 
984*da2e3ebdSchin extern int
utime(const char * path,const struct utimbuf * ut)985*da2e3ebdSchin utime(const char* path, const struct utimbuf* ut)
986*da2e3ebdSchin {
987*da2e3ebdSchin 	int	r;
988*da2e3ebdSchin 	int	oerrno;
989*da2e3ebdSchin 	char	buf[PATH_MAX];
990*da2e3ebdSchin 
991*da2e3ebdSchin 	oerrno = errno;
992*da2e3ebdSchin 	if ((r = _utime(path, ut)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
993*da2e3ebdSchin 	{
994*da2e3ebdSchin 		errno = oerrno;
995*da2e3ebdSchin 		r = _utime(path = buf, ut);
996*da2e3ebdSchin 	}
997*da2e3ebdSchin 	if (!r)
998*da2e3ebdSchin 		ctime_now(path);
999*da2e3ebdSchin 	return r;
1000*da2e3ebdSchin }
1001*da2e3ebdSchin 
1002*da2e3ebdSchin #endif
1003*da2e3ebdSchin 
1004*da2e3ebdSchin #endif
1005*da2e3ebdSchin 
1006*da2e3ebdSchin /*
1007*da2e3ebdSchin  * some systems (sun) miss a few functions required by their
1008*da2e3ebdSchin  * own bsd-like macros
1009*da2e3ebdSchin  */
1010*da2e3ebdSchin 
1011*da2e3ebdSchin #if !_lib_bzero || defined(bzero)
1012*da2e3ebdSchin 
1013*da2e3ebdSchin #undef	bzero
1014*da2e3ebdSchin 
1015*da2e3ebdSchin void
bzero(void * b,size_t n)1016*da2e3ebdSchin bzero(void* b, size_t n)
1017*da2e3ebdSchin {
1018*da2e3ebdSchin 	memset(b, 0, n);
1019*da2e3ebdSchin }
1020*da2e3ebdSchin 
1021*da2e3ebdSchin #endif
1022*da2e3ebdSchin 
1023*da2e3ebdSchin #if !_lib_getpagesize || defined(getpagesize)
1024*da2e3ebdSchin 
1025*da2e3ebdSchin #ifndef OMITTED
1026*da2e3ebdSchin #define OMITTED	1
1027*da2e3ebdSchin #endif
1028*da2e3ebdSchin 
1029*da2e3ebdSchin #undef	getpagesize
1030*da2e3ebdSchin 
1031*da2e3ebdSchin #ifdef	_SC_PAGESIZE
1032*da2e3ebdSchin #undef	_AST_PAGESIZE
1033*da2e3ebdSchin #define _AST_PAGESIZE	(int)sysconf(_SC_PAGESIZE)
1034*da2e3ebdSchin #else
1035*da2e3ebdSchin #ifndef _AST_PAGESIZE
1036*da2e3ebdSchin #define _AST_PAGESIZE	4096
1037*da2e3ebdSchin #endif
1038*da2e3ebdSchin #endif
1039*da2e3ebdSchin 
1040*da2e3ebdSchin int
getpagesize()1041*da2e3ebdSchin getpagesize()
1042*da2e3ebdSchin {
1043*da2e3ebdSchin 	return _AST_PAGESIZE;
1044*da2e3ebdSchin }
1045*da2e3ebdSchin 
1046*da2e3ebdSchin #endif
1047*da2e3ebdSchin 
1048*da2e3ebdSchin #if __CYGWIN__ && defined(__IMPORT__) && defined(__EXPORT__)
1049*da2e3ebdSchin 
1050*da2e3ebdSchin #ifndef OMITTED
1051*da2e3ebdSchin #define OMITTED	1
1052*da2e3ebdSchin #endif
1053*da2e3ebdSchin 
1054*da2e3ebdSchin /*
1055*da2e3ebdSchin  * a few _imp__FUNCTION symbols are needed to avoid
1056*da2e3ebdSchin  * static link multiple definitions
1057*da2e3ebdSchin  */
1058*da2e3ebdSchin 
1059*da2e3ebdSchin #ifndef strtod
1060*da2e3ebdSchin __EXPORT__ double (*_imp__strtod)(const char*, char**) = strtod;
1061*da2e3ebdSchin #endif
1062*da2e3ebdSchin 
1063*da2e3ebdSchin #endif
1064*da2e3ebdSchin 
1065*da2e3ebdSchin #ifndef OMITTED
1066*da2e3ebdSchin 
1067*da2e3ebdSchin NoN(omitted)
1068*da2e3ebdSchin 
1069*da2e3ebdSchin #endif
1070