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