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 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); 83 84 #if defined(__EXPORT__) 85 #define extern __EXPORT__ 86 #endif 87 88 static char* 89 suffix(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 102 static int 103 execrate(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 126 static int 127 magic(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 179 extern int 180 access(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 199 extern unsigned int 200 alarm(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 221 extern int 222 chmod(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 280 extern uid_t _getuid(void); 281 282 static int convertinit; 283 284 /* 285 * convertvars[0] names the list of env var names 286 * convertvars[i] are not converted 287 */ 288 289 static const char* convertvars[] = { "DOSPATHVARS", "PATH" }; 290 291 static int 292 convert(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 319 uid_t 320 getuid(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 350 static pid_t 351 runve(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 550 extern pid_t 551 execve(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 560 extern pid_t 561 spawnve(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 572 extern size_t 573 getpagesize(void) 574 { 575 return 64 * 1024; 576 } 577 578 #endif 579 580 #if _win32_botch_link 581 582 extern int 583 link(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 612 typedef struct Exe_test_s 613 { 614 int test; 615 ino_t ino; 616 char path[PATH_MAX]; 617 } Exe_test_t; 618 619 static Exe_test_t* exe[16]; 620 621 extern int 622 close(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 650 extern ssize_t 651 write(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 660 extern int 661 open(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 704 extern long 705 pathconf(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 716 extern int 717 rename(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 739 extern int 740 stat(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 759 extern int 760 truncate(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 779 extern int 780 unlink(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 933 static void 934 ctime_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 966 extern int 967 utimes(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 984 extern int 985 utime(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 1015 void 1016 bzero(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 1040 int 1041 getpagesize() 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 1067 NoN(omitted) 1068 1069 #endif 1070