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