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