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