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