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 uid_t _getuid(void); 73extern int _link(const char*, const char*); 74extern int _open(const char*, int, ...); 75extern long _pathconf(const char*, int); 76extern ssize_t _read(int, void*, size_t); 77extern int _rename(const char*, const char*); 78extern pid_t _spawnve(int, const char*, char* const*, char* const*); 79extern int _stat(const char*, struct stat*); 80extern int _unlink(const char*); 81extern int _utime(const char*, const struct utimbuf*); 82extern int _utimes(const char*, const struct timeval*); 83extern 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 173static char* 174suffix(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 187static int 188execrate(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 211static int 212magic(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 264extern int 265access(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 284extern unsigned int 285alarm(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 306extern int 307chmod(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 365static int convertinit; 366 367/* 368 * convertvars[0] names the list of env var names 369 * convertvars[i] are not converted 370 */ 371 372static const char* convertvars[] = { "DOSPATHVARS", "PATH" }; 373 374static int 375convert(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 402uid_t 403getuid(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 433static pid_t 434runve(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 633extern pid_t 634execve(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 643extern pid_t 644spawnve(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 655extern size_t 656getpagesize(void) 657{ 658 return 64 * 1024; 659} 660 661#endif 662 663#if _win32_botch_link 664 665extern int 666link(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 695typedef struct Exe_test_s 696{ 697 int test; 698 ino_t ino; 699 char path[PATH_MAX]; 700} Exe_test_t; 701 702static Exe_test_t* exe[16]; 703 704extern int 705close(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 733extern ssize_t 734write(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 743extern int 744open(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 787extern long 788pathconf(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 799extern int 800rename(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 822extern int 823stat(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 842extern int 843truncate(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 862extern int 863unlink(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 1016static void 1017ctime_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 1049extern int 1050utimes(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 1067extern int 1068utime(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 1098void 1099bzero(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 1123int 1124getpagesize() 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 1150NoN(omitted) 1151 1152#endif 1153