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