github.com/HACKERALERT/Picocrypt/src/external/sys@v0.0.0-20210609020157-e519952f829f/unix/syscall_zos_test.go (about) 1 // Copyright 2020 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 //go:build zos && s390x 6 // +build zos,s390x 7 8 package unix_test 9 10 import ( 11 "bytes" 12 "flag" 13 "fmt" 14 "io/ioutil" 15 "net" 16 "os" 17 "os/exec" 18 "path/filepath" 19 "runtime" 20 "strconv" 21 "syscall" 22 "testing" 23 "time" 24 "unsafe" 25 26 "golang.org/x/sys/unix" 27 ) 28 29 // Tests that below functions, structures and constants are consistent 30 // on all Unix-like systems. 31 func _() { 32 // program scheduling priority functions and constants 33 var ( 34 _ func(int, int, int) error = unix.Setpriority 35 _ func(int, int) (int, error) = unix.Getpriority 36 ) 37 const ( 38 _ int = unix.PRIO_USER 39 _ int = unix.PRIO_PROCESS 40 _ int = unix.PRIO_PGRP 41 ) 42 43 // termios constants 44 const ( 45 _ int = unix.TCIFLUSH 46 _ int = unix.TCIOFLUSH 47 _ int = unix.TCOFLUSH 48 ) 49 50 // fcntl file locking structure and constants 51 var ( 52 _ = unix.Flock_t{ 53 Type: int16(0), 54 Whence: int16(0), 55 Start: int64(0), 56 Len: int64(0), 57 Pid: int32(0), 58 } 59 ) 60 const ( 61 _ = unix.F_GETLK 62 _ = unix.F_SETLK 63 _ = unix.F_SETLKW 64 ) 65 } 66 67 func TestErrnoSignalName(t *testing.T) { 68 testErrors := []struct { 69 num syscall.Errno 70 name string 71 }{ 72 {syscall.EPERM, "EDC5139I"}, 73 {syscall.EINVAL, "EDC5121I"}, 74 {syscall.ENOENT, "EDC5129I"}, 75 } 76 77 for _, te := range testErrors { 78 t.Run(fmt.Sprintf("%d/%s", te.num, te.name), func(t *testing.T) { 79 e := unix.ErrnoName(te.num) 80 if e != te.name { 81 t.Errorf("ErrnoName(%d) returned %s, want %s", te.num, e, te.name) 82 } 83 }) 84 } 85 86 testSignals := []struct { 87 num syscall.Signal 88 name string 89 }{ 90 {syscall.SIGHUP, "SIGHUP"}, 91 {syscall.SIGPIPE, "SIGPIPE"}, 92 {syscall.SIGSEGV, "SIGSEGV"}, 93 } 94 95 for _, ts := range testSignals { 96 t.Run(fmt.Sprintf("%d/%s", ts.num, ts.name), func(t *testing.T) { 97 s := unix.SignalName(ts.num) 98 if s != ts.name { 99 t.Errorf("SignalName(%d) returned %s, want %s", ts.num, s, ts.name) 100 } 101 }) 102 } 103 } 104 105 func TestSignalNum(t *testing.T) { 106 testSignals := []struct { 107 name string 108 want syscall.Signal 109 }{ 110 {"SIGHUP", syscall.SIGHUP}, 111 {"SIGPIPE", syscall.SIGPIPE}, 112 {"SIGSEGV", syscall.SIGSEGV}, 113 {"NONEXISTS", 0}, 114 } 115 for _, ts := range testSignals { 116 t.Run(fmt.Sprintf("%s/%d", ts.name, ts.want), func(t *testing.T) { 117 got := unix.SignalNum(ts.name) 118 if got != ts.want { 119 t.Errorf("SignalNum(%s) returned %d, want %d", ts.name, got, ts.want) 120 } 121 }) 122 123 } 124 } 125 126 func TestFcntlInt(t *testing.T) { 127 t.Parallel() 128 file, err := ioutil.TempFile("", "TestFnctlInt") 129 if err != nil { 130 t.Fatal(err) 131 } 132 defer os.Remove(file.Name()) 133 defer file.Close() 134 f := file.Fd() 135 flags, err := unix.FcntlInt(f, unix.F_GETFD, 0) 136 if err != nil { 137 t.Fatal(err) 138 } 139 if flags&unix.FD_CLOEXEC == 0 { 140 t.Errorf("flags %#x do not include FD_CLOEXEC", flags) 141 } 142 } 143 144 // TestFcntlFlock tests whether the file locking structure matches 145 // the calling convention of each kernel. 146 func TestFcntlFlock(t *testing.T) { 147 name := filepath.Join(os.TempDir(), "TestFcntlFlock") 148 fd, err := unix.Open(name, unix.O_CREAT|unix.O_RDWR|unix.O_CLOEXEC, 0) 149 if err != nil { 150 t.Fatalf("Open failed: %v", err) 151 } 152 defer unix.Unlink(name) 153 defer unix.Close(fd) 154 flock := unix.Flock_t{ 155 Type: unix.F_RDLCK, 156 Start: 0, Len: 0, Whence: 1, 157 } 158 if err := unix.FcntlFlock(uintptr(fd), unix.F_GETLK, &flock); err != nil { 159 t.Fatalf("FcntlFlock failed: %v", err) 160 } 161 } 162 163 // TestPassFD tests passing a file descriptor over a Unix socket. 164 // 165 // This test involved both a parent and child process. The parent 166 // process is invoked as a normal test, with "go test", which then 167 // runs the child process by running the current test binary with args 168 // "-test.run=^TestPassFD$" and an environment variable used to signal 169 // that the test should become the child process instead. 170 func TestPassFD(t *testing.T) { 171 if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" { 172 t.Skip("cannot exec subprocess on iOS, skipping test") 173 } 174 175 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" { 176 passFDChild() 177 return 178 } 179 180 if runtime.GOOS == "aix" { 181 // Unix network isn't properly working on AIX 182 // 7.2 with Technical Level < 2 183 out, err := exec.Command("oslevel", "-s").Output() 184 if err != nil { 185 t.Skipf("skipping on AIX because oslevel -s failed: %v", err) 186 } 187 188 if len(out) < len("7200-XX-ZZ-YYMM") { // AIX 7.2, Tech Level XX, Service Pack ZZ, date YYMM 189 t.Skip("skipping on AIX because oslevel -s hasn't the right length") 190 } 191 aixVer := string(out[:4]) 192 tl, err := strconv.Atoi(string(out[5:7])) 193 if err != nil { 194 t.Skipf("skipping on AIX because oslevel -s output cannot be parsed: %v", err) 195 } 196 if aixVer < "7200" || (aixVer == "7200" && tl < 2) { 197 t.Skip("skipped on AIX versions previous to 7.2 TL 2") 198 } 199 } 200 201 tempDir, err := ioutil.TempDir("", "TestPassFD") 202 if err != nil { 203 t.Fatal(err) 204 } 205 defer os.RemoveAll(tempDir) 206 207 fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM, 0) 208 if err != nil { 209 t.Fatalf("Socketpair: %v", err) 210 } 211 writeFile := os.NewFile(uintptr(fds[0]), "child-writes") 212 readFile := os.NewFile(uintptr(fds[1]), "parent-reads") 213 defer writeFile.Close() 214 defer readFile.Close() 215 216 cmd := exec.Command(os.Args[0], "-test.run=^TestPassFD$", "--", tempDir) 217 cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} 218 if lp := os.Getenv("LD_LIBRARY_PATH"); lp != "" { 219 cmd.Env = append(cmd.Env, "LD_LIBRARY_PATH="+lp) 220 } 221 cmd.ExtraFiles = []*os.File{writeFile} 222 223 out, err := cmd.CombinedOutput() 224 if len(out) > 0 || err != nil { 225 t.Fatalf("child process: %q, %v", out, err) 226 } 227 228 c, err := net.FileConn(readFile) 229 if err != nil { 230 t.Fatalf("FileConn: %v", err) 231 } 232 defer c.Close() 233 234 uc, ok := c.(*net.UnixConn) 235 if !ok { 236 t.Fatalf("unexpected FileConn type; expected UnixConn, got %T", c) 237 } 238 239 buf := make([]byte, 32) // expect 1 byte 240 oob := make([]byte, 32) // expect 24 bytes 241 closeUnix := time.AfterFunc(5*time.Second, func() { 242 t.Logf("timeout reading from unix socket") 243 uc.Close() 244 }) 245 _, oobn, _, _, err := uc.ReadMsgUnix(buf, oob) 246 if err != nil { 247 t.Fatalf("ReadMsgUnix: %v", err) 248 } 249 closeUnix.Stop() 250 251 scms, err := unix.ParseSocketControlMessage(oob[:oobn]) 252 if err != nil { 253 t.Fatalf("ParseSocketControlMessage: %v", err) 254 } 255 if len(scms) != 1 { 256 t.Fatalf("expected 1 SocketControlMessage; got scms = %#v", scms) 257 } 258 scm := scms[0] 259 gotFds, err := unix.ParseUnixRights(&scm) 260 if err != nil { 261 t.Fatalf("unix.ParseUnixRights: %v", err) 262 } 263 if len(gotFds) != 1 { 264 t.Fatalf("wanted 1 fd; got %#v", gotFds) 265 } 266 267 f := os.NewFile(uintptr(gotFds[0]), "fd-from-child") 268 defer f.Close() 269 270 got, err := ioutil.ReadAll(f) 271 want := "Hello from child process!\n" 272 if string(got) != want { 273 t.Errorf("child process ReadAll: %q, %v; want %q", got, err, want) 274 } 275 } 276 277 // passFDChild is the child process used by TestPassFD. 278 func passFDChild() { 279 defer os.Exit(0) 280 281 // Look for our fd. It should be fd 3, but we work around an fd leak 282 // bug here (http://golang.org/issue/2603) to let it be elsewhere. 283 var uc *net.UnixConn 284 for fd := uintptr(3); fd <= 10; fd++ { 285 f := os.NewFile(fd, "unix-conn") 286 var ok bool 287 netc, _ := net.FileConn(f) 288 uc, ok = netc.(*net.UnixConn) 289 if ok { 290 break 291 } 292 } 293 if uc == nil { 294 fmt.Println("failed to find unix fd") 295 return 296 } 297 298 // Make a file f to send to our parent process on uc. 299 // We make it in tempDir, which our parent will clean up. 300 flag.Parse() 301 tempDir := flag.Arg(0) 302 f, err := ioutil.TempFile(tempDir, "") 303 if err != nil { 304 fmt.Printf("TempFile: %v", err) 305 return 306 } 307 308 f.Write([]byte("Hello from child process!\n")) 309 f.Seek(0, 0) 310 311 rights := unix.UnixRights(int(f.Fd())) 312 dummyByte := []byte("x") 313 n, oobn, err := uc.WriteMsgUnix(dummyByte, rights, nil) 314 if err != nil { 315 fmt.Printf("WriteMsgUnix: %v", err) 316 return 317 } 318 if n != 1 || oobn != len(rights) { 319 fmt.Printf("WriteMsgUnix = %d, %d; want 1, %d", n, oobn, len(rights)) 320 return 321 } 322 } 323 324 // TestUnixRightsRoundtrip tests that UnixRights, ParseSocketControlMessage, 325 // and ParseUnixRights are able to successfully round-trip lists of file descriptors. 326 func TestUnixRightsRoundtrip(t *testing.T) { 327 testCases := [...][][]int{ 328 {{42}}, 329 {{1, 2}}, 330 {{3, 4, 5}}, 331 {{}}, 332 {{1, 2}, {3, 4, 5}, {}, {7}}, 333 } 334 for _, testCase := range testCases { 335 b := []byte{} 336 var n int 337 for _, fds := range testCase { 338 // Last assignment to n wins 339 n = len(b) + unix.CmsgLen(4*len(fds)) 340 b = append(b, unix.UnixRights(fds...)...) 341 } 342 // Truncate b 343 b = b[:n] 344 345 scms, err := unix.ParseSocketControlMessage(b) 346 if err != nil { 347 t.Fatalf("ParseSocketControlMessage: %v", err) 348 } 349 if len(scms) != len(testCase) { 350 t.Fatalf("expected %v SocketControlMessage; got scms = %#v", len(testCase), scms) 351 } 352 for i, scm := range scms { 353 gotFds, err := unix.ParseUnixRights(&scm) 354 if err != nil { 355 t.Fatalf("ParseUnixRights: %v", err) 356 } 357 wantFds := testCase[i] 358 if len(gotFds) != len(wantFds) { 359 t.Fatalf("expected %v fds, got %#v", len(wantFds), gotFds) 360 } 361 for j, fd := range gotFds { 362 if fd != wantFds[j] { 363 t.Fatalf("expected fd %v, got %v", wantFds[j], fd) 364 } 365 } 366 } 367 } 368 } 369 370 func TestRlimit(t *testing.T) { 371 var rlimit, zero unix.Rlimit 372 err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit) 373 if err != nil { 374 t.Fatalf("Getrlimit: save failed: %v", err) 375 } 376 if zero == rlimit { 377 t.Fatalf("Getrlimit: save failed: got zero value %#v", rlimit) 378 } 379 set := rlimit 380 set.Cur = set.Max - 1 381 if runtime.GOOS == "darwin" && set.Cur > 10240 { 382 // The max file limit is 10240, even though 383 // the max returned by Getrlimit is 1<<63-1. 384 // This is OPEN_MAX in sys/syslimits.h. 385 set.Cur = 10240 386 } 387 err = unix.Setrlimit(unix.RLIMIT_NOFILE, &set) 388 if err != nil { 389 t.Fatalf("Setrlimit: set failed: %#v %v", set, err) 390 } 391 var get unix.Rlimit 392 err = unix.Getrlimit(unix.RLIMIT_NOFILE, &get) 393 if err != nil { 394 t.Fatalf("Getrlimit: get failed: %v", err) 395 } 396 set = rlimit 397 set.Cur = set.Max - 1 398 if set != get { 399 // Seems like Darwin requires some privilege to 400 // increase the soft limit of rlimit sandbox, though 401 // Setrlimit never reports an error. 402 switch runtime.GOOS { 403 case "darwin": 404 default: 405 t.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get) 406 } 407 } 408 err = unix.Setrlimit(unix.RLIMIT_NOFILE, &rlimit) 409 if err != nil { 410 t.Fatalf("Setrlimit: restore failed: %#v %v", rlimit, err) 411 } 412 } 413 414 func TestSeekFailure(t *testing.T) { 415 _, err := unix.Seek(-1, 0, 0) 416 if err == nil { 417 t.Fatalf("Seek(-1, 0, 0) did not fail") 418 } 419 str := err.Error() // used to crash on Linux 420 t.Logf("Seek: %v", str) 421 if str == "" { 422 t.Fatalf("Seek(-1, 0, 0) return error with empty message") 423 } 424 } 425 426 func TestSetsockoptString(t *testing.T) { 427 // should not panic on empty string, see issue #31277 428 err := unix.SetsockoptString(-1, 0, 0, "") 429 if err == nil { 430 t.Fatalf("SetsockoptString: did not fail") 431 } 432 } 433 434 func TestDup(t *testing.T) { 435 file, err := ioutil.TempFile("", "TestDup") 436 if err != nil { 437 t.Fatalf("Tempfile failed: %v", err) 438 } 439 defer os.Remove(file.Name()) 440 defer file.Close() 441 f := int(file.Fd()) 442 443 newFd, err := unix.Dup(f) 444 if err != nil { 445 t.Fatalf("Dup: %v", err) 446 } 447 448 // Create and reserve a file descriptor. 449 // Dup2 automatically closes it before reusing it. 450 nullFile, err := os.Open("/dev/null") 451 if err != nil { 452 t.Fatal(err) 453 } 454 dupFd := int(file.Fd()) 455 err = unix.Dup2(newFd, dupFd) 456 if err != nil { 457 t.Fatalf("Dup2: %v", err) 458 } 459 // Keep the dummy file open long enough to not be closed in 460 // its finalizer. 461 runtime.KeepAlive(nullFile) 462 463 b1 := []byte("Test123") 464 b2 := make([]byte, 7) 465 _, err = unix.Write(dupFd, b1) 466 if err != nil { 467 t.Fatalf("Write to dup2 fd failed: %v", err) 468 } 469 _, err = unix.Seek(f, 0, 0) 470 if err != nil { 471 t.Fatalf("Seek failed: %v", err) 472 } 473 _, err = unix.Read(f, b2) 474 if err != nil { 475 t.Fatalf("Read back failed: %v", err) 476 } 477 if string(b1) != string(b2) { 478 t.Errorf("Dup: stdout write not in file, expected %v, got %v", string(b1), string(b2)) 479 } 480 } 481 482 func TestGetwd(t *testing.T) { 483 fd, err := os.Open(".") 484 if err != nil { 485 t.Fatalf("Open .: %s", err) 486 } 487 defer fd.Close() 488 // Directory list for test. Do not worry if any are symlinks or do not 489 // exist on some common unix desktop environments. That will be checked. 490 dirs := []string{"/", "/usr/bin", "/etc", "/var", "/opt"} 491 switch runtime.GOOS { 492 case "android": 493 dirs = []string{"/", "/system/bin"} 494 case "darwin": 495 switch runtime.GOARCH { 496 case "arm64": 497 d1, err := ioutil.TempDir("", "d1") 498 if err != nil { 499 t.Fatalf("TempDir: %v", err) 500 } 501 d2, err := ioutil.TempDir("", "d2") 502 if err != nil { 503 t.Fatalf("TempDir: %v", err) 504 } 505 dirs = []string{d1, d2} 506 } 507 } 508 oldwd := os.Getenv("PWD") 509 for _, d := range dirs { 510 // Check whether d exists, is a dir and that d's path does not contain a symlink 511 fi, err := os.Stat(d) 512 if err != nil || !fi.IsDir() { 513 t.Logf("Test dir %s stat error (%v) or not a directory, skipping", d, err) 514 continue 515 } 516 check, err := filepath.EvalSymlinks(d) 517 if err != nil || check != d { 518 t.Logf("Test dir %s (%s) is symlink or other error (%v), skipping", d, check, err) 519 continue 520 } 521 err = os.Chdir(d) 522 if err != nil { 523 t.Fatalf("Chdir: %v", err) 524 } 525 pwd, err := unix.Getwd() 526 if err != nil { 527 t.Fatalf("Getwd in %s: %s", d, err) 528 } 529 os.Setenv("PWD", oldwd) 530 err = fd.Chdir() 531 if err != nil { 532 // We changed the current directory and cannot go back. 533 // Don't let the tests continue; they'll scribble 534 // all over some other directory. 535 fmt.Fprintf(os.Stderr, "fchdir back to dot failed: %s\n", err) 536 os.Exit(1) 537 } 538 if pwd != d { 539 t.Fatalf("Getwd returned %q want %q", pwd, d) 540 } 541 } 542 } 543 544 func TestMkdev(t *testing.T) { 545 major := uint32(42) 546 minor := uint32(7) 547 dev := unix.Mkdev(major, minor) 548 549 if unix.Major(dev) != major { 550 t.Errorf("Major(%#x) == %d, want %d", dev, unix.Major(dev), major) 551 } 552 if unix.Minor(dev) != minor { 553 t.Errorf("Minor(%#x) == %d, want %d", dev, unix.Minor(dev), minor) 554 } 555 } 556 557 // mktmpfifo creates a temporary FIFO and provides a cleanup function. 558 func mktmpfifo(t *testing.T) (*os.File, func()) { 559 err := unix.Mkfifo("fifo", 0666) 560 if err != nil { 561 t.Fatalf("mktmpfifo: failed to create FIFO: %v", err) 562 } 563 564 f, err := os.OpenFile("fifo", os.O_RDWR, 0666) 565 if err != nil { 566 os.Remove("fifo") 567 t.Fatalf("mktmpfifo: failed to open FIFO: %v", err) 568 } 569 570 return f, func() { 571 f.Close() 572 os.Remove("fifo") 573 } 574 } 575 576 // utilities taken from os/os_test.go 577 578 func touch(t *testing.T, name string) { 579 f, err := os.Create(name) 580 if err != nil { 581 t.Fatal(err) 582 } 583 if err := f.Close(); err != nil { 584 t.Fatal(err) 585 } 586 } 587 588 // chtmpdir changes the working directory to a new temporary directory and 589 // provides a cleanup function. Used when PWD is read-only. 590 func chtmpdir(t *testing.T) func() { 591 oldwd, err := os.Getwd() 592 if err != nil { 593 t.Fatalf("chtmpdir: %v", err) 594 } 595 d, err := ioutil.TempDir("", "test") 596 if err != nil { 597 t.Fatalf("chtmpdir: %v", err) 598 } 599 if err := os.Chdir(d); err != nil { 600 t.Fatalf("chtmpdir: %v", err) 601 } 602 return func() { 603 if err := os.Chdir(oldwd); err != nil { 604 t.Fatalf("chtmpdir: %v", err) 605 } 606 os.RemoveAll(d) 607 } 608 } 609 610 func TestMountUnmount(t *testing.T) { 611 b2s := func(arr []byte) string { 612 nulli := bytes.IndexByte(arr, 0) 613 if nulli == -1 { 614 return string(arr) 615 } else { 616 return string(arr[:nulli]) 617 } 618 } 619 // use an available fs 620 var buffer struct { 621 header unix.W_Mnth 622 fsinfo [64]unix.W_Mntent 623 } 624 fsCount, err := unix.W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer))) 625 if err != nil { 626 t.Fatalf("W_Getmntent_A returns with error: %s", err.Error()) 627 } else if fsCount == 0 { 628 t.Fatalf("W_Getmntent_A returns no entries") 629 } 630 var fs string 631 var fstype string 632 var mountpoint string 633 var available bool = false 634 for i := 0; i < fsCount; i++ { 635 err = unix.Unmount(b2s(buffer.fsinfo[i].Mountpoint[:]), unix.MTM_RDWR) 636 if err != nil { 637 // Unmount and Mount require elevated privilege 638 // If test is run without such permission, skip test 639 if err == unix.EPERM { 640 t.Logf("Permission denied for Unmount. Skipping test (Errno2: %X)", unix.Errno2()) 641 return 642 } else if err == unix.EBUSY { 643 continue 644 } else { 645 t.Fatalf("Unmount returns with error: %s", err.Error()) 646 } 647 } else { 648 available = true 649 fs = b2s(buffer.fsinfo[i].Fsname[:]) 650 fstype = b2s(buffer.fsinfo[i].Fstname[:]) 651 mountpoint = b2s(buffer.fsinfo[i].Mountpoint[:]) 652 t.Logf("using file system = %s; fstype = %s and mountpoint = %s\n", fs, fstype, mountpoint) 653 break 654 } 655 } 656 if !available { 657 t.Fatalf("No filesystem available") 658 } 659 // test unmount 660 buffer.header = unix.W_Mnth{} 661 fsCount, err = unix.W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer))) 662 if err != nil { 663 t.Fatalf("W_Getmntent_A returns with error: %s", err.Error()) 664 } 665 for i := 0; i < fsCount; i++ { 666 if b2s(buffer.fsinfo[i].Fsname[:]) == fs { 667 t.Fatalf("File system found after unmount") 668 } 669 } 670 // test mount 671 err = unix.Mount(fs, mountpoint, fstype, unix.MTM_RDWR, "") 672 if err != nil { 673 t.Fatalf("Mount returns with error: %s", err.Error()) 674 } 675 buffer.header = unix.W_Mnth{} 676 fsCount, err = unix.W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer))) 677 if err != nil { 678 t.Fatalf("W_Getmntent_A returns with error: %s", err.Error()) 679 } 680 fsMounted := false 681 for i := 0; i < fsCount; i++ { 682 if b2s(buffer.fsinfo[i].Fsname[:]) == fs && b2s(buffer.fsinfo[i].Mountpoint[:]) == mountpoint { 683 fsMounted = true 684 } 685 } 686 if !fsMounted { 687 t.Fatalf("%s not mounted after Mount()", fs) 688 } 689 } 690 691 func TestChroot(t *testing.T) { 692 // create temp dir and tempfile 1 693 tempDir, err := ioutil.TempDir("", "TestChroot") 694 if err != nil { 695 t.Fatalf("TempDir: %s", err.Error()) 696 } 697 defer os.RemoveAll(tempDir) 698 f, err := ioutil.TempFile(tempDir, "chroot_test_file") 699 if err != nil { 700 t.Fatalf("TempFile: %s", err.Error()) 701 } 702 // chroot temp dir 703 err = unix.Chroot(tempDir) 704 // Chroot requires elevated privilege 705 // If test is run without such permission, skip test 706 if err == unix.EPERM { 707 t.Logf("Denied permission for Chroot. Skipping test (Errno2: %X)", unix.Errno2()) 708 return 709 } else if err != nil { 710 t.Fatalf("Chroot: %s", err.Error()) 711 } 712 // check if tempDir contains test file 713 files, err := ioutil.ReadDir("/") 714 if err != nil { 715 t.Fatalf("ReadDir: %s", err.Error()) 716 } 717 found := false 718 for _, file := range files { 719 if file.Name() == filepath.Base(f.Name()) { 720 found = true 721 break 722 } 723 } 724 if !found { 725 t.Fatalf("Temp file not found in temp dir") 726 } 727 } 728 729 func TestFlock(t *testing.T) { 730 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" { 731 defer os.Exit(0) 732 if len(os.Args) != 3 { 733 fmt.Printf("bad argument") 734 return 735 } 736 fn := os.Args[2] 737 f, err := os.OpenFile(fn, os.O_RDWR, 0755) 738 if err != nil { 739 fmt.Printf("%s", err.Error()) 740 return 741 } 742 err = unix.Flock(int(f.Fd()), unix.LOCK_EX|unix.LOCK_NB) 743 // if the lock we are trying should be locked, ignore EAGAIN error 744 // otherwise, report all errors 745 if err != nil && err != unix.EAGAIN { 746 fmt.Printf("%s", err.Error()) 747 } 748 } else { 749 // create temp dir and tempfile 1 750 tempDir, err := ioutil.TempDir("", "TestFlock") 751 if err != nil { 752 t.Fatalf("TempDir: %s", err.Error()) 753 } 754 defer os.RemoveAll(tempDir) 755 f, err := ioutil.TempFile(tempDir, "flock_test_file") 756 if err != nil { 757 t.Fatalf("TempFile: %s", err.Error()) 758 } 759 fd := int(f.Fd()) 760 761 /* Test Case 1 762 * Try acquiring an occupied lock from another process 763 */ 764 err = unix.Flock(fd, unix.LOCK_EX) 765 if err != nil { 766 t.Fatalf("Flock: %s", err.Error()) 767 } 768 cmd := exec.Command(os.Args[0], "-test.run=TestFlock", f.Name()) 769 cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1") 770 out, err := cmd.CombinedOutput() 771 if len(out) > 0 || err != nil { 772 t.Fatalf("child process: %q, %v", out, err) 773 } 774 err = unix.Flock(fd, unix.LOCK_UN) 775 if err != nil { 776 t.Fatalf("Flock: %s", err.Error()) 777 } 778 779 /* Test Case 2 780 * Try locking with Flock and FcntlFlock for same file 781 */ 782 err = unix.Flock(fd, unix.LOCK_EX) 783 if err != nil { 784 t.Fatalf("Flock: %s", err.Error()) 785 } 786 flock := unix.Flock_t{ 787 Type: int16(unix.F_WRLCK), 788 Whence: int16(0), 789 Start: int64(0), 790 Len: int64(0), 791 Pid: int32(unix.Getppid()), 792 } 793 err = unix.FcntlFlock(f.Fd(), unix.F_SETLK, &flock) 794 if err != nil { 795 t.Fatalf("FcntlFlock: %s", err.Error()) 796 } 797 } 798 } 799 800 func TestSelect(t *testing.T) { 801 for { 802 n, err := unix.Select(0, nil, nil, nil, &unix.Timeval{Sec: 0, Usec: 0}) 803 if err == unix.EINTR { 804 t.Logf("Select interrupted") 805 continue 806 } else if err != nil { 807 t.Fatalf("Select: %v", err) 808 } 809 if n != 0 { 810 t.Fatalf("Select: got %v ready file descriptors, expected 0", n) 811 } 812 break 813 } 814 815 dur := 250 * time.Millisecond 816 var took time.Duration 817 for { 818 // On some platforms (e.g. Linux), the passed-in timeval is 819 // updated by select(2). Make sure to reset to the full duration 820 // in case of an EINTR. 821 tv := unix.NsecToTimeval(int64(dur)) 822 start := time.Now() 823 n, err := unix.Select(0, nil, nil, nil, &tv) 824 took = time.Since(start) 825 if err == unix.EINTR { 826 t.Logf("Select interrupted after %v", took) 827 continue 828 } else if err != nil { 829 t.Fatalf("Select: %v", err) 830 } 831 if n != 0 { 832 t.Fatalf("Select: got %v ready file descriptors, expected 0", n) 833 } 834 break 835 } 836 837 // On some BSDs the actual timeout might also be slightly less than the requested. 838 // Add an acceptable margin to avoid flaky tests. 839 if took < dur*2/3 { 840 t.Errorf("Select: got %v timeout, expected at least %v", took, dur) 841 } 842 843 rr, ww, err := os.Pipe() 844 if err != nil { 845 t.Fatal(err) 846 } 847 defer rr.Close() 848 defer ww.Close() 849 850 if _, err := ww.Write([]byte("HELLO GOPHER")); err != nil { 851 t.Fatal(err) 852 } 853 854 rFdSet := &unix.FdSet{} 855 fd := int(rr.Fd()) 856 rFdSet.Set(fd) 857 858 for { 859 n, err := unix.Select(fd+1, rFdSet, nil, nil, nil) 860 if err == unix.EINTR { 861 t.Log("Select interrupted") 862 continue 863 } else if err != nil { 864 t.Fatalf("Select: %v", err) 865 } 866 if n != 1 { 867 t.Fatalf("Select: got %v ready file descriptors, expected 1", n) 868 } 869 break 870 } 871 }