github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/cmd/dist/unix.c (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // These #ifdefs are being used as a substitute for 6 // build configuration, so that on any system, this 7 // tool can be built with the local equivalent of 8 // cc *.c 9 // 10 #ifndef WIN32 11 #ifndef PLAN9 12 13 #include "a.h" 14 #include <unistd.h> 15 #include <dirent.h> 16 #include <sys/stat.h> 17 #include <sys/wait.h> 18 #include <sys/param.h> 19 #include <sys/utsname.h> 20 #include <fcntl.h> 21 #include <string.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <errno.h> 25 #include <stdarg.h> 26 #include <setjmp.h> 27 #include <signal.h> 28 29 // bprintf replaces the buffer with the result of the printf formatting 30 // and returns a pointer to the NUL-terminated buffer contents. 31 char* 32 bprintf(Buf *b, char *fmt, ...) 33 { 34 va_list arg; 35 char buf[4096]; 36 37 breset(b); 38 va_start(arg, fmt); 39 vsnprintf(buf, sizeof buf, fmt, arg); 40 va_end(arg); 41 bwritestr(b, buf); 42 return bstr(b); 43 } 44 45 // bpathf is the same as bprintf (on windows it turns / into \ after the printf). 46 // It returns a pointer to the NUL-terminated buffer contents. 47 char* 48 bpathf(Buf *b, char *fmt, ...) 49 { 50 va_list arg; 51 char buf[4096]; 52 53 breset(b); 54 va_start(arg, fmt); 55 vsnprintf(buf, sizeof buf, fmt, arg); 56 va_end(arg); 57 bwritestr(b, buf); 58 return bstr(b); 59 } 60 61 // bwritef is like bprintf but does not reset the buffer 62 // and does not return the NUL-terminated string. 63 void 64 bwritef(Buf *b, char *fmt, ...) 65 { 66 va_list arg; 67 char buf[4096]; 68 69 va_start(arg, fmt); 70 vsnprintf(buf, sizeof buf, fmt, arg); 71 va_end(arg); 72 bwritestr(b, buf); 73 } 74 75 // breadfrom appends to b all the data that can be read from fd. 76 static void 77 breadfrom(Buf *b, int fd) 78 { 79 int n; 80 81 for(;;) { 82 bgrow(b, 4096); 83 n = read(fd, b->p+b->len, 4096); 84 if(n < 0) 85 fatal("read: %s", strerror(errno)); 86 if(n == 0) 87 break; 88 b->len += n; 89 } 90 } 91 92 // xgetenv replaces b with the value of the named environment variable. 93 void 94 xgetenv(Buf *b, char *name) 95 { 96 char *p; 97 98 breset(b); 99 p = getenv(name); 100 if(p != NULL) 101 bwritestr(b, p); 102 } 103 104 static void genrun(Buf *b, char *dir, int mode, Vec *argv, int bg); 105 106 // run runs the command named by cmd. 107 // If b is not nil, run replaces b with the output of the command. 108 // If dir is not nil, run runs the command in that directory. 109 // If mode is CheckExit, run calls fatal if the command is not successful. 110 void 111 run(Buf *b, char *dir, int mode, char *cmd, ...) 112 { 113 va_list arg; 114 Vec argv; 115 char *p; 116 117 vinit(&argv); 118 vadd(&argv, cmd); 119 va_start(arg, cmd); 120 while((p = va_arg(arg, char*)) != nil) 121 vadd(&argv, p); 122 va_end(arg); 123 124 runv(b, dir, mode, &argv); 125 126 vfree(&argv); 127 } 128 129 // runv is like run but takes a vector. 130 void 131 runv(Buf *b, char *dir, int mode, Vec *argv) 132 { 133 genrun(b, dir, mode, argv, 1); 134 } 135 136 // bgrunv is like run but runs the command in the background. 137 // bgwait waits for pending bgrunv to finish. 138 void 139 bgrunv(char *dir, int mode, Vec *argv) 140 { 141 genrun(nil, dir, mode, argv, 0); 142 } 143 144 #define MAXBG 4 /* maximum number of jobs to run at once */ 145 146 static struct { 147 int pid; 148 int mode; 149 char *cmd; 150 Buf *b; 151 } bg[MAXBG]; 152 static int nbg; 153 static int maxnbg = nelem(bg); 154 155 static void bgwait1(void); 156 157 // genrun is the generic run implementation. 158 static void 159 genrun(Buf *b, char *dir, int mode, Vec *argv, int wait) 160 { 161 int i, p[2], pid; 162 Buf cmd; 163 char *q; 164 165 while(nbg >= maxnbg) 166 bgwait1(); 167 168 // Generate a copy of the command to show in a log. 169 // Substitute $WORK for the work directory. 170 binit(&cmd); 171 for(i=0; i<argv->len; i++) { 172 if(i > 0) 173 bwritestr(&cmd, " "); 174 q = argv->p[i]; 175 if(workdir != nil && hasprefix(q, workdir)) { 176 bwritestr(&cmd, "$WORK"); 177 q += strlen(workdir); 178 } 179 bwritestr(&cmd, q); 180 } 181 if(vflag > 1) 182 errprintf("%s\n", bstr(&cmd)); 183 184 if(b != nil) { 185 breset(b); 186 if(pipe(p) < 0) 187 fatal("pipe: %s", strerror(errno)); 188 } 189 190 switch(pid = fork()) { 191 case -1: 192 fatal("fork: %s", strerror(errno)); 193 case 0: 194 if(b != nil) { 195 close(0); 196 close(p[0]); 197 dup2(p[1], 1); 198 dup2(p[1], 2); 199 if(p[1] > 2) 200 close(p[1]); 201 } 202 if(dir != nil) { 203 if(chdir(dir) < 0) { 204 fprintf(stderr, "chdir %s: %s\n", dir, strerror(errno)); 205 _exit(1); 206 } 207 } 208 vadd(argv, nil); 209 execvp(argv->p[0], argv->p); 210 fprintf(stderr, "%s\n", bstr(&cmd)); 211 fprintf(stderr, "exec %s: %s\n", argv->p[0], strerror(errno)); 212 _exit(1); 213 } 214 if(b != nil) { 215 close(p[1]); 216 breadfrom(b, p[0]); 217 close(p[0]); 218 } 219 220 if(nbg < 0) 221 fatal("bad bookkeeping"); 222 bg[nbg].pid = pid; 223 bg[nbg].mode = mode; 224 bg[nbg].cmd = btake(&cmd); 225 bg[nbg].b = b; 226 nbg++; 227 228 if(wait) 229 bgwait(); 230 231 bfree(&cmd); 232 } 233 234 // bgwait1 waits for a single background job. 235 static void 236 bgwait1(void) 237 { 238 int i, pid, status, mode; 239 char *cmd; 240 Buf *b; 241 242 errno = 0; 243 while((pid = wait(&status)) < 0) { 244 if(errno != EINTR) 245 fatal("waitpid: %s", strerror(errno)); 246 } 247 for(i=0; i<nbg; i++) 248 if(bg[i].pid == pid) 249 goto ok; 250 fatal("waitpid: unexpected pid"); 251 252 ok: 253 cmd = bg[i].cmd; 254 mode = bg[i].mode; 255 bg[i].pid = 0; 256 b = bg[i].b; 257 bg[i].b = nil; 258 bg[i] = bg[--nbg]; 259 260 if(mode == CheckExit && (!WIFEXITED(status) || WEXITSTATUS(status) != 0)) { 261 if(b != nil) 262 xprintf("%s\n", bstr(b)); 263 fatal("FAILED: %s", cmd); 264 } 265 xfree(cmd); 266 } 267 268 // bgwait waits for all the background jobs. 269 void 270 bgwait(void) 271 { 272 while(nbg > 0) 273 bgwait1(); 274 } 275 276 // xgetwd replaces b with the current directory. 277 void 278 xgetwd(Buf *b) 279 { 280 char buf[MAXPATHLEN]; 281 282 breset(b); 283 if(getcwd(buf, MAXPATHLEN) == nil) 284 fatal("getcwd: %s", strerror(errno)); 285 bwritestr(b, buf); 286 } 287 288 // xrealwd replaces b with the 'real' name for the given path. 289 // real is defined as what getcwd returns in that directory. 290 void 291 xrealwd(Buf *b, char *path) 292 { 293 int fd; 294 295 fd = open(".", 0); 296 if(fd < 0) 297 fatal("open .: %s", strerror(errno)); 298 if(chdir(path) < 0) 299 fatal("chdir %s: %s", path, strerror(errno)); 300 xgetwd(b); 301 if(fchdir(fd) < 0) 302 fatal("fchdir: %s", strerror(errno)); 303 close(fd); 304 } 305 306 // isdir reports whether p names an existing directory. 307 bool 308 isdir(char *p) 309 { 310 struct stat st; 311 312 return stat(p, &st) >= 0 && S_ISDIR(st.st_mode); 313 } 314 315 // isfile reports whether p names an existing file. 316 bool 317 isfile(char *p) 318 { 319 struct stat st; 320 321 return stat(p, &st) >= 0 && S_ISREG(st.st_mode); 322 } 323 324 // mtime returns the modification time of the file p. 325 Time 326 mtime(char *p) 327 { 328 struct stat st; 329 330 if(stat(p, &st) < 0) 331 return 0; 332 return (Time)st.st_mtime*1000000000LL; 333 } 334 335 // isabs reports whether p is an absolute path. 336 bool 337 isabs(char *p) 338 { 339 return hasprefix(p, "/"); 340 } 341 342 // readfile replaces b with the content of the named file. 343 void 344 readfile(Buf *b, char *file) 345 { 346 int fd; 347 348 breset(b); 349 fd = open(file, 0); 350 if(fd < 0) 351 fatal("open %s: %s", file, strerror(errno)); 352 breadfrom(b, fd); 353 close(fd); 354 } 355 356 // writefile writes b to the named file, creating it if needed. if 357 // exec is non-zero, marks the file as executable. 358 void 359 writefile(Buf *b, char *file, int exec) 360 { 361 int fd; 362 363 fd = creat(file, 0666); 364 if(fd < 0) 365 fatal("create %s: %s", file, strerror(errno)); 366 if(write(fd, b->p, b->len) != b->len) 367 fatal("short write: %s", strerror(errno)); 368 if(exec) 369 fchmod(fd, 0755); 370 close(fd); 371 } 372 373 // xmkdir creates the directory p. 374 void 375 xmkdir(char *p) 376 { 377 if(mkdir(p, 0777) < 0) 378 fatal("mkdir %s: %s", p, strerror(errno)); 379 } 380 381 // xmkdirall creates the directory p and its parents, as needed. 382 void 383 xmkdirall(char *p) 384 { 385 char *q; 386 387 if(isdir(p)) 388 return; 389 q = strrchr(p, '/'); 390 if(q != nil) { 391 *q = '\0'; 392 xmkdirall(p); 393 *q = '/'; 394 } 395 xmkdir(p); 396 } 397 398 // xremove removes the file p. 399 void 400 xremove(char *p) 401 { 402 if(vflag > 2) 403 errprintf("rm %s\n", p); 404 unlink(p); 405 } 406 407 // xremoveall removes the file or directory tree rooted at p. 408 void 409 xremoveall(char *p) 410 { 411 int i; 412 Buf b; 413 Vec dir; 414 415 binit(&b); 416 vinit(&dir); 417 418 if(isdir(p)) { 419 xreaddir(&dir, p); 420 for(i=0; i<dir.len; i++) { 421 bprintf(&b, "%s/%s", p, dir.p[i]); 422 xremoveall(bstr(&b)); 423 } 424 if(vflag > 2) 425 errprintf("rm %s\n", p); 426 rmdir(p); 427 } else { 428 if(vflag > 2) 429 errprintf("rm %s\n", p); 430 unlink(p); 431 } 432 433 bfree(&b); 434 vfree(&dir); 435 } 436 437 // xreaddir replaces dst with a list of the names of the files in dir. 438 // The names are relative to dir; they are not full paths. 439 void 440 xreaddir(Vec *dst, char *dir) 441 { 442 DIR *d; 443 struct dirent *dp; 444 445 vreset(dst); 446 d = opendir(dir); 447 if(d == nil) 448 fatal("opendir %s: %s", dir, strerror(errno)); 449 while((dp = readdir(d)) != nil) { 450 if(streq(dp->d_name, ".") || streq(dp->d_name, "..")) 451 continue; 452 vadd(dst, dp->d_name); 453 } 454 closedir(d); 455 } 456 457 // xworkdir creates a new temporary directory to hold object files 458 // and returns the name of that directory. 459 char* 460 xworkdir(void) 461 { 462 Buf b; 463 char *p; 464 465 binit(&b); 466 467 xgetenv(&b, "TMPDIR"); 468 if(b.len == 0) 469 bwritestr(&b, "/var/tmp"); 470 if(b.p[b.len-1] != '/') 471 bwrite(&b, "/", 1); 472 bwritestr(&b, "go-cbuild-XXXXXX"); 473 p = bstr(&b); 474 if(mkdtemp(p) == nil) 475 fatal("mkdtemp(%s): %s", p, strerror(errno)); 476 p = btake(&b); 477 478 bfree(&b); 479 480 return p; 481 } 482 483 // fatal prints an error message to standard error and exits. 484 void 485 fatal(char *msg, ...) 486 { 487 va_list arg; 488 489 fflush(stdout); 490 fprintf(stderr, "go tool dist: "); 491 va_start(arg, msg); 492 vfprintf(stderr, msg, arg); 493 va_end(arg); 494 fprintf(stderr, "\n"); 495 496 bgwait(); 497 exit(1); 498 } 499 500 // xmalloc returns a newly allocated zeroed block of n bytes of memory. 501 // It calls fatal if it runs out of memory. 502 void* 503 xmalloc(int n) 504 { 505 void *p; 506 507 p = malloc(n); 508 if(p == nil) 509 fatal("out of memory"); 510 memset(p, 0, n); 511 return p; 512 } 513 514 // xstrdup returns a newly allocated copy of p. 515 // It calls fatal if it runs out of memory. 516 char* 517 xstrdup(char *p) 518 { 519 p = strdup(p); 520 if(p == nil) 521 fatal("out of memory"); 522 return p; 523 } 524 525 // xrealloc grows the allocation p to n bytes and 526 // returns the new (possibly moved) pointer. 527 // It calls fatal if it runs out of memory. 528 void* 529 xrealloc(void *p, int n) 530 { 531 p = realloc(p, n); 532 if(p == nil) 533 fatal("out of memory"); 534 return p; 535 } 536 537 // xfree frees the result returned by xmalloc, xstrdup, or xrealloc. 538 void 539 xfree(void *p) 540 { 541 free(p); 542 } 543 544 // hassuffix reports whether p ends with suffix. 545 bool 546 hassuffix(char *p, char *suffix) 547 { 548 int np, ns; 549 550 np = strlen(p); 551 ns = strlen(suffix); 552 return np >= ns && streq(p+np-ns, suffix); 553 } 554 555 // hasprefix reports whether p begins with prefix. 556 bool 557 hasprefix(char *p, char *prefix) 558 { 559 return strncmp(p, prefix, strlen(prefix)) == 0; 560 } 561 562 // contains reports whether sep appears in p. 563 bool 564 contains(char *p, char *sep) 565 { 566 return strstr(p, sep) != nil; 567 } 568 569 // streq reports whether p and q are the same string. 570 bool 571 streq(char *p, char *q) 572 { 573 return strcmp(p, q) == 0; 574 } 575 576 // lastelem returns the final path element in p. 577 char* 578 lastelem(char *p) 579 { 580 char *out; 581 582 out = p; 583 for(; *p; p++) 584 if(*p == '/') 585 out = p+1; 586 return out; 587 } 588 589 // xmemmove copies n bytes from src to dst. 590 void 591 xmemmove(void *dst, void *src, int n) 592 { 593 memmove(dst, src, n); 594 } 595 596 // xmemcmp compares the n-byte regions starting at a and at b. 597 int 598 xmemcmp(void *a, void *b, int n) 599 { 600 return memcmp(a, b, n); 601 } 602 603 // xstrlen returns the length of the NUL-terminated string at p. 604 int 605 xstrlen(char *p) 606 { 607 return strlen(p); 608 } 609 610 // xexit exits the process with return code n. 611 void 612 xexit(int n) 613 { 614 exit(n); 615 } 616 617 // xatexit schedules the exit-handler f to be run when the program exits. 618 void 619 xatexit(void (*f)(void)) 620 { 621 atexit(f); 622 } 623 624 // xprintf prints a message to standard output. 625 void 626 xprintf(char *fmt, ...) 627 { 628 va_list arg; 629 630 va_start(arg, fmt); 631 vprintf(fmt, arg); 632 va_end(arg); 633 } 634 635 // errprintf prints a message to standard output. 636 void 637 errprintf(char *fmt, ...) 638 { 639 va_list arg; 640 641 va_start(arg, fmt); 642 vfprintf(stderr, fmt, arg); 643 va_end(arg); 644 } 645 646 // xsetenv sets the environment variable $name to the given value. 647 void 648 xsetenv(char *name, char *value) 649 { 650 setenv(name, value, 1); 651 } 652 653 // main takes care of OS-specific startup and dispatches to xmain. 654 int 655 main(int argc, char **argv) 656 { 657 Buf b; 658 int osx; 659 struct utsname u; 660 661 setvbuf(stdout, nil, _IOLBF, 0); 662 setvbuf(stderr, nil, _IOLBF, 0); 663 664 setenv("TERM", "dumb", 1); // disable escape codes in clang errors 665 666 binit(&b); 667 668 slash = "/"; 669 670 #if defined(__APPLE__) 671 gohostos = "darwin"; 672 // Even on 64-bit platform, darwin uname -m prints i386. 673 run(&b, nil, 0, "sysctl", "machdep.cpu.extfeatures", nil); 674 if(contains(bstr(&b), "EM64T")) 675 gohostarch = "amd64"; 676 #elif defined(__linux__) 677 gohostos = "linux"; 678 #elif defined(__DragonFly__) 679 gohostos = "dragonfly"; 680 #elif defined(__FreeBSD__) 681 gohostos = "freebsd"; 682 #elif defined(__FreeBSD_kernel__) 683 // detect debian/kFreeBSD. 684 // http://wiki.debian.org/Debian_GNU/kFreeBSD_FAQ#Q._How_do_I_detect_kfreebsd_with_preprocessor_directives_in_a_C_program.3F 685 gohostos = "freebsd"; 686 #elif defined(__OpenBSD__) 687 gohostos = "openbsd"; 688 #elif defined(__NetBSD__) 689 gohostos = "netbsd"; 690 #elif defined(__sun) && defined(__SVR4) 691 gohostos = "solaris"; 692 // Even on 64-bit platform, solaris uname -m prints i86pc. 693 run(&b, nil, 0, "isainfo", "-n", nil); 694 if(contains(bstr(&b), "amd64")) 695 gohostarch = "amd64"; 696 if(contains(bstr(&b), "i386")) 697 gohostarch = "386"; 698 #else 699 fatal("unknown operating system"); 700 #endif 701 702 if(gohostarch == nil) { 703 if(uname(&u) < 0) 704 fatal("uname: %s", strerror(errno)); 705 if(contains(u.machine, "x86_64") || contains(u.machine, "amd64")) 706 gohostarch = "amd64"; 707 else if(hassuffix(u.machine, "86")) 708 gohostarch = "386"; 709 else if(contains(u.machine, "arm")) 710 gohostarch = "arm"; 711 else if(contains(u.machine, "ppc64le")) 712 gohostarch = "ppc64le"; 713 else if(contains(u.machine, "ppc64")) 714 gohostarch = "ppc64"; 715 else 716 fatal("unknown architecture: %s", u.machine); 717 } 718 719 if(streq(gohostarch, "arm")) 720 maxnbg = 1; 721 722 // The OS X 10.6 linker does not support external linking mode. 723 // See golang.org/issue/5130. 724 // 725 // OS X 10.6 does not work with clang either, but OS X 10.9 requires it. 726 // It seems to work with OS X 10.8, so we default to clang for 10.8 and later. 727 // See golang.org/issue/5822. 728 // 729 // Roughly, OS X 10.N shows up as uname release (N+4), 730 // so OS X 10.6 is uname version 10 and OS X 10.8 is uname version 12. 731 if(streq(gohostos, "darwin")) { 732 if(uname(&u) < 0) 733 fatal("uname: %s", strerror(errno)); 734 osx = atoi(u.release) - 4; 735 if(osx <= 6) 736 goextlinkenabled = "0"; 737 if(osx >= 8) 738 defaultclang = 1; 739 } 740 741 init(); 742 xmain(argc, argv); 743 bfree(&b); 744 return 0; 745 } 746 747 // xqsort is a wrapper for the C standard qsort. 748 void 749 xqsort(void *data, int n, int elemsize, int (*cmp)(const void*, const void*)) 750 { 751 qsort(data, n, elemsize, cmp); 752 } 753 754 // xstrcmp compares the NUL-terminated strings a and b. 755 int 756 xstrcmp(char *a, char *b) 757 { 758 return strcmp(a, b); 759 } 760 761 // xstrstr returns a pointer to the first occurrence of b in a. 762 char* 763 xstrstr(char *a, char *b) 764 { 765 return strstr(a, b); 766 } 767 768 // xstrrchr returns a pointer to the final occurrence of c in p. 769 char* 770 xstrrchr(char *p, int c) 771 { 772 return strrchr(p, c); 773 } 774 775 // xsamefile reports whether f1 and f2 are the same file (or dir) 776 int 777 xsamefile(char *f1, char *f2) 778 { 779 return streq(f1, f2); // suffice for now 780 } 781 782 sigjmp_buf sigill_jmpbuf; 783 static void sigillhand(int); 784 785 // xtryexecfunc tries to execute function f, if any illegal instruction 786 // signal received in the course of executing that function, it will 787 // return 0, otherwise it will return 1. 788 // Some systems (notably NetBSD) will spin and spin when executing VFPv3 789 // instructions on VFPv2 system (e.g. Raspberry Pi) without ever triggering 790 // SIGILL, so we set a 1-second alarm to catch that case. 791 int 792 xtryexecfunc(void (*f)(void)) 793 { 794 int r; 795 r = 0; 796 signal(SIGILL, sigillhand); 797 signal(SIGALRM, sigillhand); 798 alarm(1); 799 if(sigsetjmp(sigill_jmpbuf, 1) == 0) { 800 f(); 801 r = 1; 802 } 803 signal(SIGILL, SIG_DFL); 804 alarm(0); 805 signal(SIGALRM, SIG_DFL); 806 return r; 807 } 808 809 // SIGILL handler helper 810 static void 811 sigillhand(int signum) 812 { 813 USED(signum); 814 siglongjmp(sigill_jmpbuf, 1); 815 } 816 817 static void 818 __cpuid(int dst[4], int ax) 819 { 820 #ifdef __i386__ 821 // we need to avoid ebx on i386 (esp. when -fPIC). 822 asm volatile( 823 "mov %%ebx, %%edi\n\t" 824 "cpuid\n\t" 825 "xchgl %%ebx, %%edi" 826 : "=a" (dst[0]), "=D" (dst[1]), "=c" (dst[2]), "=d" (dst[3]) 827 : "0" (ax)); 828 #elif defined(__x86_64__) 829 asm volatile("cpuid" 830 : "=a" (dst[0]), "=b" (dst[1]), "=c" (dst[2]), "=d" (dst[3]) 831 : "0" (ax)); 832 #else 833 dst[0] = dst[1] = dst[2] = dst[3] = 0; 834 #endif 835 } 836 837 bool 838 cansse2(void) 839 { 840 int info[4]; 841 842 __cpuid(info, 1); 843 return (info[3] & (1<<26)) != 0; // SSE2 844 } 845 846 #endif // PLAN9 847 #endif // __WINDOWS__