1 #pragma prototyped noticed
4 * workarounds to bring the native interface close to posix and x/open
7 #if defined(__STDPP__directive) && defined(__STDPP__hide)
8 __STDPP__directive pragma pp
:hide utime utimes
10 #define utime ______utime
11 #define utimes ______utimes
18 #include "FEATURE/omitted"
30 #include <ast_windows.h>
31 #if _win32_botch_execve || _lib_spawn_mode
36 #if defined(__STDPP__directive) && defined(__STDPP__hide)
37 __STDPP__directive pragma pp
:nohide utime utimes
44 #define MAX_PATH PATH_MAX
48 * these workarounds assume each system call foo() has a _foo() entry
49 * which is true for __CYGWIN__ and __EMX__ (both gnu based)
51 * the workarounds handle:
53 * (1) .exe suffix inconsistencies
54 * (2) /bin/sh reference in execve() and spawnve()
55 * (3) bogus getpagesize() return values
56 * (4) a fork() bug that screws up shell fork()+script
58 * NOTE: Not all workarounds can be handled by unix syscall intercepts.
59 * In particular, { ksh nmake } have workarounds for case-ignorant
60 * filesystems and { libast } has workarounds for win32 locale info.
67 extern int _access(const char*, int);
68 extern unsigned int _alarm(unsigned int);
69 extern int _chmod(const char*, mode_t
);
70 extern int _close(int);
71 extern pid_t
_execve(const char*, char* const*, char* const*);
72 extern int _link(const char*, const char*);
73 extern int _open(const char*, int, ...);
74 extern long _pathconf(const char*, int);
75 extern ssize_t
_read(int, void*, size_t);
76 extern int _rename(const char*, const char*);
77 extern pid_t
_spawnve(int, const char*, char* const*, char* const*);
78 extern int _stat(const char*, struct stat
*);
79 extern int _unlink(const char*);
80 extern int _utime(const char*, const struct utimbuf
*);
81 extern int _utimes(const char*, const struct timeval
*);
82 extern ssize_t
_write(int, const void*, size_t);
84 #if defined(__EXPORT__)
85 #define extern __EXPORT__
89 suffix(register const char* path
)
91 register const char* s
= path
+ strlen(path
);
95 if ((c
= *--s
) == '.')
97 else if (c
== '/' || c
== '\\')
103 execrate(const char* path
, char* buf
, int size
, int physical
)
112 if (physical
|| strlen(path
) >= size
|| !(s
= pathcanon(strcpy(buf
, path
), PATH_PHYSICAL
|PATH_DOTDOT
|PATH_EXISTS
)))
113 snprintf(buf
, size
, "%s.exe", path
);
114 else if (!suffix(buf
) && ((buf
+ size
) - s
) >= 4)
121 * return 0 if path is magic, -1 otherwise
122 * ux!=0 set to 1 if path is unix executable
123 * ux!=0 also retains errno for -1 return
127 magic(const char* path
, int* ux
)
135 unsigned char buf
[512];
137 unsigned char buf
[2];
141 if ((fd
= _open(path
, O_RDONLY
, 0)) >= 0)
149 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;
155 else if (m
> 61 && (n
= buf
[60] | (buf
[61]<<8) + 92) < (m
- 1))
156 *ux
= (buf
[n
] | (buf
[n
+1]<<8)) == 3;
163 else if (errno
== ENOENT
)
177 #if _win32_botch_access
180 access(const char* path
, int op
)
187 if ((r
= _access(path
, op
)) && errno
== ENOENT
&& execrate(path
, buf
, sizeof(buf
), 0))
190 r
= _access(buf
, op
);
197 #if _win32_botch_alarm
200 alarm(unsigned int s
)
205 static unsigned int a
;
207 n
= (unsigned int)time(NiL
);
219 #if _win32_botch_chmod
222 chmod(const char* path
, mode_t mode
)
228 if ((r
= _chmod(path
, mode
)) && errno
== ENOENT
&& execrate(path
, buf
, sizeof(buf
), 0))
231 return _chmod(buf
, mode
);
233 if (!(r
= _chmod(path
, mode
)) &&
234 (mode
& (S_IXUSR
|S_IXGRP
|S_IXOTH
)) &&
236 (strlen(path
) + 4) < sizeof(buf
))
239 if (!magic(path
, NiL
))
241 snprintf(buf
, sizeof(buf
), "%s.exe", path
);
251 #if _win32_botch_execve || _lib_spawn_mode
256 * can anyone get const prototype args straight?
259 #define execve ______execve
260 #define spawnve ______spawnve
272 * this intercept converts dos env vars to unix
273 * we'd rather intercept main but can't twist cc to do it
274 * getuid() gets ksh to do the right thing and
275 * that's our main concern
277 * DOSPATHVARS='a b c' convert { a b c }
280 extern uid_t
_getuid(void);
282 static int convertinit
;
285 * convertvars[0] names the list of env var names
286 * convertvars[i] are not converted
289 static const char* convertvars
[] = { "DOSPATHVARS", "PATH" };
292 convert(register const char* d
, const char* s
)
294 register const char* t
;
295 register const char* v
;
298 for (i
= 0; i
< elementsof(convertvars
); i
++)
300 for (v
= convertvars
[i
], t
= s
; *t
&& *t
== *v
; t
++, v
++);
301 if (*t
== '=' && *v
== 0)
306 while (*d
== ' ' || *d
== '\t')
310 for (t
= s
; *t
&& *t
== *d
; d
++, t
++);
311 if (*t
== '=' && (*d
== ' ' || *d
== '\t' || *d
== 0))
313 while (*d
&& *d
!= ' ' && *d
!= '\t')
329 if (!convertinit
++ && (d
= getenv(convertvars
[0])))
330 for (e
= environ
; s
= *e
; e
++)
331 if ((n
= convert(d
, s
)) && (m
= cygwin_win32_to_posix_path_list_buf_size(s
+ n
)) > 0)
333 if (!(t
= malloc(n
+ m
+ 1)))
337 cygwin_win32_to_posix_path_list(s
+ n
, t
+ n
);
345 #define _P_OVERLAY (-1)
351 runve(int mode
, const char* path
, char* const* argv
, char* const* envv
)
363 #if defined(_P_DETACH) && defined(_P_NOWAIT)
379 #if defined(_P_DETACH) && defined(_P_NOWAIT)
380 if (mode
== _P_DETACH
)
383 * 2004-02-29 cygwin _P_DETACH is useless:
384 * spawn*() returns 0 instead of the spawned pid
385 * spawned { pgid sid } are the same as the parent
395 envv
= (char* const*)environ
;
400 trace
= (s
= getenv("_AST_exec_trace")) ? *s
: 'n';
402 if (execrate(path
, buf
, sizeof(buf
), 0))
404 if (!_stat(buf
, &st
))
405 path
= (const char*)buf
;
409 if (path
!= (const char*)buf
&& _stat(path
, &st
))
411 if (!S_ISREG(st
.st_mode
) || !(st
.st_mode
& (S_IXUSR
|S_IXGRP
|S_IXOTH
)))
416 if (magic(path
, &ux
))
418 #if _CYGWIN_fork_works
425 if (!(v
= (char**)malloc((p
- (char**)argv
+ 2) * sizeof(char*))))
434 path
= (const char*)pathshell();
437 while (*p
++ = (char*)*argv
++);
438 argv
= (char* const*)v
;
443 * the win32 dll search order is
444 * (1) the directory of path
446 * (3) /c/(WINNT|WINDOWS)/system32 /c/(WINNT|WINDOWS)
447 * (4) the directories on $PATH
448 * there are no cygwin dlls in (3), so if (1) and (2) fail
449 * to produce the required dlls its up to (4)
451 * the standard allows PATH to be anything once the path
452 * to an executable is determined; this code ensures that PATH
453 * contains /bin so that at least the cygwin dll, required
454 * by all cygwin executables, will be found
457 if (p
= (char**)envv
)
461 if (strneq(s
, "PATH=", 5))
466 s
= pathcat(tmp
, s
, ':', NiL
, "");
467 if (streq(tmp
, "/usr/bin/") || streq(tmp
, "/bin/"))
476 snprintf(tmp
, sizeof(tmp
), "%s:/bin", *(p
- 1));
483 n
= p
- (char**)envv
+ 1;
485 if (v
= (char**)malloc(n
* sizeof(char*)))
488 envv
= (char* const*)v
;
489 *v
++ = strcpy(tmp
, "PATH=/bin");
494 if (!ux
&& (d
= getenv(convertvars
[0])))
495 for (p
= (char**)envv
; s
= *p
; p
++)
496 if ((n
= convert(d
, s
)) && (m
= cygwin_posix_to_win32_path_list_buf_size(s
+ n
)) > 0)
498 if (!(t
= malloc(n
+ m
+ 1)))
502 cygwin_posix_to_win32_path_list(s
+ n
, t
+ n
);
508 if (trace
== 'a' || trace
== 'e')
510 sfprintf(sfstderr
, "%s %s [", mode
== _P_OVERLAY
? "_execve" : "_spawnve", path
);
511 for (n
= 0; argv
[n
]; n
++)
512 sfprintf(sfstderr
, " '%s'", argv
[n
]);
515 sfprintf(sfstderr
, " ] [");
516 for (n
= 0; envv
[n
]; n
++)
517 sfprintf(sfstderr
, " '%s'", envv
[n
]);
519 sfprintf(sfstderr
, " ]\n");
524 if (mode
!= _P_OVERLAY
)
526 pid
= _spawnve(mode
, path
, argv
, envv
);
527 #if defined(_P_DETACH) && defined(_P_NOWAIT)
535 #if defined(_P_DETACH) && defined(_P_NOWAIT)
539 pid
= _execve(path
, argv
, envv
);
546 #if _win32_botch_execve
549 execve(const char* path
, char* const* argv
, char* const* envv
)
551 return runve(_P_OVERLAY
, path
, argv
, envv
);
559 spawnve(int mode
, const char* path
, char* const* argv
, char* const* envv
)
561 return runve(mode
, path
, argv
, envv
);
568 #if _win32_botch_getpagesize
578 #if _win32_botch_link
581 link(const char* fp
, const char* tp
)
589 if ((r
= _link(fp
, tp
)) && errno
== ENOENT
&& execrate(fp
, fb
, sizeof(fb
), 1))
591 if (execrate(tp
, tb
, sizeof(tb
), 1))
601 #if _win32_botch_open || _win32_botch_copy
603 #if _win32_botch_copy
606 * this should intercept the important cases
607 * dup*() and exec*() fd's will not be intercepted
610 typedef struct Exe_test_s
617 static Exe_test_t
* exe
[16];
627 if (fd
>= 0 && fd
< elementsof(exe
) && exe
[fd
])
631 if (r
> 0 && !fstat(fd
, &st
) && st
.st_ino
== exe
[fd
]->ino
)
636 if (!stat(exe
[fd
]->path
, &st
) && st
.st_ino
== exe
[fd
]->ino
)
638 snprintf(buf
, sizeof(buf
), "%s.exe", exe
[fd
]->path
);
639 _rename(exe
[fd
]->path
, buf
);
649 write(int fd
, const void* buf
, size_t n
)
651 if (fd
>= 0 && fd
< elementsof(exe
) && exe
[fd
] && exe
[fd
]->test
< 0)
652 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
);
653 return _write(fd
, buf
, n
);
659 open(const char* path
, int flags
, ...)
665 #if _win32_botch_copy
671 mode
= (flags
& O_CREAT
) ? va_arg(ap
, int) : 0;
673 fd
= _open(path
, flags
, mode
);
674 #if _win32_botch_open
675 if (fd
< 0 && errno
== ENOENT
&& execrate(path
, buf
, sizeof(buf
), 0))
678 fd
= _open(buf
, flags
, mode
);
681 #if _win32_botch_copy
682 if (fd
>= 0 && fd
< elementsof(exe
) && strlen(path
) < PATH_MAX
&&
683 (flags
& (O_CREAT
|O_TRUNC
)) == (O_CREAT
|O_TRUNC
) && (mode
& 0111))
685 if (!suffix(path
) && !fstat(fd
, &st
) && (exe
[fd
] || (exe
[fd
] = (Exe_test_t
*)malloc(sizeof(Exe_test_t
)))))
688 exe
[fd
]->ino
= st
.st_ino
;
689 strcpy(exe
[fd
]->path
, path
);
700 #if _win32_botch_pathconf
703 pathconf(const char* path
, int op
)
705 if (_access(path
, F_OK
))
707 return _pathconf(path
, op
);
712 #if _win32_botch_rename
715 rename(const char* fp
, const char* tp
)
723 if ((r
= _rename(fp
, tp
)) && errno
== ENOENT
&& execrate(fp
, fb
, sizeof(fb
), 1))
725 if (execrate(tp
, tb
, sizeof(tb
), 1))
735 #if _win32_botch_stat
738 stat(const char* path
, struct stat
* st
)
745 if ((r
= _stat(path
, st
)) && errno
== ENOENT
&& execrate(path
, buf
, sizeof(buf
), 0))
755 #if _win32_botch_truncate
758 truncate(const char* path
, off_t offset
)
765 if ((r
= _truncate(path
, offset
)) && errno
== ENOENT
&& execrate(path
, buf
, sizeof(buf
), 0))
768 r
= _truncate(buf
, offset
);
775 #if _win32_botch_unlink
778 unlink(const char* path
)
790 #define DELETED_DIR_1 7
791 #define DELETED_DIR_2 16
793 static char deleted
[] = "%c:\\temp\\.deleted\\%08x.%03x";
795 static int count
= 0;
799 DWORD fattr
= FILE_ATTRIBUTE_NORMAL
|FILE_FLAG_DELETE_ON_CLOSE
;
800 DWORD share
= FILE_SHARE_DELETE
;
806 if (lstat(path
, &st
) || !S_ISREG(st
.st_mode
))
808 cygwin_conv_to_full_win32_path(path
, nat
);
809 if (!strncasecmp(nat
+ 1, ":\\temp\\", 7))
812 path
= (const char*)nat
;
815 hp
= CreateFile(path
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
|FILE_FLAG_DELETE_ON_CLOSE
, NULL
);
816 if (hp
!= INVALID_HANDLE_VALUE
)
822 if (GetLastError() != ERROR_FILE_NOT_FOUND
)
824 if (path
== (const char*)buf
|| !execrate(path
, buf
, sizeof(buf
), 1))
829 path
= (const char*)buf
;
832 if (_access(path
, 0))
833 #if _win32_botch_access
835 if (errno
!= ENOENT
|| !execrate(path
, buf
, sizeof(buf
), 1) || _access(buf
, 0))
837 path
= (const char*)buf
;
846 * rename to a `deleted' path just in case the file is open
847 * otherwise directory readers may choke on phantom entries
850 base
= ((getuid() & 0xffff) << 16) | (time(NiL
) & 0xffff);
851 suffix
= (getpid() & 0xfff) + count
++;
852 snprintf(tmp
, sizeof(tmp
), deleted
, drive
, base
, suffix
);
853 if (!_rename(path
, tmp
))
855 path
= (const char*)tmp
;
858 if (errno
!= ENOTDIR
&& errno
!= ENOENT
)
860 tmp
[DELETED_DIR_2
] = 0;
864 tmp
[DELETED_DIR_1
] = 0;
865 if (_access(tmp
, 0) && _mkdir(tmp
, S_IRWXU
|S_IRWXG
|S_IRWXO
))
870 tmp
[DELETED_DIR_1
] = '\\';
871 r
= _mkdir(tmp
, S_IRWXU
|S_IRWXG
|S_IRWXO
);
877 tmp
[DELETED_DIR_2
] = '\\';
878 if (!errno
&& !_rename(path
, tmp
))
880 path
= (const char*)tmp
;
886 #if !_win32_botch_access
887 if (execrate(path
, buf
, sizeof(buf
), 1) && !_rename(buf
, tmp
))
888 path
= (const char*)tmp
;
896 snprintf(tmp
, sizeof(tmp
), deleted
, drive
, base
, suffix
);
897 if (!_rename(path
, tmp
))
899 path
= (const char*)tmp
;
902 if (++suffix
> 0xfff)
904 } while (suffix
!= stop
);
907 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
);
908 if (hp
!= INVALID_HANDLE_VALUE
)
917 return _unlink(path
);
922 #if _win32_botch_utime
927 * cygwin refuses to set st_ctime for some operations
928 * this rejects that refusal
932 ctime_now(const char* path
)
942 if (_stat(path
, &fs
) || (fs
.st_mode
& S_IWUSR
) || _chmod(path
, (fs
.st_mode
| S_IWUSR
) & S_IPERM
))
944 cygwin_conv_to_win32_path(path
, tmp
);
945 hp
= CreateFile(tmp
, GENERIC_WRITE
, FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
946 if (hp
&& hp
!= INVALID_HANDLE_VALUE
)
949 SystemTimeToFileTime(&st
, &ct
);
950 SetFileTime(hp
, &ct
, 0, 0);
954 _chmod(path
, fs
.st_mode
& S_IPERM
);
965 utimes(const char* path
, const struct timeval
* ut
)
972 if ((r
= _utimes(path
, ut
)) && errno
== ENOENT
&& execrate(path
, buf
, sizeof(buf
), 0))
975 r
= _utimes(path
= buf
, ut
);
983 utime(const char* path
, const struct utimbuf
* ut
)
990 if ((r
= _utime(path
, ut
)) && errno
== ENOENT
&& execrate(path
, buf
, sizeof(buf
), 0))
993 r
= _utime(path
= buf
, ut
);
1005 * some systems (sun) miss a few functions required by their
1006 * own bsd-like macros
1009 #if !_lib_bzero || defined(bzero)
1014 bzero(void* b
, size_t n
)
1021 #if !_lib_getpagesize || defined(getpagesize)
1030 #undef _AST_PAGESIZE
1031 #define _AST_PAGESIZE (int)sysconf(_SC_PAGESIZE)
1033 #ifndef _AST_PAGESIZE
1034 #define _AST_PAGESIZE 4096
1041 return _AST_PAGESIZE
;
1046 #if __CYGWIN__ && defined(__IMPORT__) && defined(__EXPORT__)
1053 * a few _imp__FUNCTION symbols are needed to avoid
1054 * static link multiple definitions
1058 __EXPORT__
double (*_imp__strtod
)(const char*, char**) = strtod
;