...

Source file src/golang.org/x/sys/unix/syscall_zos_test.go

Documentation: golang.org/x/sys/unix

     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  
     7  package unix_test
     8  
     9  import (
    10  	"bytes"
    11  	"errors"
    12  	"flag"
    13  	"fmt"
    14  	"io"
    15  	"log"
    16  	"net"
    17  	"os"
    18  	"os/exec"
    19  	"path/filepath"
    20  	"reflect"
    21  	"regexp"
    22  	"runtime"
    23  	"strconv"
    24  	"strings"
    25  	"syscall"
    26  	"testing"
    27  	"time"
    28  	"unsafe"
    29  
    30  	"golang.org/x/sys/unix"
    31  )
    32  
    33  func TestLibVec(t *testing.T) {
    34  	ret := unix.GetZosLibVec()
    35  	if ret == 0 {
    36  		t.Fatalf("initLibVec failed %v\n", ret)
    37  	}
    38  }
    39  
    40  func TestFprintf(t *testing.T) {
    41  	const expected = 61
    42  	ret, _, _ := unix.CallLeFuncWithErr(unix.GetZosLibVec()+unix.SYS___FPRINTF_A<<4,
    43  		unix.ZosStdioFilep(2), uintptr(unsafe.Pointer(
    44  			reflect.ValueOf([]byte("TEST DATA please ignore, fprintf stderr data %d %d %d %d\x0a\x00")).Pointer())),
    45  		111, 222, 333, 444)
    46  	if ret != expected {
    47  		t.Fatalf("expected bytes written %d , receive %d\n", expected, int(ret))
    48  	}
    49  }
    50  
    51  func TestErrnos(t *testing.T) {
    52  	ret, err1, err2 := unix.CallLeFuncWithErr(unix.GetZosLibVec()+unix.SYS___OPEN_A<<4,
    53  		uintptr(unsafe.Pointer(&(([]byte("/dev/nothing" + "\x00"))[0]))), 0, 0)
    54  	if ret != 0xffffffffffffffff || err2 != 0x79 || err1 != 0x562003f {
    55  		t.Fatalf("Expect ret ffffffffffffffff err2 79 err1 562003f, received  ret %x err2 %x err1 %x\n", ret, err2, err1)
    56  	}
    57  }
    58  
    59  func TestErrnoString(t *testing.T) {
    60  	var (
    61  		ws  unix.WaitStatus
    62  		rus unix.Rusage
    63  	)
    64  	_, err := unix.Wait4(-1, &ws, unix.WNOHANG, &rus)
    65  	if syscall.Errno(int32(err.(syscall.Errno))) != unix.ECHILD {
    66  		t.Fatalf("err != unix.ECHILD")
    67  	}
    68  }
    69  
    70  func BypassTestOnUntil(sys string, date string) bool {
    71  	t0, er0 := time.Parse(time.RFC3339, date)
    72  	if er0 != nil {
    73  		fmt.Printf("Bad date-time spec %s\n", date)
    74  		return false
    75  	}
    76  	if time.Now().After(t0) {
    77  		return false
    78  	}
    79  	host1, er1 := os.Hostname()
    80  	hostname := strings.Split(host1, ".")[0]
    81  
    82  	if er1 == nil && strings.EqualFold(hostname, sys) {
    83  		pc, file, line, ok := runtime.Caller(1)
    84  		if ok {
    85  			name := runtime.FuncForPC(pc).Name()
    86  			fmt.Fprintf(os.Stderr, "TODO: Test bypassed on %s %v:%v %v\n", hostname, file, line, name)
    87  			return true
    88  		}
    89  	}
    90  	return false
    91  
    92  }
    93  
    94  var euid = unix.Geteuid()
    95  
    96  // Tests that below functions, structures and constants are consistent
    97  // on all Unix-like systems.
    98  func _() {
    99  	// program scheduling priority functions and constants
   100  	var (
   101  		_ func(int, int, int) error   = unix.Setpriority
   102  		_ func(int, int) (int, error) = unix.Getpriority
   103  	)
   104  	const (
   105  		_ int = unix.PRIO_USER
   106  		_ int = unix.PRIO_PROCESS
   107  		_ int = unix.PRIO_PGRP
   108  	)
   109  
   110  	// termios constants
   111  	const (
   112  		_ int = unix.TCIFLUSH
   113  		_ int = unix.TCIOFLUSH
   114  		_ int = unix.TCOFLUSH
   115  	)
   116  
   117  	// fcntl file locking structure and constants
   118  	var (
   119  		_ = unix.Flock_t{
   120  			Type:   int16(0),
   121  			Whence: int16(0),
   122  			Start:  int64(0),
   123  			Len:    int64(0),
   124  			Pid:    int32(0),
   125  		}
   126  	)
   127  	const (
   128  		_ = unix.F_GETLK
   129  		_ = unix.F_SETLK
   130  		_ = unix.F_SETLKW
   131  	)
   132  }
   133  
   134  func zosLeVersion() (version, release uint32) {
   135  	p1 := (*(*uintptr)(unsafe.Pointer(uintptr(1208)))) >> 32
   136  	p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 88)))
   137  	p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 8)))
   138  	p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 984)))
   139  	vrm := *(*uint32)(unsafe.Pointer(p1 + 80))
   140  	version = (vrm & 0x00ff0000) >> 16
   141  	release = (vrm & 0x0000ff00) >> 8
   142  	return
   143  }
   144  
   145  func TestErrnoSignalName(t *testing.T) {
   146  	testErrors := []struct {
   147  		num  syscall.Errno
   148  		name string
   149  	}{
   150  		{syscall.EPERM, "EDC5139I"},
   151  		{syscall.EINVAL, "EDC5121I"},
   152  		{syscall.ENOENT, "EDC5129I"},
   153  	}
   154  
   155  	for _, te := range testErrors {
   156  		t.Run(fmt.Sprintf("%d/%s", te.num, te.name), func(t *testing.T) {
   157  			e := unix.ErrnoName(te.num)
   158  			if e != te.name {
   159  				t.Errorf("ErrnoName(%d) returned %s, want %s", te.num, e, te.name)
   160  			}
   161  		})
   162  	}
   163  
   164  	testSignals := []struct {
   165  		num  syscall.Signal
   166  		name string
   167  	}{
   168  		{syscall.SIGHUP, "SIGHUP"},
   169  		{syscall.SIGPIPE, "SIGPIPE"},
   170  		{syscall.SIGSEGV, "SIGSEGV"},
   171  	}
   172  
   173  	for _, ts := range testSignals {
   174  		t.Run(fmt.Sprintf("%d/%s", ts.num, ts.name), func(t *testing.T) {
   175  			s := unix.SignalName(ts.num)
   176  			if s != ts.name {
   177  				t.Errorf("SignalName(%d) returned %s, want %s", ts.num, s, ts.name)
   178  			}
   179  		})
   180  	}
   181  }
   182  
   183  func TestSignalNum(t *testing.T) {
   184  	testSignals := []struct {
   185  		name string
   186  		want syscall.Signal
   187  	}{
   188  		{"SIGHUP", syscall.SIGHUP},
   189  		{"SIGPIPE", syscall.SIGPIPE},
   190  		{"SIGSEGV", syscall.SIGSEGV},
   191  		{"NONEXISTS", 0},
   192  	}
   193  	for _, ts := range testSignals {
   194  		t.Run(fmt.Sprintf("%s/%d", ts.name, ts.want), func(t *testing.T) {
   195  			got := unix.SignalNum(ts.name)
   196  			if got != ts.want {
   197  				t.Errorf("SignalNum(%s) returned %d, want %d", ts.name, got, ts.want)
   198  			}
   199  		})
   200  
   201  	}
   202  }
   203  
   204  func TestFcntlInt(t *testing.T) {
   205  	t.Parallel()
   206  	file, err := os.Create(filepath.Join(t.TempDir(), t.Name()))
   207  	if err != nil {
   208  		t.Fatal(err)
   209  	}
   210  	defer file.Close()
   211  	f := file.Fd()
   212  	flags, err := unix.FcntlInt(f, unix.F_GETFD, 0)
   213  	if err != nil {
   214  		t.Fatal(err)
   215  	}
   216  	if flags&unix.FD_CLOEXEC == 0 {
   217  		t.Errorf("flags %#x do not include FD_CLOEXEC", flags)
   218  	}
   219  }
   220  
   221  func TestFcntlInt2(t *testing.T) {
   222  	t.Parallel()
   223  	file, err := os.Create(filepath.Join(t.TempDir(), t.Name()))
   224  	if err != nil {
   225  		t.Fatal(err)
   226  	}
   227  	defer file.Close()
   228  	f := file.Fd()
   229  	flags, err := unix.Fcntl(f, unix.F_GETFD, 0)
   230  	if err != nil {
   231  		t.Fatal(err)
   232  	}
   233  	if flags&unix.FD_CLOEXEC == 0 {
   234  		t.Errorf("flags %#x do not include FD_CLOEXEC", flags)
   235  	}
   236  }
   237  
   238  // TestFcntlFlock tests whether the file locking structure matches
   239  // the calling convention of each kernel.
   240  func TestFcntlFlock(t *testing.T) {
   241  	name := filepath.Join(t.TempDir(), "TestFcntlFlock")
   242  	fd, err := unix.Open(name, unix.O_CREAT|unix.O_RDWR|unix.O_CLOEXEC, 0)
   243  	if err != nil {
   244  		t.Fatalf("Open failed: %v", err)
   245  	}
   246  	defer unix.Unlink(name)
   247  	defer unix.Close(fd)
   248  	flock := unix.Flock_t{
   249  		Type:  unix.F_RDLCK,
   250  		Start: 0, Len: 0, Whence: 1,
   251  	}
   252  	if err := unix.FcntlFlock(uintptr(fd), unix.F_GETLK, &flock); err != nil {
   253  		t.Fatalf("FcntlFlock failed: %v", err)
   254  	}
   255  }
   256  
   257  func TestFcntlFlock2(t *testing.T) {
   258  	name := filepath.Join(t.TempDir(), "TestFcntlFlock2")
   259  	fd, err := unix.Open(name, unix.O_CREAT|unix.O_RDWR|unix.O_CLOEXEC, 0)
   260  	if err != nil {
   261  		t.Fatalf("Open failed: %v", err)
   262  	}
   263  	defer unix.Unlink(name)
   264  	defer unix.Close(fd)
   265  	flock := unix.Flock_t{
   266  		Type:  unix.F_RDLCK,
   267  		Start: 0, Len: 0, Whence: 1,
   268  	}
   269  	if v, err := unix.Fcntl(uintptr(fd), unix.F_GETLK, &flock); err != nil {
   270  		t.Fatalf("FcntlFlock failed: %d %v", v, err)
   271  	}
   272  }
   273  
   274  // TestPassFD tests passing a file descriptor over a Unix socket.
   275  //
   276  // This test involved both a parent and child process. The parent
   277  // process is invoked as a normal test, with "go test", which then
   278  // runs the child process by running the current test binary with args
   279  // "-test.run=^TestPassFD$" and an environment variable used to signal
   280  // that the test should become the child process instead.
   281  func TestPassFD(t *testing.T) {
   282  	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
   283  		passFDChild()
   284  		return
   285  	}
   286  
   287  	fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM, 0)
   288  	if err != nil {
   289  		t.Fatalf("Socketpair: %v", err)
   290  	}
   291  	defer unix.Close(fds[0])
   292  	defer unix.Close(fds[1])
   293  	writeFile := os.NewFile(uintptr(fds[0]), "child-writes")
   294  	readFile := os.NewFile(uintptr(fds[1]), "parent-reads")
   295  	defer writeFile.Close()
   296  	defer readFile.Close()
   297  
   298  	exe, err := os.Executable()
   299  	if err != nil {
   300  		t.Fatal(err)
   301  	}
   302  	cmd := exec.Command(exe, "-test.run=^TestPassFD$", "--", t.TempDir())
   303  	cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
   304  	if lp := os.Getenv("LD_LIBRARY_PATH"); lp != "" {
   305  		cmd.Env = append(cmd.Env, "LD_LIBRARY_PATH="+lp)
   306  	}
   307  	cmd.ExtraFiles = []*os.File{writeFile}
   308  
   309  	out, err := cmd.CombinedOutput()
   310  	if len(out) > 0 || err != nil {
   311  		t.Fatalf("child process: %q, %v", out, err)
   312  	}
   313  
   314  	c, err := net.FileConn(readFile)
   315  	if err != nil {
   316  		t.Fatalf("FileConn: %v", err)
   317  	}
   318  	defer c.Close()
   319  
   320  	uc, ok := c.(*net.UnixConn)
   321  	if !ok {
   322  		t.Fatalf("unexpected FileConn type; expected UnixConn, got %T", c)
   323  	}
   324  
   325  	buf := make([]byte, 32) // expect 1 byte
   326  	oob := make([]byte, 32) // expect 24 bytes
   327  	closeUnix := time.AfterFunc(5*time.Second, func() {
   328  		t.Logf("timeout reading from unix socket")
   329  		uc.Close()
   330  	})
   331  	_, oobn, _, _, err := uc.ReadMsgUnix(buf, oob)
   332  	if err != nil {
   333  		t.Fatalf("ReadMsgUnix: %v", err)
   334  	}
   335  	closeUnix.Stop()
   336  
   337  	scms, err := unix.ParseSocketControlMessage(oob[:oobn])
   338  	if err != nil {
   339  		t.Fatalf("ParseSocketControlMessage: %v", err)
   340  	}
   341  	if len(scms) != 1 {
   342  		t.Fatalf("expected 1 SocketControlMessage; got scms = %#v", scms)
   343  	}
   344  	scm := scms[0]
   345  	gotFds, err := unix.ParseUnixRights(&scm)
   346  	if err != nil {
   347  		t.Fatalf("unix.ParseUnixRights: %v", err)
   348  	}
   349  	if len(gotFds) != 1 {
   350  		t.Fatalf("wanted 1 fd; got %#v", gotFds)
   351  	}
   352  
   353  	f := os.NewFile(uintptr(gotFds[0]), "fd-from-child")
   354  	defer f.Close()
   355  
   356  	got, err := io.ReadAll(f)
   357  	want := "Hello from child process!\n"
   358  	if string(got) != want {
   359  		t.Errorf("child process ReadAll: %q, %v; want %q", got, err, want)
   360  	}
   361  }
   362  
   363  // passFDChild is the child process used by TestPassFD.
   364  func passFDChild() {
   365  	defer os.Exit(0)
   366  
   367  	// Look for our fd. It should be fd 3, but we work around an fd leak
   368  	// bug here (http://golang.org/issue/2603) to let it be elsewhere.
   369  	var uc *net.UnixConn
   370  	for fd := uintptr(3); fd <= 10; fd++ {
   371  		f := os.NewFile(fd, "unix-conn")
   372  		var ok bool
   373  		netc, _ := net.FileConn(f)
   374  		uc, ok = netc.(*net.UnixConn)
   375  		if ok {
   376  			break
   377  		}
   378  	}
   379  	if uc == nil {
   380  		fmt.Println("failed to find unix fd")
   381  		return
   382  	}
   383  
   384  	// Make a file f to send to our parent process on uc.
   385  	// We make it in tempDir, which our parent will clean up.
   386  	flag.Parse()
   387  	tempDir := flag.Arg(0)
   388  	f, err := os.CreateTemp(tempDir, "")
   389  	if err != nil {
   390  		fmt.Printf("TempFile: %v", err)
   391  		return
   392  	}
   393  	defer f.Close()
   394  
   395  	f.Write([]byte("Hello from child process!\n"))
   396  	f.Seek(0, 0)
   397  
   398  	rights := unix.UnixRights(int(f.Fd()))
   399  	dummyByte := []byte("x")
   400  	n, oobn, err := uc.WriteMsgUnix(dummyByte, rights, nil)
   401  	if err != nil {
   402  		fmt.Printf("WriteMsgUnix: %v", err)
   403  		return
   404  	}
   405  	if n != 1 || oobn != len(rights) {
   406  		fmt.Printf("WriteMsgUnix = %d, %d; want 1, %d", n, oobn, len(rights))
   407  		return
   408  	}
   409  }
   410  
   411  // TestUnixRightsRoundtrip tests that UnixRights, ParseSocketControlMessage, ParseOneSocketControlMessage,
   412  // and ParseUnixRights are able to successfully round-trip lists of file descriptors.
   413  func TestUnixRightsRoundtrip(t *testing.T) {
   414  	testCases := [...][][]int{
   415  		{{42}},
   416  		{{1, 2}},
   417  		{{3, 4, 5}},
   418  		{{}},
   419  		{{1, 2}, {3, 4, 5}, {}, {7}},
   420  	}
   421  	for _, testCase := range testCases {
   422  		b := []byte{}
   423  		var n int
   424  		for _, fds := range testCase {
   425  			// Last assignment to n wins
   426  			n = len(b) + unix.CmsgLen(4*len(fds))
   427  			b = append(b, unix.UnixRights(fds...)...)
   428  		}
   429  		// Truncate b
   430  		b = b[:n]
   431  
   432  		scms, err := unix.ParseSocketControlMessage(b)
   433  		if err != nil {
   434  			t.Fatalf("ParseSocketControlMessage: %v", err)
   435  		}
   436  		if len(scms) != len(testCase) {
   437  			t.Fatalf("expected %v SocketControlMessage; got scms = %#v", len(testCase), scms)
   438  		}
   439  
   440  		var c int
   441  		for len(b) > 0 {
   442  			hdr, data, remainder, err := unix.ParseOneSocketControlMessage(b)
   443  			if err != nil {
   444  				t.Fatalf("ParseOneSocketControlMessage: %v", err)
   445  			}
   446  			if scms[c].Header != hdr || !bytes.Equal(scms[c].Data, data) {
   447  				t.Fatal("expected SocketControlMessage header and data to match")
   448  			}
   449  			b = remainder
   450  			c++
   451  		}
   452  		if c != len(scms) {
   453  			t.Fatalf("expected %d SocketControlMessages; got %d", len(scms), c)
   454  		}
   455  
   456  		for i, scm := range scms {
   457  			gotFds, err := unix.ParseUnixRights(&scm)
   458  			if err != nil {
   459  				t.Fatalf("ParseUnixRights: %v", err)
   460  			}
   461  			wantFds := testCase[i]
   462  			if len(gotFds) != len(wantFds) {
   463  				t.Fatalf("expected %v fds, got %#v", len(wantFds), gotFds)
   464  			}
   465  			for j, fd := range gotFds {
   466  				if fd != wantFds[j] {
   467  					t.Fatalf("expected fd %v, got %v", wantFds[j], fd)
   468  				}
   469  			}
   470  		}
   471  	}
   472  }
   473  
   474  func TestPrlimit(t *testing.T) {
   475  	var rlimit, get, set, zero unix.Rlimit
   476  	// Save initial settings
   477  	err := unix.Prlimit(0, unix.RLIMIT_NOFILE, nil, &rlimit)
   478  	if err != nil {
   479  		t.Fatalf("Prlimit: save failed: %v", err)
   480  	}
   481  	if zero == rlimit {
   482  		t.Fatalf("Prlimit: save failed: got zero value %#v", rlimit)
   483  	}
   484  	set = rlimit
   485  	set.Cur = set.Max - 1
   486  	// Set to one below max
   487  	err = unix.Prlimit(0, unix.RLIMIT_NOFILE, &set, nil)
   488  	if err != nil {
   489  		t.Fatalf("Prlimit: set failed: %#v %v", set, err)
   490  	}
   491  	// Get and restore to original
   492  	err = unix.Prlimit(0, unix.RLIMIT_NOFILE, &rlimit, &get)
   493  	if err != nil {
   494  		t.Fatalf("Prlimit: get and restore failed: %v", err)
   495  	}
   496  	if set != get {
   497  		t.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
   498  	}
   499  }
   500  
   501  func TestRlimit(t *testing.T) {
   502  	var rlimit, zero unix.Rlimit
   503  	err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit)
   504  	if err != nil {
   505  		t.Fatalf("Getrlimit: save failed: %v", err)
   506  	}
   507  	if zero == rlimit {
   508  		t.Fatalf("Getrlimit: save failed: got zero value %#v", rlimit)
   509  	}
   510  	set := rlimit
   511  	set.Cur = set.Max - 1
   512  
   513  	err = unix.Setrlimit(unix.RLIMIT_NOFILE, &set)
   514  	if err != nil {
   515  		t.Fatalf("Setrlimit: set failed: %#v %v", set, err)
   516  	}
   517  	var get unix.Rlimit
   518  	err = unix.Getrlimit(unix.RLIMIT_NOFILE, &get)
   519  	if err != nil {
   520  		t.Fatalf("Getrlimit: get failed: %v", err)
   521  	}
   522  	set = rlimit
   523  	set.Cur = set.Max - 1
   524  	if set != get {
   525  		t.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
   526  	}
   527  	err = unix.Setrlimit(unix.RLIMIT_NOFILE, &rlimit)
   528  	if err != nil {
   529  		t.Fatalf("Setrlimit: restore failed: %#v %v", rlimit, err)
   530  	}
   531  
   532  	// make sure RLIM_INFINITY can be assigned to Rlimit members
   533  	_ = unix.Rlimit{
   534  		Cur: unix.RLIM_INFINITY,
   535  		Max: unix.RLIM_INFINITY,
   536  	}
   537  }
   538  
   539  func TestSeekFailure(t *testing.T) {
   540  	_, err := unix.Seek(-1, 0, 0)
   541  	if err == nil {
   542  		t.Fatalf("Seek(-1, 0, 0) did not fail")
   543  	}
   544  	str := err.Error() // used to crash on Linux
   545  	t.Logf("Seek: %v", str)
   546  	if str == "" {
   547  		t.Fatalf("Seek(-1, 0, 0) return error with empty message")
   548  	}
   549  }
   550  
   551  func TestSetsockoptString(t *testing.T) {
   552  	// should not panic on empty string, see issue #31277
   553  	err := unix.SetsockoptString(-1, 0, 0, "")
   554  	if err == nil {
   555  		t.Fatalf("SetsockoptString: did not fail")
   556  	}
   557  }
   558  
   559  func TestDup(t *testing.T) {
   560  	file, err := os.Create(filepath.Join(t.TempDir(), t.Name()))
   561  	if err != nil {
   562  		t.Fatal(err)
   563  	}
   564  	defer file.Close()
   565  	f := int(file.Fd())
   566  
   567  	newFd, err := unix.Dup(f)
   568  	if err != nil {
   569  		t.Fatalf("Dup: %v", err)
   570  	}
   571  
   572  	// Create and reserve a file descriptor.
   573  	// Dup2 automatically closes it before reusing it.
   574  	nullFile, err := os.Open("/dev/null")
   575  	if err != nil {
   576  		t.Fatal(err)
   577  	}
   578  	defer nullFile.Close()
   579  
   580  	dupFd := int(file.Fd())
   581  	err = unix.Dup2(newFd, dupFd)
   582  	if err != nil {
   583  		t.Fatalf("Dup2: %v", err)
   584  	}
   585  	// Keep the dummy file open long enough to not be closed in
   586  	// its finalizer.
   587  	runtime.KeepAlive(nullFile)
   588  
   589  	b1 := []byte("Test123")
   590  	b2 := make([]byte, 7)
   591  	_, err = unix.Write(dupFd, b1)
   592  	if err != nil {
   593  		t.Fatalf("Write to dup2 fd failed: %v", err)
   594  	}
   595  	_, err = unix.Seek(f, 0, 0)
   596  	if err != nil {
   597  		t.Fatalf("Seek failed: %v", err)
   598  	}
   599  	_, err = unix.Read(f, b2)
   600  	if err != nil {
   601  		t.Fatalf("Read back failed: %v", err)
   602  	}
   603  	if string(b1) != string(b2) {
   604  		t.Errorf("Dup: stdout write not in file, expected %v, got %v", string(b1), string(b2))
   605  	}
   606  }
   607  
   608  func TestGetwd(t *testing.T) {
   609  	fd, err := os.Open(".")
   610  	if err != nil {
   611  		t.Fatalf("Open .: %s", err)
   612  	}
   613  	defer fd.Close()
   614  	// Directory list for test. Do not worry if any are symlinks or do not
   615  	// exist on some common unix desktop environments. That will be checked.
   616  	dirs := []string{"/", "/usr/bin", "/etc", "/var", "/opt"}
   617  	oldwd := os.Getenv("PWD")
   618  	for _, d := range dirs {
   619  		// Check whether d exists, is a dir and that d's path does not contain a symlink
   620  		fi, err := os.Stat(d)
   621  		if err != nil || !fi.IsDir() {
   622  			t.Logf("Test dir %s stat error (%v) or not a directory, skipping", d, err)
   623  			continue
   624  		}
   625  		check, err := filepath.EvalSymlinks(d)
   626  		if err != nil || check != d {
   627  			t.Logf("Test dir %s (%s) is symlink or other error (%v), skipping", d, check, err)
   628  			continue
   629  		}
   630  		err = os.Chdir(d)
   631  		if err != nil {
   632  			t.Fatalf("Chdir: %v", err)
   633  		}
   634  		pwd, err := unix.Getwd()
   635  		if err != nil {
   636  			t.Fatalf("Getwd in %s: %s", d, err)
   637  		}
   638  		os.Setenv("PWD", oldwd)
   639  		err = fd.Chdir()
   640  		if err != nil {
   641  			// We changed the current directory and cannot go back.
   642  			// Don't let the tests continue; they'll scribble
   643  			// all over some other directory.
   644  			fmt.Fprintf(os.Stderr, "fchdir back to dot failed: %s\n", err)
   645  			os.Exit(1)
   646  		}
   647  		if pwd != d {
   648  			t.Fatalf("Getwd returned %q want %q", pwd, d)
   649  		}
   650  	}
   651  }
   652  
   653  func TestMkdev(t *testing.T) {
   654  	major := uint32(42)
   655  	minor := uint32(7)
   656  	dev := unix.Mkdev(major, minor)
   657  
   658  	if unix.Major(dev) != major {
   659  		t.Errorf("Major(%#x) == %d, want %d", dev, unix.Major(dev), major)
   660  	}
   661  	if unix.Minor(dev) != minor {
   662  		t.Errorf("Minor(%#x) == %d, want %d", dev, unix.Minor(dev), minor)
   663  	}
   664  }
   665  func TestZosFdToPath(t *testing.T) {
   666  	f, err := os.OpenFile("/tmp", os.O_RDONLY, 0755)
   667  	if err != nil {
   668  		t.Fatalf("Openfile %v", err)
   669  	}
   670  	defer f.Close()
   671  	fd := f.Fd()
   672  
   673  	var res string
   674  	res, err = unix.ZosFdToPath(int(fd))
   675  	if err != nil {
   676  		t.Fatalf("ZosFdToPath %v", err)
   677  	}
   678  	chk := regexp.MustCompile(`^.*/([^\/]+)`).FindStringSubmatch(res)
   679  	lastpath := chk[len(chk)-1]
   680  	if lastpath != "tmp" {
   681  		t.Fatalf("original %s last part of path \"%s\" received, expected \"tmp\" \n", res, lastpath)
   682  	}
   683  }
   684  
   685  // mktmpfifo creates a temporary FIFO and provides a cleanup function.
   686  func mktmpfifo(t *testing.T) (*os.File, func()) {
   687  	err := unix.Mkfifo("fifo", 0666)
   688  	if err != nil {
   689  		t.Fatalf("mktmpfifo: failed to create FIFO: %v", err)
   690  	}
   691  
   692  	f, err := os.OpenFile("fifo", os.O_RDWR, 0666)
   693  	if err != nil {
   694  		os.Remove("fifo")
   695  		t.Fatalf("mktmpfifo: failed to open FIFO: %v", err)
   696  	}
   697  
   698  	return f, func() {
   699  		f.Close()
   700  		os.Remove("fifo")
   701  	}
   702  }
   703  
   704  // utilities taken from os/os_test.go
   705  
   706  func touch(t *testing.T, name string) {
   707  	f, err := os.Create(name)
   708  	if err != nil {
   709  		t.Fatal(err)
   710  	}
   711  	if err := f.Close(); err != nil {
   712  		t.Fatal(err)
   713  	}
   714  }
   715  
   716  // chtmpdir changes the working directory to a new temporary directory and
   717  // sets up a cleanup function. Used when PWD is read-only.
   718  func chtmpdir(t *testing.T) {
   719  	t.Helper()
   720  	oldwd, err := os.Getwd()
   721  	if err != nil {
   722  		t.Fatal(err)
   723  	}
   724  	if err := os.Chdir(t.TempDir()); err != nil {
   725  		t.Fatal(err)
   726  	}
   727  	t.Cleanup(func() {
   728  		if err := os.Chdir(oldwd); err != nil {
   729  			t.Fatal(err)
   730  		}
   731  	})
   732  }
   733  
   734  func TestLegacyMountUnmount(t *testing.T) {
   735  	if euid != 0 {
   736  		t.Skip("euid != 0")
   737  	}
   738  	b2s := func(arr []byte) string {
   739  		var str string
   740  		for i := 0; i < len(arr); i++ {
   741  			if arr[i] == 0 {
   742  				str = string(arr[:i])
   743  				break
   744  			}
   745  		}
   746  		return str
   747  	}
   748  	// use an available fs
   749  	var buffer struct {
   750  		header unix.W_Mnth
   751  		fsinfo [64]unix.W_Mntent
   752  	}
   753  	fs_count, err := unix.W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer)))
   754  	if err != nil {
   755  		t.Fatalf("W_Getmntent_A returns with error: %s", err.Error())
   756  	} else if fs_count == 0 {
   757  		t.Fatalf("W_Getmntent_A returns no entries")
   758  	}
   759  	var fs string
   760  	var fstype string
   761  	var mountpoint string
   762  	var available bool = false
   763  	for i := 0; i < fs_count; i++ {
   764  		err = unix.Unmount(b2s(buffer.fsinfo[i].Mountpoint[:]), unix.MTM_RDWR)
   765  		if err != nil {
   766  			// Unmount and Mount require elevated privilege
   767  			// If test is run without such permission, skip test
   768  			if err == unix.EPERM {
   769  				t.Logf("Permission denied for Unmount. Skipping test (Errno2:  %X)", unix.Errno2())
   770  				return
   771  			} else if err == unix.EBUSY {
   772  				continue
   773  			} else {
   774  				t.Fatalf("Unmount returns with error: %s", err.Error())
   775  			}
   776  		} else {
   777  			available = true
   778  			fs = b2s(buffer.fsinfo[i].Fsname[:])
   779  			fstype = b2s(buffer.fsinfo[i].Fstname[:])
   780  			mountpoint = b2s(buffer.fsinfo[i].Mountpoint[:])
   781  			t.Logf("using file system = %s; fstype = %s and mountpoint = %s\n", fs, fstype, mountpoint)
   782  			break
   783  		}
   784  	}
   785  	if !available {
   786  		t.Fatalf("No filesystem available")
   787  	}
   788  	// test unmount
   789  	buffer.header = unix.W_Mnth{}
   790  	fs_count, err = unix.W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer)))
   791  	if err != nil {
   792  		t.Fatalf("W_Getmntent_A returns with error: %s", err.Error())
   793  	}
   794  	for i := 0; i < fs_count; i++ {
   795  		if b2s(buffer.fsinfo[i].Fsname[:]) == fs {
   796  			t.Fatalf("File system found after unmount")
   797  		}
   798  	}
   799  	// test mount
   800  	err = unix.Mount(fs, mountpoint, fstype, unix.MTM_RDWR, "")
   801  	if err != nil {
   802  		t.Fatalf("Mount returns with error: %s", err.Error())
   803  	}
   804  	buffer.header = unix.W_Mnth{}
   805  	fs_count, err = unix.W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer)))
   806  	if err != nil {
   807  		t.Fatalf("W_Getmntent_A returns with error: %s", err.Error())
   808  	}
   809  	fs_mounted := false
   810  	for i := 0; i < fs_count; i++ {
   811  		if b2s(buffer.fsinfo[i].Fsname[:]) == fs && b2s(buffer.fsinfo[i].Mountpoint[:]) == mountpoint {
   812  			fs_mounted = true
   813  		}
   814  	}
   815  	if !fs_mounted {
   816  		t.Fatalf("%s not mounted after Mount()", fs)
   817  	}
   818  }
   819  
   820  func TestChroot(t *testing.T) {
   821  	if euid != 0 {
   822  		t.Skip("euid != 0")
   823  	}
   824  	// create temp dir and tempfile 1
   825  	tempDir := t.TempDir()
   826  	f, err := os.CreateTemp(tempDir, "chroot_test_file")
   827  	if err != nil {
   828  		t.Fatalf("TempFile: %s", err.Error())
   829  	}
   830  	defer f.Close()
   831  
   832  	// chroot temp dir
   833  	err = unix.Chroot(tempDir)
   834  	// Chroot requires elevated privilege
   835  	// If test is run without such permission, skip test
   836  	if err == unix.EPERM {
   837  		t.Logf("Denied permission for Chroot. Skipping test (Errno2:  %X)", unix.Errno2())
   838  		return
   839  	} else if err != nil {
   840  		t.Fatalf("Chroot: %s", err.Error())
   841  	}
   842  	// check if tempDir contains test file
   843  	files, err := os.ReadDir("/")
   844  	if err != nil {
   845  		t.Fatalf("ReadDir: %s", err.Error())
   846  	}
   847  	found := false
   848  	for _, file := range files {
   849  		if file.Name() == filepath.Base(f.Name()) {
   850  			found = true
   851  			break
   852  		}
   853  	}
   854  	if !found {
   855  		t.Fatalf("Temp file not found in temp dir")
   856  	}
   857  }
   858  
   859  func TestFlock(t *testing.T) {
   860  	if v, r := zosLeVersion(); v <= 2 && r <= 4 {
   861  		t.Skipf("New flock can't be used in %d.%d < 2.5. Run TestLegacyFlock", v, r)
   862  	}
   863  
   864  	const (
   865  		SUCCESS = iota
   866  		BLOCKED
   867  	)
   868  
   869  	if os.Getenv("TEST_FLOCK_HELPER") == "1" {
   870  		defer os.Exit(0)
   871  		if len(os.Args) != 4 {
   872  			log.Fatal("bad argument")
   873  		}
   874  		mode, err := strconv.Atoi(os.Args[2])
   875  		if err != nil {
   876  			log.Fatalf("%s is invalid: %s", os.Args[2], err)
   877  		}
   878  		filename := os.Args[3]
   879  		f, err := os.OpenFile(filename, os.O_RDWR, 0755)
   880  		if err != nil {
   881  			log.Fatalf("%s", err.Error())
   882  		}
   883  		defer f.Close()
   884  
   885  		go func() {
   886  			// timeout
   887  			time.Sleep(5 * time.Second)
   888  			unix.Flock(int(f.Fd()), unix.LOCK_UN)
   889  			fmt.Print(BLOCKED)
   890  			os.Exit(1)
   891  		}()
   892  
   893  		err = unix.Flock(int(f.Fd()), mode)
   894  		if err == unix.EWOULDBLOCK {
   895  			fmt.Print(int(unix.EWOULDBLOCK))
   896  			os.Exit(1)
   897  		}
   898  		if err != nil {
   899  			log.Fatal(err)
   900  		}
   901  		defer unix.Flock(int(f.Fd()), unix.LOCK_UN)
   902  		fmt.Print(0)
   903  		return
   904  	}
   905  
   906  	f, err := os.Create(filepath.Join(t.TempDir(), "flock_test_file"))
   907  	if err != nil {
   908  		t.Fatalf("TempFile: %s\n", err)
   909  	}
   910  	defer f.Close()
   911  	fd := int(f.Fd())
   912  
   913  	testCases := []struct {
   914  		name     string
   915  		fd       int
   916  		p1modes  []int
   917  		p2mode   int
   918  		expected syscall.Errno
   919  	}{
   920  		{"Invalid fd", -1, []int{unix.LOCK_SH}, unix.LOCK_SH, unix.EBADF},
   921  		{"Invalid mode", fd, []int{unix.LOCK_EX | unix.LOCK_SH}, unix.LOCK_SH, unix.EINVAL},
   922  		{"EX-EX", fd, []int{unix.LOCK_SH, unix.LOCK_EX}, unix.LOCK_EX, BLOCKED},
   923  		{"EX-SH", fd, []int{unix.LOCK_SH, unix.LOCK_EX}, unix.LOCK_SH, BLOCKED},
   924  		{"SH-EX", fd, []int{unix.LOCK_EX, unix.LOCK_SH}, unix.LOCK_EX, BLOCKED},
   925  		{"SH-SH", fd, []int{unix.LOCK_EX, unix.LOCK_SH}, unix.LOCK_SH, SUCCESS},
   926  		{"EX-EXNB", fd, []int{unix.LOCK_SH, unix.LOCK_EX}, unix.LOCK_EX | unix.LOCK_NB, unix.EWOULDBLOCK},
   927  		{"EX-SHNB", fd, []int{unix.LOCK_SH, unix.LOCK_EX}, unix.LOCK_SH | unix.LOCK_NB, unix.EWOULDBLOCK},
   928  		{"SH-SHNB", fd, []int{unix.LOCK_EX, unix.LOCK_SH}, unix.LOCK_EX | unix.LOCK_NB, unix.EWOULDBLOCK},
   929  		{"SH-SHNB", fd, []int{unix.LOCK_EX, unix.LOCK_SH}, unix.LOCK_SH | unix.LOCK_NB, SUCCESS},
   930  	}
   931  	// testcase:
   932  	for _, c := range testCases {
   933  		t.Run(c.name, func(t *testing.T) {
   934  			for _, mode := range c.p1modes {
   935  				err = unix.Flock(c.fd, mode)
   936  				if err == c.expected {
   937  					return
   938  				}
   939  				if err != nil {
   940  					t.Fatalf("failed to acquire Flock with mode(%d): %s\n", mode, err)
   941  				}
   942  			}
   943  
   944  			p2status := BLOCKED
   945  			done := make(chan bool)
   946  			execP2 := func(isBlock bool) {
   947  				exe, err := os.Executable()
   948  				if err != nil {
   949  					t.Fatal(err)
   950  				}
   951  				cmd := exec.Command(exe, "-test.run=^TestFlock$", strconv.Itoa(c.p2mode), f.Name())
   952  				cmd.Env = append(os.Environ(), "TEST_FLOCK_HELPER=1")
   953  				out, _ := cmd.CombinedOutput()
   954  				if p2status, err = strconv.Atoi(string(out)); err != nil {
   955  					log.Fatalf("p2status is not valid: %s\n", err)
   956  				}
   957  				if isBlock {
   958  					done <- true
   959  				}
   960  			}
   961  
   962  			if c.expected == BLOCKED {
   963  				go execP2(true)
   964  				<-done
   965  			} else {
   966  				execP2(false)
   967  			}
   968  
   969  			if p2status != int(c.expected) {
   970  				unix.Flock(c.fd, unix.LOCK_UN)
   971  				t.Fatalf("expected %d, actual %d\n", c.expected, p2status)
   972  			}
   973  			unix.Flock(c.fd, unix.LOCK_UN)
   974  		})
   975  
   976  	}
   977  }
   978  
   979  func TestLegacyFlock(t *testing.T) {
   980  	if v, r := zosLeVersion(); v > 2 || (v == 2 && r > 4) {
   981  		t.Skipf("Legacy flock can't be used in %d.%d > 2.4. Run TestFlock", v, r)
   982  	}
   983  	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
   984  		defer os.Exit(0)
   985  		if len(os.Args) != 3 {
   986  			fmt.Printf("bad argument")
   987  			return
   988  		}
   989  		fn := os.Args[2]
   990  		f, err := os.OpenFile(fn, os.O_RDWR, 0755)
   991  		if err != nil {
   992  			fmt.Printf("%s", err.Error())
   993  			return
   994  		}
   995  		err = unix.Flock(int(f.Fd()), unix.LOCK_EX|unix.LOCK_NB)
   996  		// if the lock we are trying should be locked, ignore EAGAIN error
   997  		// otherwise, report all errors
   998  		if err != nil && err != unix.EAGAIN {
   999  			fmt.Printf("%s", err.Error())
  1000  		}
  1001  	} else {
  1002  		// create tempfile 1
  1003  		f, err := os.Create(filepath.Join(t.TempDir(), "flock_test_file"))
  1004  		if err != nil {
  1005  			t.Fatalf("TempFile: %s", err.Error())
  1006  		}
  1007  		defer f.Close()
  1008  
  1009  		fd := int(f.Fd())
  1010  
  1011  		/* Test Case 1
  1012  		 * Try acquiring an occupied lock from another process
  1013  		 */
  1014  		err = unix.Flock(fd, unix.LOCK_EX)
  1015  		if err != nil {
  1016  			t.Fatalf("Flock: %s", err.Error())
  1017  		}
  1018  		exe, err := os.Executable()
  1019  		if err != nil {
  1020  			t.Fatal(err)
  1021  		}
  1022  		cmd := exec.Command(exe, "-test.run=TestLegacyFlock", f.Name())
  1023  		cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1")
  1024  		out, err := cmd.CombinedOutput()
  1025  		if len(out) > 0 || err != nil {
  1026  			t.Fatalf("child process: %q, %v", out, err)
  1027  		}
  1028  		err = unix.Flock(fd, unix.LOCK_UN)
  1029  		if err != nil {
  1030  			t.Fatalf("Flock: %s", err.Error())
  1031  		}
  1032  
  1033  		/* Test Case 2
  1034  		 * Try locking with Flock and FcntlFlock for same file
  1035  		 */
  1036  		err = unix.Flock(fd, unix.LOCK_EX)
  1037  		if err != nil {
  1038  			t.Fatalf("Flock: %s", err.Error())
  1039  		}
  1040  		flock := unix.Flock_t{
  1041  			Type:   int16(unix.F_WRLCK),
  1042  			Whence: int16(0),
  1043  			Start:  int64(0),
  1044  			Len:    int64(0),
  1045  			Pid:    int32(unix.Getppid()),
  1046  		}
  1047  		err = unix.FcntlFlock(f.Fd(), unix.F_SETLK, &flock)
  1048  		if err != nil {
  1049  			t.Fatalf("FcntlFlock: %s", err.Error())
  1050  		}
  1051  	}
  1052  }
  1053  
  1054  func TestSelect(t *testing.T) {
  1055  	for {
  1056  		n, err := unix.Select(0, nil, nil, nil, &unix.Timeval{Sec: 0, Usec: 0})
  1057  		if err == unix.EINTR {
  1058  			t.Logf("Select interrupted")
  1059  			continue
  1060  		} else if err != nil {
  1061  			t.Fatalf("Select: %v", err)
  1062  		}
  1063  		if n != 0 {
  1064  			t.Fatalf("Select: got %v ready file descriptors, expected 0", n)
  1065  		}
  1066  		break
  1067  	}
  1068  
  1069  	dur := 250 * time.Millisecond
  1070  	var took time.Duration
  1071  	for {
  1072  		// On some platforms (e.g. Linux), the passed-in timeval is
  1073  		// updated by select(2). Make sure to reset to the full duration
  1074  		// in case of an EINTR.
  1075  		tv := unix.NsecToTimeval(int64(dur))
  1076  		start := time.Now()
  1077  		n, err := unix.Select(0, nil, nil, nil, &tv)
  1078  		took = time.Since(start)
  1079  		if err == unix.EINTR {
  1080  			t.Logf("Select interrupted after %v", took)
  1081  			continue
  1082  		} else if err != nil {
  1083  			t.Fatalf("Select: %v", err)
  1084  		}
  1085  		if n != 0 {
  1086  			t.Fatalf("Select: got %v ready file descriptors, expected 0", n)
  1087  		}
  1088  		break
  1089  	}
  1090  
  1091  	// On some BSDs the actual timeout might also be slightly less than the requested.
  1092  	// Add an acceptable margin to avoid flaky tests.
  1093  	if took < dur*2/3 {
  1094  		t.Errorf("Select: got %v timeout, expected at least %v", took, dur)
  1095  	}
  1096  
  1097  	rr, ww, err := os.Pipe()
  1098  	if err != nil {
  1099  		t.Fatal(err)
  1100  	}
  1101  	defer rr.Close()
  1102  	defer ww.Close()
  1103  
  1104  	if _, err := ww.Write([]byte("HELLO GOPHER")); err != nil {
  1105  		t.Fatal(err)
  1106  	}
  1107  
  1108  	rFdSet := &unix.FdSet{}
  1109  	fd := int(rr.Fd())
  1110  	rFdSet.Set(fd)
  1111  
  1112  	for {
  1113  		n, err := unix.Select(fd+1, rFdSet, nil, nil, nil)
  1114  		if err == unix.EINTR {
  1115  			t.Log("Select interrupted")
  1116  			continue
  1117  		} else if err != nil {
  1118  			t.Fatalf("Select: %v", err)
  1119  		}
  1120  		if n != 1 {
  1121  			t.Fatalf("Select: got %v ready file descriptors, expected 1", n)
  1122  		}
  1123  		break
  1124  	}
  1125  }
  1126  
  1127  func TestUnixCredentials(t *testing.T) {
  1128  	var ucred syscall.Ucred
  1129  	if os.Getuid() != 0 {
  1130  		ucred.Pid = int32(os.Getpid())
  1131  		ucred.Uid = 0
  1132  		ucred.Gid = 0
  1133  	}
  1134  
  1135  	ucred.Pid = int32(os.Getpid())
  1136  	ucred.Uid = uint32(os.Getuid())
  1137  	ucred.Gid = uint32(os.Getgid())
  1138  	oob := syscall.UnixCredentials(&ucred)
  1139  
  1140  	// On SOCK_STREAM, this is internally going to send a dummy byte
  1141  	scm, err := syscall.ParseSocketControlMessage(oob)
  1142  	if err != nil {
  1143  		t.Fatalf("ParseSocketControlMessage: %v", err)
  1144  	}
  1145  	newUcred, err := syscall.ParseUnixCredentials(&scm[0])
  1146  	if err != nil {
  1147  		t.Fatalf("ParseUnixCredentials: %v", err)
  1148  	}
  1149  	if *newUcred != ucred {
  1150  		t.Fatalf("ParseUnixCredentials = %+v, want %+v", newUcred, ucred)
  1151  	}
  1152  }
  1153  
  1154  func TestFutimes(t *testing.T) {
  1155  	// Create temp dir and file
  1156  	f, err := os.Create(filepath.Join(t.TempDir(), "futimes_test_file"))
  1157  	if err != nil {
  1158  		t.Fatalf("TempFile: %s", err.Error())
  1159  	}
  1160  	defer f.Close()
  1161  
  1162  	fd := int(f.Fd())
  1163  
  1164  	// Set mod time to newTime
  1165  	newTime := time.Date(2001, time.Month(2), 15, 7, 7, 7, 0, time.UTC)
  1166  	err = unix.Futimes(
  1167  		fd,
  1168  		[]unix.Timeval{
  1169  			unix.Timeval{newTime.Unix(), 0},
  1170  			unix.Timeval{newTime.Unix(), 0},
  1171  		})
  1172  	if err != nil {
  1173  		t.Fatalf("TestFutimes: %v", err)
  1174  	}
  1175  
  1176  	// Compare mod time
  1177  	stats, err := f.Stat()
  1178  	if err != nil {
  1179  		t.Fatalf("Stat: %v", err)
  1180  	}
  1181  
  1182  	modTime := stats.ModTime()
  1183  	if modTime.UTC() != newTime {
  1184  		t.Fatalf("TestFutimes: modTime = %v, want %v", modTime.UTC(), newTime)
  1185  	}
  1186  }
  1187  
  1188  func TestLutimes(t *testing.T) {
  1189  	// Create temp dir and file
  1190  	tempDir := t.TempDir()
  1191  	f, err := os.CreateTemp(tempDir, "lutimes_test_file")
  1192  	if err != nil {
  1193  		t.Fatalf("TempFile: %s", err.Error())
  1194  	}
  1195  	defer f.Close()
  1196  
  1197  	symlinkPath := tempDir + "/test_symlink"
  1198  	err = os.Symlink(f.Name(), symlinkPath)
  1199  	if err != nil {
  1200  		t.Fatalf("Symlink: %v", err)
  1201  	}
  1202  
  1203  	// Set mod time to newTime
  1204  	newTime := time.Date(2001, time.Month(2), 15, 7, 7, 7, 0, time.UTC)
  1205  	err = unix.Lutimes(
  1206  		symlinkPath,
  1207  		[]unix.Timeval{
  1208  			unix.Timeval{newTime.Unix(), 0},
  1209  			unix.Timeval{newTime.Unix(), 0},
  1210  		})
  1211  	if err != nil {
  1212  		t.Fatalf("TestLutimes: %v", err)
  1213  	}
  1214  
  1215  	// Compare mod time
  1216  	stats, err := os.Lstat(symlinkPath)
  1217  	if err != nil {
  1218  		t.Fatalf("Lstat: %v", err)
  1219  	}
  1220  
  1221  	modTime := stats.ModTime()
  1222  	if modTime.UTC() != newTime {
  1223  		t.Fatalf("TestLutimes: modTime = %v, want %v", modTime.UTC(), newTime)
  1224  	}
  1225  
  1226  }
  1227  
  1228  func TestDirfd(t *testing.T) {
  1229  	// Create temporary directory
  1230  	tempDir := t.TempDir()
  1231  
  1232  	f, err := os.CreateTemp(tempDir, "dirfd_test_file")
  1233  	if err != nil {
  1234  		t.Fatalf("TempFile: %v", err)
  1235  	}
  1236  	defer f.Close()
  1237  
  1238  	// Open temp dir and get stream
  1239  	dirStream, err := unix.Opendir(tempDir)
  1240  	if err != nil {
  1241  		t.Fatalf("Opendir: %v", err)
  1242  	}
  1243  	defer unix.Closedir(dirStream)
  1244  
  1245  	// Get fd from stream
  1246  	dirFd, err := unix.Dirfd(dirStream)
  1247  	if err != nil {
  1248  		t.Fatalf("Dirfd: %v", err)
  1249  	}
  1250  	if dirFd < 0 {
  1251  		t.Fatalf("Dirfd: fd < 0, (fd = %v)", dirFd)
  1252  	}
  1253  
  1254  	oldwd, err := os.Getwd()
  1255  	if err != nil {
  1256  		t.Fatalf("Getwd: %v", err)
  1257  	}
  1258  	defer os.Chdir(oldwd)
  1259  
  1260  	// Change dir to fd and get path
  1261  	err = unix.Fchdir(dirFd)
  1262  	if err != nil {
  1263  		t.Fatalf("Fchdir: %v", err)
  1264  	}
  1265  	path, err := os.Getwd()
  1266  	if err != nil {
  1267  		t.Fatalf("Getwd: %v", err)
  1268  	}
  1269  
  1270  	pathInfo, err := os.Lstat(path)
  1271  	if err != nil {
  1272  		t.Fatalf("os.Stat: %v", err)
  1273  	}
  1274  	tempDirInfo2, err := os.Lstat(tempDir)
  1275  	if err != nil {
  1276  		t.Fatalf("os.Stat: %v", err)
  1277  	}
  1278  	// Perform Test
  1279  	if !os.SameFile(pathInfo, tempDirInfo2) {
  1280  		t.Fatalf("Dirfd: expected working directory to be %v, actually: %v", tempDir, path)
  1281  	}
  1282  }
  1283  
  1284  func TestEpollCreate(t *testing.T) {
  1285  	if BypassTestOnUntil("zoscan59", "2024-04-01T12:45:21.123Z") {
  1286  		t.Skip("skipping on zoscan59 until 2024-04-01")
  1287  	}
  1288  	efd, err := unix.EpollCreate(1)
  1289  	if err != nil {
  1290  		t.Fatalf("EpollCreate: %v", err)
  1291  	}
  1292  	defer unix.Close(efd)
  1293  }
  1294  
  1295  func TestEpollCreate1(t *testing.T) {
  1296  	if BypassTestOnUntil("zoscan59", "2024-04-01T12:45:21.123Z") {
  1297  		t.Skip("skipping on zoscan59 until 2024-04-01")
  1298  	}
  1299  	efd, err := unix.EpollCreate1(0)
  1300  	if err != nil {
  1301  		t.Fatalf("EpollCreate1: %v", err)
  1302  	}
  1303  	unix.Close(efd)
  1304  }
  1305  
  1306  func TestEpoll(t *testing.T) {
  1307  	if BypassTestOnUntil("zoscan59", "2024-04-01T12:45:21.123Z") {
  1308  		t.Skip("skipping on zoscan59 until 2024-04-01")
  1309  	}
  1310  	efd, err := unix.EpollCreate1(0) // no CLOEXEC equivalent on z/OS
  1311  	if err != nil {
  1312  		t.Fatalf("EpollCreate1: %v", err)
  1313  	}
  1314  	// no need to defer a close on efd, as it's not a real file descriptor on zos
  1315  
  1316  	r, w, err := os.Pipe()
  1317  	if err != nil {
  1318  		t.Fatal(err)
  1319  	}
  1320  	defer r.Close()
  1321  	defer w.Close()
  1322  
  1323  	fd := int(r.Fd())
  1324  	ev := unix.EpollEvent{Events: unix.EPOLLIN, Fd: int32(fd)}
  1325  
  1326  	err = unix.EpollCtl(efd, unix.EPOLL_CTL_ADD, fd, &ev)
  1327  	if err != nil {
  1328  		t.Fatalf("EpollCtl: %v", err)
  1329  	}
  1330  
  1331  	if _, err := w.Write([]byte("HELLO GOPHER")); err != nil {
  1332  		t.Fatal(err)
  1333  	}
  1334  
  1335  	events := make([]unix.EpollEvent, 128)
  1336  	n, err := unix.EpollWait(efd, events, 1)
  1337  	if err != nil {
  1338  		t.Fatalf("EpollWait: %v", err)
  1339  	}
  1340  
  1341  	if n != 1 {
  1342  		t.Errorf("EpollWait: wrong number of events: got %v, expected 1", n)
  1343  	}
  1344  
  1345  	got := int(events[0].Fd)
  1346  	if got != fd {
  1347  		t.Errorf("EpollWait: wrong Fd in event: got %v, expected %v", got, fd)
  1348  	}
  1349  
  1350  	if events[0].Events&unix.EPOLLIN == 0 {
  1351  		t.Errorf("Expected EPOLLIN flag to be set, got %b", events[0].Events)
  1352  	}
  1353  
  1354  	x := 0
  1355  	n, err = unix.EpollPwait(efd, events, 1, &x)
  1356  	if err != nil {
  1357  		t.Fatalf("EpollPwait: %v", err)
  1358  	}
  1359  }
  1360  
  1361  func TestEventfd(t *testing.T) {
  1362  	fd, err := unix.Eventfd(0, 0)
  1363  	if err != nil {
  1364  		t.Fatalf("Eventfd: %v", err)
  1365  	}
  1366  	if fd <= 2 {
  1367  		t.Fatalf("Eventfd: fd <= 2, got: %d", fd)
  1368  	}
  1369  }
  1370  
  1371  func TestEventfdSemaphore(t *testing.T) {
  1372  	efd, err := unix.Eventfd(1, unix.EFD_SEMAPHORE|unix.EFD_NONBLOCK|unix.EFD_CLOEXEC)
  1373  	if err != nil {
  1374  		t.Fatalf("Eventfd: %v", err)
  1375  	}
  1376  
  1377  	writeBytes := make([]byte, 8)
  1378  	writeBytes[7] = 0x4
  1379  	n, err := unix.Write(efd, writeBytes)
  1380  	if err != nil {
  1381  		t.Fatalf("Write: %v", err)
  1382  	}
  1383  	if n != 8 {
  1384  		t.Fatalf("Write: only wrote %d bytes, wanted 8", n)
  1385  	}
  1386  
  1387  	for i := 0; i < 5; i++ {
  1388  		readBytes := make([]byte, 8)
  1389  		n, err := unix.Read(efd, readBytes)
  1390  		if err != nil {
  1391  			t.Fatalf("Read: %v", err)
  1392  		}
  1393  		if n != 8 {
  1394  			t.Fatalf("Read: only read %d bytes, wanted 8", n)
  1395  		}
  1396  	}
  1397  	readBytes := make([]byte, 8)
  1398  	n, err = unix.Read(efd, readBytes)
  1399  	if err == nil || err.Error() != "EDC5112I Resource temporarily unavailable." {
  1400  		t.Fatalf("Read: expected error \"EDC5112I Resource temporarily unavailable.\", got %v", err)
  1401  	}
  1402  	if n != -1 {
  1403  		t.Fatalf("Read: expected error code -1, got %d", n)
  1404  	}
  1405  	if readBytes[7] != 0 {
  1406  		t.Fatalf("Read: expected return of 0, got %d", readBytes[7])
  1407  	}
  1408  }
  1409  
  1410  func TestStatfs(t *testing.T) {
  1411  	// Create temporary directory
  1412  	tempDir := t.TempDir()
  1413  
  1414  	var stat unix.Statfs_t
  1415  	if err := unix.Statfs(tempDir, &stat); err != nil {
  1416  		t.Fatalf("Stafs: %v", err)
  1417  	}
  1418  
  1419  	if stat.Files == 0 {
  1420  		t.Fatalf("Statfs: expected files > 0")
  1421  	}
  1422  }
  1423  
  1424  func TestStatfsProc(t *testing.T) {
  1425  	// Create temporary directory
  1426  
  1427  	if _, err := os.Stat("/proc/self"); errors.Is(err, os.ErrNotExist) {
  1428  		t.Skip("/proc/self is not exist skipping the test")
  1429  	}
  1430  
  1431  	var stat unix.Statfs_t
  1432  	if err := unix.Statfs("/proc/self/ns", &stat); err != nil {
  1433  		t.Fatalf("Stafs: %v", err)
  1434  	}
  1435  
  1436  	if stat.Type != unix.PROC_SUPER_MAGIC {
  1437  		t.Fatalf("Statfs: expected files > 0")
  1438  	}
  1439  }
  1440  
  1441  func TestFstatfs(t *testing.T) {
  1442  	// Create temporary directory
  1443  	file, err := os.Create(filepath.Join(t.TempDir(), "fstatfs_test_file"))
  1444  	if err != nil {
  1445  		t.Fatalf("TempFile: %v", err)
  1446  	}
  1447  	defer file.Close()
  1448  
  1449  	fd := int(file.Fd())
  1450  
  1451  	var stat unix.Statfs_t
  1452  	if err = unix.Fstatfs(fd, &stat); err != nil {
  1453  		t.Fatalf("Stafs: %v", err)
  1454  	}
  1455  
  1456  	if stat.Files == 0 {
  1457  		t.Fatalf("Statfs: expected files > 0")
  1458  	}
  1459  }
  1460  
  1461  func TestFdatasync(t *testing.T) {
  1462  	t.Skip("FAIL: Known failure, would hang if not skipped")
  1463  	// Create temporary directory
  1464  	file, err := os.Create(filepath.Join(t.TempDir(), "fdatasync_test_file"))
  1465  	if err != nil {
  1466  		t.Fatalf("TempFile: %v", err)
  1467  	}
  1468  	file.Close()
  1469  
  1470  	fd := int(file.Fd())
  1471  
  1472  	var stat1 unix.Stat_t
  1473  	if err = unix.Fstat(fd, &stat1); err != nil {
  1474  		t.Fatalf("Fstat: %v", err)
  1475  	}
  1476  
  1477  	time.Sleep(1 * time.Second)
  1478  	if _, err := unix.Write(fd, []byte("Test string")); err != nil {
  1479  		t.Fatalf("Write: %v", err)
  1480  	}
  1481  
  1482  	var stat2 unix.Stat_t
  1483  	if err = unix.Fstat(fd, &stat2); err != nil {
  1484  		t.Fatalf("Fstat: %v", err)
  1485  	}
  1486  
  1487  	time.Sleep(1 * time.Second)
  1488  	if err = unix.Fdatasync(fd); err != nil {
  1489  		t.Fatalf("Fdatasync: %v", err)
  1490  	}
  1491  
  1492  	var stat3 unix.Stat_t
  1493  	if err = unix.Fstat(fd, &stat3); err != nil {
  1494  		t.Fatalf("Fstat: %v", err)
  1495  	}
  1496  
  1497  	if stat2.Mtim != stat3.Mtim {
  1498  		t.Fatalf("Fdatasync: Modify times do not match. Wanted %v, got %v", stat2.Mtim, stat3.Mtim)
  1499  	}
  1500  }
  1501  
  1502  func TestReadDirent(t *testing.T) {
  1503  	// Create temporary directory and files
  1504  	tempDir := t.TempDir()
  1505  
  1506  	f1, err := os.CreateTemp(tempDir, "ReadDirent_test_file")
  1507  	if err != nil {
  1508  		t.Fatalf("TempFile: %v", err)
  1509  	}
  1510  	defer f1.Close()
  1511  	f2, err := os.CreateTemp(tempDir, "ReadDirent_test_file")
  1512  	if err != nil {
  1513  		t.Fatalf("TempFile: %v", err)
  1514  	}
  1515  	defer f2.Close()
  1516  
  1517  	tempSubDir, err := os.MkdirTemp(tempDir, "ReadDirent_SubDir")
  1518  	if err != nil {
  1519  		t.Fatalf("TempDir: %v", err)
  1520  	}
  1521  	f3, err := os.CreateTemp(tempSubDir, "ReadDirent_subDir_test_file")
  1522  	if err != nil {
  1523  		t.Fatalf("TempFile: %v", err)
  1524  	}
  1525  	defer f3.Close()
  1526  
  1527  	// Get fd of tempDir
  1528  	dir, err := os.Open(tempDir)
  1529  	if err != nil {
  1530  		t.Fatalf("Open: %v", err)
  1531  	}
  1532  	defer dir.Close()
  1533  
  1534  	fd := int(dir.Fd())
  1535  
  1536  	// Run Getdirentries
  1537  	buf := make([]byte, 2048)
  1538  	n, err := unix.ReadDirent(fd, buf)
  1539  	if err != nil {
  1540  		t.Fatalf("ReadDirent: %v", err)
  1541  	}
  1542  	if n == 0 {
  1543  		t.Fatalf("ReadDirent: 0 bytes read")
  1544  	}
  1545  
  1546  	names := make([]string, 0)
  1547  	consumed, count, _ := unix.ParseDirent(buf, 100, names)
  1548  	if consumed == 0 {
  1549  		t.Fatalf("ParseDirent: consumed 0 bytes")
  1550  	}
  1551  	if count != 3 {
  1552  		t.Fatalf("ParseDirent: only recorded %d entries, expected 3", count)
  1553  	}
  1554  }
  1555  
  1556  func TestPipe2(t *testing.T) {
  1557  	var p [2]int
  1558  	err := unix.Pipe2(p[:], unix.O_CLOEXEC)
  1559  	if err != nil {
  1560  		t.Fatalf("Pipe2: %v", err)
  1561  	}
  1562  
  1563  	r, w := int(p[0]), int(p[1])
  1564  
  1565  	n1, err := unix.Write(w, []byte("Testing pipe2!"))
  1566  	if err != nil {
  1567  		t.Fatalf("Write: %v", err)
  1568  	}
  1569  
  1570  	buf := make([]byte, 256)
  1571  	n2, err := unix.Read(r, buf[:])
  1572  	if err != nil {
  1573  		t.Fatalf("Read: %v", err)
  1574  	}
  1575  
  1576  	if n1 != n2 {
  1577  		t.Fatalf("Pipe2: bytes read != bytes written. Wrote %d, read %d", n1, n2)
  1578  	}
  1579  }
  1580  
  1581  func TestInotify(t *testing.T) {
  1582  	// Driver func to try and capture all possible events
  1583  	t.Run("IN_ACCESS", inotify_access)
  1584  	t.Run("IN_ATTRIB", inotify_attrib)
  1585  	t.Run("IN_CLOSE_WRITE", inotify_close_write)
  1586  	t.Run("IN_CLOSE_NOWRITE", inotify_close_nowrite)
  1587  	t.Run("IN_CREATE", inotify_create)
  1588  	t.Run("IN_DELETE", inotify_delete)
  1589  	t.Run("IN_DELETE_SELF", inotify_delete_self)
  1590  	t.Run("IN_MODIFY", inotify_modify)
  1591  	t.Run("IN_MOVE_SELF", inotify_move_self)
  1592  	t.Run("IN_MOVED_FROM", inotify_moved_from)
  1593  	t.Run("IN_MOVED_TO", inotify_moved_to)
  1594  	t.Run("IN_OPEN", inotify_open)
  1595  }
  1596  
  1597  func inotify_access(t *testing.T) {
  1598  	// Create temporary files
  1599  	tempDir := t.TempDir()
  1600  	tempFile, err := os.Create(filepath.Join(tempDir, "inotify_access_test_file"))
  1601  	if err != nil {
  1602  		t.Fatalf("TempFile: %v", err)
  1603  	}
  1604  	defer tempFile.Close()
  1605  
  1606  	// Setup iNotify
  1607  	infd, err := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
  1608  	if err != nil {
  1609  		t.Fatalf("InotifyInit1: %v", err)
  1610  	}
  1611  
  1612  	wd, err := unix.InotifyAddWatch(infd, tempFile.Name(), unix.IN_ACCESS)
  1613  	if err != nil {
  1614  		t.Fatalf("InotifyAddWatch: %v", err)
  1615  	}
  1616  
  1617  	// Trigger Event
  1618  	n, err := tempFile.Write([]byte("Writing before reading"))
  1619  	if err != nil {
  1620  		t.Fatalf("Write: %v", err)
  1621  	}
  1622  	if n <= 0 {
  1623  		t.Fatalf("Did not write any data")
  1624  	}
  1625  	tempFile.Seek(0, 0)
  1626  
  1627  	buf := make([]byte, 64)
  1628  	n, err = tempFile.Read(buf)
  1629  	if err != nil {
  1630  		t.Fatalf("Read: %v", err)
  1631  	}
  1632  	if n <= 0 {
  1633  		t.Fatalf("Did not read any data")
  1634  	}
  1635  
  1636  	// Expect event
  1637  	buf = make([]byte, unix.SizeofInotifyEvent)
  1638  	n, err = unix.Read(infd, buf[:])
  1639  	if n == -1 {
  1640  		t.Fatalf("No event was read from the iNotify fd")
  1641  	}
  1642  
  1643  	// Remove Watch
  1644  	if _, err = unix.InotifyRmWatch(infd, uint32(wd)); err != nil {
  1645  		t.Fatalf("InotifyRmWatch: %v", err)
  1646  	}
  1647  }
  1648  
  1649  func inotify_attrib(t *testing.T) {
  1650  	// Create temporary files
  1651  	tempDir := t.TempDir()
  1652  	tempFile, err := os.Create(filepath.Join(tempDir, "inotify_attrib_test_file"))
  1653  	if err != nil {
  1654  		t.Fatalf("TempFile: %v", err)
  1655  	}
  1656  	defer tempFile.Close()
  1657  
  1658  	// Setup iNotify
  1659  	infd, err := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
  1660  	if err != nil {
  1661  		t.Fatalf("InotifyInit1: %v", err)
  1662  	}
  1663  	defer unix.Close(infd)
  1664  
  1665  	wd, err := unix.InotifyAddWatch(infd, tempFile.Name(), unix.IN_ATTRIB)
  1666  	if err != nil {
  1667  		t.Fatalf("InotifyAddWatch: %v", err)
  1668  	}
  1669  
  1670  	// Trigger Event
  1671  	if err = tempFile.Chmod(0777); err != nil {
  1672  		t.Fatalf("Chmod: %v", err)
  1673  	}
  1674  
  1675  	// Expect event
  1676  	buf := make([]byte, unix.SizeofInotifyEvent)
  1677  	n, err := unix.Read(infd, buf[:])
  1678  	if n == -1 {
  1679  		t.Fatalf("No event was read from the iNotify fd")
  1680  	}
  1681  
  1682  	// Remove Watch
  1683  	if _, err = unix.InotifyRmWatch(infd, uint32(wd)); err != nil {
  1684  		t.Fatalf("InotifyRmWatch: %v", err)
  1685  	}
  1686  }
  1687  
  1688  func inotify_close_write(t *testing.T) {
  1689  	// Create temporary files
  1690  	tempDir := t.TempDir()
  1691  	tempFile, err := os.Create(filepath.Join(tempDir, "inotify_close_write_test_file"))
  1692  	if err != nil {
  1693  		t.Fatalf("TempFile: %v", err)
  1694  	}
  1695  	// File closed in test later
  1696  
  1697  	// Setup iNotify
  1698  	infd, err := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
  1699  	if err != nil {
  1700  		t.Fatalf("InotifyInit1: %v", err)
  1701  	}
  1702  
  1703  	wd, err := unix.InotifyAddWatch(infd, tempFile.Name(), unix.IN_CLOSE_WRITE)
  1704  	if err != nil {
  1705  		t.Fatalf("InotifyAddWatch: %v", err)
  1706  	}
  1707  
  1708  	// Trigger Event
  1709  	_, err = tempFile.Write([]byte("Writing before closing"))
  1710  	if err != nil {
  1711  		t.Fatalf("Write: %v", err)
  1712  	}
  1713  	tempFile.Close()
  1714  
  1715  	// Expect event
  1716  	buf := make([]byte, unix.SizeofInotifyEvent)
  1717  	n, err := unix.Read(infd, buf[:])
  1718  	if n == -1 {
  1719  		t.Fatalf("No event was read from the iNotify fd")
  1720  	}
  1721  
  1722  	// Remove Watch
  1723  	if _, err = unix.InotifyRmWatch(infd, uint32(wd)); err != nil {
  1724  		t.Fatalf("InotifyRmWatch: %v", err)
  1725  	}
  1726  }
  1727  
  1728  func inotify_close_nowrite(t *testing.T) {
  1729  	// Create temporary files
  1730  	tempDir := t.TempDir()
  1731  	tempFile, err := os.CreateTemp(tempDir, "inotify_close_nowrite_test_file")
  1732  	if err != nil {
  1733  		t.Fatalf("TempFile: %v", err)
  1734  	}
  1735  	// File closed later in test
  1736  
  1737  	// Setup iNotify
  1738  	infd, err := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
  1739  	if err != nil {
  1740  		t.Fatalf("InotifyInit1: %v", err)
  1741  	}
  1742  
  1743  	wd, err := unix.InotifyAddWatch(infd, tempDir, unix.IN_CLOSE_NOWRITE)
  1744  	if err != nil {
  1745  		t.Fatalf("InotifyAddWatch: %v", err)
  1746  	}
  1747  
  1748  	// Trigger Event
  1749  	d, err := os.Open(tempDir)
  1750  	if err != nil {
  1751  		t.Fatalf("Opendir: %v", err)
  1752  	}
  1753  	tempFile.Close()
  1754  	d.Close()
  1755  
  1756  	// Expect event
  1757  	buf := make([]byte, unix.SizeofInotifyEvent*4)
  1758  	n, err := unix.Read(infd, buf[:])
  1759  	if err != nil {
  1760  		t.Fatalf("Read: %v", err)
  1761  	}
  1762  
  1763  	if n == 0 {
  1764  		t.Fatalf("No event was read from the iNotify fd")
  1765  	}
  1766  
  1767  	// Remove Watch
  1768  	if _, err = unix.InotifyRmWatch(infd, uint32(wd)); err != nil {
  1769  		t.Fatalf("InotifyRmWatch: %v", err)
  1770  	}
  1771  }
  1772  
  1773  func inotify_create(t *testing.T) {
  1774  	// Create temporary files
  1775  	tempDir := t.TempDir()
  1776  
  1777  	// Setup iNotify
  1778  	infd, err := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
  1779  	if err != nil {
  1780  		t.Fatalf("InotifyInit1: %v", err)
  1781  	}
  1782  
  1783  	wd, err := unix.InotifyAddWatch(infd, tempDir, unix.IN_CREATE)
  1784  	if err != nil {
  1785  		t.Fatalf("InotifyAddWatch: %v", err)
  1786  	}
  1787  
  1788  	// Trigger Event
  1789  	f, err := os.CreateTemp(tempDir, "inotify_create_test_file")
  1790  	if err != nil {
  1791  		t.Fatalf("TempFile: %v", err)
  1792  	}
  1793  	f.Close()
  1794  
  1795  	// Expect event
  1796  	buf := make([]byte, unix.SizeofInotifyEvent*4)
  1797  	n, err := unix.Read(infd, buf[:])
  1798  	if err != nil {
  1799  		t.Fatalf("Read: %v", err)
  1800  	}
  1801  	if n == 0 {
  1802  		t.Fatalf("No event was read from the iNotify fd")
  1803  	}
  1804  
  1805  	// Remove Watch
  1806  	if _, err = unix.InotifyRmWatch(infd, uint32(wd)); err != nil {
  1807  		t.Fatalf("InotifyRmWatch: %v", err)
  1808  	}
  1809  }
  1810  
  1811  func inotify_delete(t *testing.T) {
  1812  	// Create temporary files
  1813  	tempDir := t.TempDir()
  1814  	tempFile, err := os.CreateTemp(tempDir, "inotify_delete_test_file")
  1815  	if err != nil {
  1816  		t.Fatalf("TempFile: %v", err)
  1817  	}
  1818  	// File closed later in test
  1819  
  1820  	// Setup iNotify
  1821  	infd, err := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
  1822  	if err != nil {
  1823  		t.Fatalf("InotifyInit1: %v", err)
  1824  	}
  1825  
  1826  	wd, err := unix.InotifyAddWatch(infd, tempDir, unix.IN_DELETE)
  1827  	if err != nil {
  1828  		t.Fatalf("InotifyAddWatch: %v", err)
  1829  	}
  1830  
  1831  	// Trigger Event
  1832  	name := tempFile.Name()
  1833  	tempFile.Close()
  1834  	if err = os.Remove(name); err != nil {
  1835  		t.Fatalf("Remove: %v", err)
  1836  	}
  1837  
  1838  	// Expect event
  1839  	buf := make([]byte, unix.SizeofInotifyEvent*4)
  1840  	n, err := unix.Read(infd, buf[:])
  1841  	if err != nil {
  1842  		t.Fatalf("Read: %v", err)
  1843  	}
  1844  	if n == 0 {
  1845  		t.Fatalf("No event was read from the iNotify fd")
  1846  	}
  1847  
  1848  	// Remove Watch
  1849  	if _, err = unix.InotifyRmWatch(infd, uint32(wd)); err != nil {
  1850  		t.Fatalf("InotifyRmWatch: %v", err)
  1851  	}
  1852  }
  1853  
  1854  func inotify_delete_self(t *testing.T) {
  1855  	// Create temporary files
  1856  	tempDir := t.TempDir()
  1857  	tempFile, err := os.CreateTemp(tempDir, "inotify_delete_self_test_file")
  1858  	if err != nil {
  1859  		t.Fatalf("TempFile: %v", err)
  1860  	}
  1861  	// File closed later in test
  1862  
  1863  	// Setup iNotify
  1864  	infd, err := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
  1865  	if err != nil {
  1866  		t.Fatalf("InotifyInit1: %v", err)
  1867  	}
  1868  
  1869  	_, err = unix.InotifyAddWatch(infd, tempDir, unix.IN_DELETE_SELF)
  1870  	if err != nil {
  1871  		t.Fatalf("InotifyAddWatch: %v", err)
  1872  	}
  1873  
  1874  	// Trigger Event
  1875  	tempFile.Close()
  1876  	if err = os.RemoveAll(tempDir); err != nil {
  1877  		t.Fatalf("RemoveAll: %v", err)
  1878  	}
  1879  
  1880  	// Expect event
  1881  	buf := make([]byte, unix.SizeofInotifyEvent)
  1882  	n, err := unix.Read(infd, buf[:])
  1883  	if err != nil {
  1884  		t.Fatalf("Read: %v", err)
  1885  	}
  1886  	if n == 0 {
  1887  		t.Fatalf("No event was read from the iNotify fd")
  1888  	}
  1889  }
  1890  
  1891  func inotify_modify(t *testing.T) {
  1892  	// Create temporary files
  1893  	tempDir := t.TempDir()
  1894  	tempFile, err := os.CreateTemp(tempDir, "inotify_modify_test_file")
  1895  	if err != nil {
  1896  		t.Fatalf("TempFile: %v", err)
  1897  	}
  1898  	defer tempFile.Close()
  1899  
  1900  	// Setup iNotify
  1901  	infd, err := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
  1902  	if err != nil {
  1903  		t.Fatalf("InotifyInit1: %v", err)
  1904  	}
  1905  
  1906  	wd, err := unix.InotifyAddWatch(infd, tempFile.Name(), unix.IN_MODIFY)
  1907  	if err != nil {
  1908  		t.Fatalf("InotifyAddWatch: %v", err)
  1909  	}
  1910  
  1911  	// Trigger Event
  1912  	_, err = tempFile.Write([]byte("Writing before closing"))
  1913  	if err != nil {
  1914  		t.Fatalf("Write: %v", err)
  1915  	}
  1916  
  1917  	// Expect event
  1918  	buf := make([]byte, unix.SizeofInotifyEvent)
  1919  	n, err := unix.Read(infd, buf[:])
  1920  	if err != nil {
  1921  		t.Fatalf("Read: %v", err)
  1922  	}
  1923  	if n == 0 {
  1924  		t.Fatalf("No event was read from the iNotify fd")
  1925  	}
  1926  
  1927  	// Remove Watch
  1928  	if _, err = unix.InotifyRmWatch(infd, uint32(wd)); err != nil {
  1929  		t.Fatalf("InotifyRmWatch: %v", err)
  1930  	}
  1931  }
  1932  
  1933  func inotify_move_self(t *testing.T) {
  1934  	// Create temporary files
  1935  	tempDir := t.TempDir()
  1936  	tempFile, err := os.CreateTemp(tempDir, "inotify_move_self_test_file")
  1937  	if err != nil {
  1938  		t.Fatalf("TempFile: %v", err)
  1939  	}
  1940  	defer tempFile.Close()
  1941  
  1942  	// Setup iNotify
  1943  	infd, err := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
  1944  	if err != nil {
  1945  		t.Fatalf("InotifyInit1: %v", err)
  1946  	}
  1947  
  1948  	wd, err := unix.InotifyAddWatch(infd, tempFile.Name(), unix.IN_MOVE_SELF)
  1949  	if err != nil {
  1950  		t.Fatalf("InotifyAddWatch: %v", err)
  1951  	}
  1952  
  1953  	// Trigger Event
  1954  	err = os.Rename(tempFile.Name(), tempFile.Name()+"2")
  1955  	if err != nil {
  1956  		t.Fatalf("Rename: %v", err)
  1957  	}
  1958  
  1959  	// Expect event
  1960  	buf := make([]byte, unix.SizeofInotifyEvent)
  1961  	n, err := unix.Read(infd, buf[:])
  1962  	if err != nil {
  1963  		t.Fatalf("Read: %v", err)
  1964  	}
  1965  	if n == 0 {
  1966  		t.Fatalf("No event was read from the iNotify fd")
  1967  	}
  1968  
  1969  	// Remove Watch
  1970  	if _, err = unix.InotifyRmWatch(infd, uint32(wd)); err != nil {
  1971  		t.Fatalf("InotifyRmWatch: %v", err)
  1972  	}
  1973  }
  1974  
  1975  func inotify_moved_from(t *testing.T) {
  1976  	// Create temporary files
  1977  	tempDir1 := t.TempDir()
  1978  	tempDir2 := t.TempDir()
  1979  	tempFile, err := os.CreateTemp(tempDir1, "inotify_moved_from_test_file")
  1980  	if err != nil {
  1981  		t.Fatalf("TempFile: %v", err)
  1982  	}
  1983  	defer tempFile.Close()
  1984  
  1985  	// Setup iNotify
  1986  	infd, err := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
  1987  	if err != nil {
  1988  		t.Fatalf("InotifyInit1: %v", err)
  1989  	}
  1990  
  1991  	wd, err := unix.InotifyAddWatch(infd, tempDir1, unix.IN_MOVED_FROM)
  1992  	if err != nil {
  1993  		t.Fatalf("InotifyAddWatch: %v", err)
  1994  	}
  1995  
  1996  	// Trigger Event
  1997  	filename := strings.TrimPrefix(tempFile.Name(), tempDir1)
  1998  	err = os.Rename(tempDir1+filename,
  1999  		tempDir2+filename)
  2000  	if err != nil {
  2001  		t.Fatalf("Rename: %v", err)
  2002  	}
  2003  
  2004  	// Expect event
  2005  	buf := make([]byte, unix.SizeofInotifyEvent*4)
  2006  	n, err := unix.Read(infd, buf[:])
  2007  	if err != nil {
  2008  		t.Fatalf("Read: %v", err)
  2009  	}
  2010  
  2011  	if n == 0 {
  2012  		t.Fatalf("No event was read from the iNotify fd")
  2013  	}
  2014  
  2015  	// Remove Watch
  2016  	if _, err = unix.InotifyRmWatch(infd, uint32(wd)); err != nil {
  2017  		t.Fatalf("InotifyRmWatch: %v", err)
  2018  	}
  2019  }
  2020  
  2021  func inotify_moved_to(t *testing.T) {
  2022  	// Create temporary files
  2023  	tempDir1 := t.TempDir()
  2024  	tempDir2 := t.TempDir()
  2025  	tempFile, err := os.CreateTemp(tempDir1, "inotify_moved_to_test_file")
  2026  	if err != nil {
  2027  		t.Fatalf("TempFile: %v", err)
  2028  	}
  2029  	defer tempFile.Close()
  2030  
  2031  	// Setup iNotify
  2032  	infd, err := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
  2033  	if err != nil {
  2034  		t.Fatalf("InotifyInit1: %v", err)
  2035  	}
  2036  
  2037  	wd, err := unix.InotifyAddWatch(infd, tempDir2, unix.IN_MOVED_TO)
  2038  	if err != nil {
  2039  		t.Fatalf("InotifyAddWatch: %v", err)
  2040  	}
  2041  
  2042  	// Trigger Event
  2043  	filename := strings.TrimPrefix(tempFile.Name(), tempDir1)
  2044  	err = os.Rename(tempDir1+filename,
  2045  		tempDir2+filename)
  2046  	if err != nil {
  2047  		t.Fatalf("Rename: %v", err)
  2048  	}
  2049  
  2050  	// Expect event
  2051  	buf := make([]byte, unix.SizeofInotifyEvent*4)
  2052  	n, err := unix.Read(infd, buf[:])
  2053  	if err != nil {
  2054  		t.Fatalf("Read: %v", err)
  2055  	}
  2056  
  2057  	if n == 0 {
  2058  		t.Fatalf("No event was read from the iNotify fd")
  2059  	}
  2060  
  2061  	// Remove Watch
  2062  	if _, err = unix.InotifyRmWatch(infd, uint32(wd)); err != nil {
  2063  		t.Fatalf("InotifyRmWatch: %v", err)
  2064  	}
  2065  }
  2066  
  2067  func inotify_open(t *testing.T) {
  2068  	// Create temporary files
  2069  	tempDir := t.TempDir()
  2070  	tempFile, err := os.CreateTemp(tempDir, "inotify_open_test_file")
  2071  	if err != nil {
  2072  		t.Fatalf("TempFile: %v", err)
  2073  	}
  2074  	// File closed later in test
  2075  
  2076  	// Setup iNotify
  2077  	infd, err := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK)
  2078  	if err != nil {
  2079  		t.Fatalf("InotifyInit1: %v", err)
  2080  	}
  2081  
  2082  	wd, err := unix.InotifyAddWatch(infd, tempFile.Name(), unix.IN_OPEN)
  2083  	if err != nil {
  2084  		t.Fatalf("InotifyAddWatch: %v", err)
  2085  	}
  2086  
  2087  	// Trigger Event
  2088  	name := tempFile.Name()
  2089  	tempFile.Close()
  2090  	f, err := os.Open(name)
  2091  	if err != nil {
  2092  		t.Fatalf("Open: %v", err)
  2093  	}
  2094  	defer f.Close()
  2095  
  2096  	// Expect event
  2097  	buf := make([]byte, unix.SizeofInotifyEvent)
  2098  	n, err := unix.Read(infd, buf[:])
  2099  	if err != nil {
  2100  		t.Fatalf("Read: %v", err)
  2101  	}
  2102  	if n == 0 {
  2103  		t.Fatalf("No event was read from the iNotify fd")
  2104  	}
  2105  
  2106  	// Remove Watch
  2107  	if _, err = unix.InotifyRmWatch(infd, uint32(wd)); err != nil {
  2108  		t.Fatalf("InotifyRmWatch: %v", err)
  2109  	}
  2110  }
  2111  
  2112  func TestSockNonblock(t *testing.T) {
  2113  	ch1 := make(chan int)
  2114  	go func() {
  2115  		select {
  2116  		case <-ch1:
  2117  		}
  2118  
  2119  		client, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM|unix.SOCK_CLOEXEC, 0)
  2120  		if err != nil {
  2121  			t.Fatalf("Socket: %v", err)
  2122  		}
  2123  		defer unix.Close(client)
  2124  
  2125  		clientSA := unix.SockaddrInet4{Port: 33333, Addr: [4]byte{127, 0, 0, 1}}
  2126  		err = unix.Connect(client, &clientSA)
  2127  		if err != nil {
  2128  			t.Fatalf("Connect: %v", err)
  2129  		}
  2130  
  2131  		select {
  2132  		case <-ch1:
  2133  		}
  2134  	}()
  2135  
  2136  	server, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM|unix.SOCK_CLOEXEC, 0)
  2137  	if err != nil {
  2138  		t.Fatalf("Socket: %v", err)
  2139  	}
  2140  	defer unix.Close(server)
  2141  
  2142  	serverSA := unix.SockaddrInet4{Port: 33333, Addr: [4]byte{}}
  2143  
  2144  	err = unix.SetsockoptInt(server, unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
  2145  	if err != nil {
  2146  		t.Fatalf("SetsockoptInt: %v", err)
  2147  	}
  2148  
  2149  	err = unix.Bind(server, &serverSA)
  2150  	if err != nil {
  2151  		t.Fatalf("Bind: %v", err)
  2152  	}
  2153  
  2154  	err = unix.Listen(server, 3)
  2155  	if err != nil {
  2156  		t.Fatalf("Listen: %v", err)
  2157  	}
  2158  
  2159  	ch1 <- 1
  2160  
  2161  	accept, _, err := unix.Accept4(server, unix.SOCK_NONBLOCK|unix.SOCK_CLOEXEC)
  2162  	if err != nil {
  2163  		t.Fatalf("Accept: %v", err)
  2164  	}
  2165  
  2166  	buf := make([]byte, 16)
  2167  	_, err = unix.Read(accept, buf)
  2168  	if err.Error() != "EDC8102I Operation would block." {
  2169  		t.Fatalf("Read: Expected error \"EDC8102I Operation would block.\", but got \"%v\"", err)
  2170  	}
  2171  
  2172  	ch1 <- 1
  2173  }
  2174  
  2175  func TestSockIPTTL(t *testing.T) {
  2176  	server, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM|unix.SOCK_CLOEXEC, 0)
  2177  	if err != nil {
  2178  		t.Fatalf("Socket: %v", err)
  2179  	}
  2180  
  2181  	ttl, err := unix.GetsockoptInt(server, unix.IPPROTO_IP, unix.IP_TTL)
  2182  	if err != nil {
  2183  		t.Fatalf("GetsockoptInt: %v", err)
  2184  	}
  2185  
  2186  	if ttl != 64 {
  2187  		t.Fatalf("Expected TTL value of 64, got %v", ttl)
  2188  	}
  2189  
  2190  	err = unix.SetsockoptInt(server, unix.IPPROTO_IP, unix.IP_TTL, 65)
  2191  	if err != nil {
  2192  		t.Fatalf("SetsockoptInt: %v", err)
  2193  	}
  2194  
  2195  	ttl, err = unix.GetsockoptInt(server, unix.IPPROTO_IP, unix.IP_TTL)
  2196  	if err != nil {
  2197  		t.Fatalf("GetsockoptInt: %v", err)
  2198  	}
  2199  
  2200  	if ttl != 65 {
  2201  		t.Fatalf("Expected TTL value of 65, got %v", ttl)
  2202  	}
  2203  }
  2204  
  2205  func TestSethostname(t *testing.T) {
  2206  	name, err := os.Hostname()
  2207  	if err != nil {
  2208  		t.Fatalf("Failed to get hostname: %v", err)
  2209  	}
  2210  
  2211  	err = unix.Sethostname([]byte(name))
  2212  	if !strings.Contains(err.Error(), unix.ENOTSUP.Error()) {
  2213  		t.Fatalf("Sethostname: Expected error \"EDC5247I Operation not supported.\", but got \"%v\"", err)
  2214  	}
  2215  }
  2216  
  2217  func TestGetrandom(t *testing.T) {
  2218  	buf := make([]byte, 16)
  2219  	n, err := unix.Getrandom(buf, unix.GRND_NONBLOCK|unix.GRND_RANDOM)
  2220  	if err != nil {
  2221  		t.Fatalf("Getrandom: %v", err)
  2222  	}
  2223  	if n != 16 {
  2224  		t.Fatalf("Expected to read %d bytes. Actually read %d", 16, n)
  2225  	}
  2226  
  2227  	sum := 0
  2228  	for _, v := range buf {
  2229  		sum += int(v)
  2230  	}
  2231  	if sum == 0 {
  2232  		t.Fatalf("Getrandom: no random values retrieved")
  2233  	}
  2234  }
  2235  
  2236  func TestTermios(t *testing.T) {
  2237  	const ioctlReadTermios = unix.TCGETS
  2238  	const ioctlWriteTermios = unix.TCSETS
  2239  
  2240  	// Get address of controlling terminal
  2241  	tty, err := unix.Ctermid()
  2242  	if err != nil {
  2243  		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
  2244  		t.Skip("No terminal")
  2245  	}
  2246  
  2247  	// Open controlling terminal
  2248  	f, err := unix.Open(tty, 3, 0755)
  2249  	if err != nil {
  2250  		t.Skipf("Skipping because opening /dev/tty failed: %v", err)
  2251  	}
  2252  	defer unix.Close(f)
  2253  
  2254  	// Test IoctlGetTermios
  2255  	termios, err := unix.IoctlGetTermios(f, ioctlReadTermios)
  2256  
  2257  	// Save old terminal settings to restore
  2258  	oldTermios := *termios
  2259  	if err != nil {
  2260  		t.Fatalf("IoctlGetTermios: %v", err)
  2261  	}
  2262  
  2263  	// This attempts to replicate the behaviour documented for cfmakeraw in
  2264  	// the termios(3) manpage.
  2265  	termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
  2266  	termios.Oflag &^= unix.OPOST
  2267  	termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
  2268  	termios.Cflag &^= unix.CSIZE | unix.PARENB
  2269  	termios.Cflag |= unix.CS8
  2270  	termios.Cc[unix.VMIN] = 1
  2271  	termios.Cc[unix.VTIME] = 0
  2272  
  2273  	// Test IoctlSetTermios
  2274  	if err := unix.IoctlSetTermios(f, ioctlWriteTermios, termios); err != nil {
  2275  		t.Fatalf("IoctlSetTermios: %v", err)
  2276  	}
  2277  
  2278  	// Restore
  2279  	if err := unix.IoctlSetTermios(f, ioctlWriteTermios, &oldTermios); err != nil {
  2280  		t.Fatalf("IoctlSetTermios: %v", err)
  2281  	}
  2282  }
  2283  
  2284  func TestDup3(t *testing.T) {
  2285  	data := []byte("Test String")
  2286  
  2287  	// Create temporary files
  2288  	tempDir := t.TempDir()
  2289  	tempFile, err := os.Create(filepath.Join(tempDir, "dup3_test_file"))
  2290  	if err != nil {
  2291  		t.Fatalf("TempFile: %v", err)
  2292  	}
  2293  	defer tempFile.Close()
  2294  
  2295  	// Duplicate fd
  2296  	fd1, err := unix.Open(tempFile.Name(), unix.O_RDWR|unix.O_CLOEXEC, 777)
  2297  	if err != nil {
  2298  		t.Fatalf("Open: %v", err)
  2299  	}
  2300  	defer unix.Close(fd1)
  2301  
  2302  	fd2 := 11
  2303  	if err := unix.Dup3(fd1, fd2, unix.O_CLOEXEC); err != nil {
  2304  		t.Fatalf("Dup3: %v", err)
  2305  	}
  2306  	defer unix.Close(fd2)
  2307  
  2308  	// Write
  2309  	n, err := unix.Write(fd2, data)
  2310  	if err != nil {
  2311  		t.Fatalf("Write: %v", err)
  2312  	}
  2313  	if n != len(data) {
  2314  		t.Fatalf("Write: only wrote %d bytes, expected %d", n, len(data))
  2315  	}
  2316  
  2317  	// Read
  2318  	buf := make([]byte, 16)
  2319  	n, err = tempFile.Read(buf)
  2320  	if err != nil {
  2321  		t.Fatalf("Read: %v", err)
  2322  	}
  2323  	if n != len(data) {
  2324  		t.Fatalf("Read: only read %d bytes, expected %d", n, len(data))
  2325  	}
  2326  
  2327  	// Compare
  2328  	for i := 0; i < len(data); i++ {
  2329  		if buf[i] != data[i] {
  2330  			t.Fatalf("Dup3: data read did not match data written")
  2331  		}
  2332  	}
  2333  }
  2334  
  2335  func TestWait4(t *testing.T) {
  2336  	if v, r := zosLeVersion(); v <= 2 && r <= 4 {
  2337  		t.Skipf("New wait4 can't be used in %d.%d < 2.5", v, r)
  2338  	}
  2339  	if os.Getenv("TEST_WAIT4_HELPER") == "1" {
  2340  		exitCode, err := strconv.Atoi(os.Args[2])
  2341  		if err != nil {
  2342  			fmt.Printf("exit code cannot be parsed: %s\n", err)
  2343  		}
  2344  		defer os.Exit(exitCode)
  2345  		for i := 0; i < 50000000; i++ {
  2346  		}
  2347  		return
  2348  	}
  2349  
  2350  	const (
  2351  		childPid = -2
  2352  		core     = 0x80
  2353  		exited   = 0x00
  2354  		stopped  = 0x7F
  2355  		shift    = 8
  2356  	)
  2357  	pgid, err := unix.Getpgid(os.Getpid())
  2358  	if err != nil {
  2359  		t.Fatal(err)
  2360  	}
  2361  	testCases := []struct {
  2362  		name     string
  2363  		exitCode int
  2364  		pid      int
  2365  		options  int
  2366  		signals  []syscall.Signal
  2367  		wpid     int
  2368  		err      error
  2369  		ws       unix.WaitStatus
  2370  	}{
  2371  		{"Child's pgid", 0, -pgid, 0, []syscall.Signal{}, childPid, nil, exited},
  2372  		{"Any", 0, -1, 0, []syscall.Signal{}, childPid, nil, exited},
  2373  		{"Pid zero", 0, 0, 0, []syscall.Signal{}, childPid, nil, exited},
  2374  		{"Child's pid", 0, childPid, 0, []syscall.Signal{}, childPid, nil, exited},
  2375  		{"Exited with 2", 2, childPid, 0, []syscall.Signal{}, childPid, nil, unix.WaitStatus((2 << shift) | exited)},
  2376  		{"No hang", 0, childPid, unix.WNOHANG, []syscall.Signal{}, 0, nil, exited},
  2377  		{"No child", 0, os.Getpid(), 0, []syscall.Signal{}, -1, unix.ECHILD, exited},
  2378  		{"Inval", 0, -1, -1, []syscall.Signal{}, -1, unix.EINVAL, exited},
  2379  		{"Killed", 0, childPid, 0, []syscall.Signal{unix.SIGKILL}, childPid, nil, unix.WaitStatus(unix.SIGKILL)},
  2380  		{"Interrupted", 0, childPid, 0, []syscall.Signal{unix.SIGINT}, childPid, nil, unix.WaitStatus(unix.SIGINT)},
  2381  		{"Stopped", 0, childPid, unix.WUNTRACED, []syscall.Signal{unix.SIGSTOP}, childPid, nil, unix.WaitStatus((unix.SIGSTOP << shift) | stopped)},
  2382  		{"Core dump", 0, childPid, unix.WUNTRACED, []syscall.Signal{unix.SIGTRAP}, childPid, nil, unix.WaitStatus(core | unix.SIGTRAP)},
  2383  		// TODO(paulc): Skipping these two until wait4 behaves the same as in Linux
  2384  		// {"Continued", 0, cpid, unix.WCONTINUED, []syscall.Signal{unix.SIGSTOP, unix.SIGCONT}, cpid, nil, 0xffff},
  2385  		// {"Intmin", 0, -2147483648, 0, []syscall.Signal{}, -1, unix.ESRCH, exited},
  2386  	}
  2387  
  2388  	for _, c := range testCases {
  2389  		t.Run(c.name, func(t *testing.T) {
  2390  			exe, err := os.Executable()
  2391  			if err != nil {
  2392  				t.Fatal(err)
  2393  			}
  2394  			cmd := exec.Command(exe, "-test.run=^TestWait4$", fmt.Sprint(c.exitCode))
  2395  			cmd.Env = []string{"TEST_WAIT4_HELPER=1"}
  2396  			if err := cmd.Start(); err != nil {
  2397  				t.Fatal(err)
  2398  			}
  2399  
  2400  			for i, sig := range c.signals {
  2401  				if err := cmd.Process.Signal(sig); err != nil {
  2402  					cmd.Process.Kill()
  2403  					t.Fatal(err)
  2404  				}
  2405  				if i != len(c.signals)-1 {
  2406  					time.Sleep(1000 * time.Millisecond)
  2407  				}
  2408  			}
  2409  
  2410  			pid, wpid := c.pid, c.wpid
  2411  			if c.pid == childPid {
  2412  				pid = cmd.Process.Pid
  2413  			}
  2414  			if c.wpid == childPid {
  2415  				wpid = cmd.Process.Pid
  2416  			}
  2417  			ws := unix.WaitStatus(0)
  2418  			ru := unix.Rusage{}
  2419  			ret, err := unix.Wait4(pid, &ws, c.options, &ru)
  2420  			if err != c.err {
  2421  				t.Fatalf("expected %s error but got %s error\n", c.err, err)
  2422  			}
  2423  			if ret != wpid {
  2424  				t.Fatalf("expected return value of %d but got %d\n", wpid, ret)
  2425  			}
  2426  			if ws != c.ws {
  2427  				t.Fatalf("expected wait status %x but got %x\n", c.ws, ws)
  2428  			}
  2429  			if err == nil && len(c.signals) == 0 && c.options&unix.WNOHANG != unix.WNOHANG {
  2430  				if emptyRU := new(unix.Rusage); ru == *emptyRU {
  2431  					t.Fatalf("expected non-empty rusage but got %+v", ru)
  2432  				}
  2433  			}
  2434  			cmd.Process.Kill()
  2435  		})
  2436  	}
  2437  }
  2438  
  2439  func TestNanosleep(t *testing.T) {
  2440  	waitTime := int64(10000000)
  2441  
  2442  	var ts, tsLeftover unix.Timespec
  2443  	ts = unix.Timespec{
  2444  		Sec:  0,
  2445  		Nsec: waitTime,
  2446  	}
  2447  	tsLeftover = unix.Timespec{
  2448  		Sec:  0,
  2449  		Nsec: 0,
  2450  	}
  2451  
  2452  	t1 := time.Now().UnixNano()
  2453  	if err := unix.Nanosleep(&ts, &tsLeftover); err != nil {
  2454  		t.Fatalf("Nanosleep: %v", err)
  2455  	}
  2456  	t2 := time.Now().UnixNano()
  2457  
  2458  	if t2-t1 < waitTime {
  2459  		t.Fatalf("Nanosleep: did not wait long enough. Expected: %d, got: %d", waitTime, t2-t1)
  2460  	}
  2461  }
  2462  
  2463  func TestOpenat2(t *testing.T) {
  2464  	how := &unix.OpenHow{
  2465  		Flags: unix.O_RDONLY,
  2466  	}
  2467  	fd, err := unix.Openat2(unix.AT_FDCWD, ".", how)
  2468  	if err != nil {
  2469  		t.Fatalf("openat2: %v", err)
  2470  	}
  2471  	if err := unix.Close(fd); err != nil {
  2472  		t.Fatalf("close: %v", err)
  2473  	}
  2474  
  2475  	// prepare
  2476  	tempDir := t.TempDir()
  2477  
  2478  	subdir := filepath.Join(tempDir, "dir")
  2479  	if err := os.Mkdir(subdir, 0755); err != nil {
  2480  		t.Fatal(err)
  2481  	}
  2482  	symlink := filepath.Join(subdir, "symlink")
  2483  	if err := os.Symlink("../", symlink); err != nil {
  2484  		t.Fatal(err)
  2485  	}
  2486  
  2487  	dirfd, err := unix.Open(subdir, unix.O_RDONLY, 0)
  2488  	if err != nil {
  2489  		t.Fatalf("open(%q): %v", subdir, err)
  2490  	}
  2491  	defer unix.Close(dirfd)
  2492  
  2493  	// openat2 with no extra flags -- should succeed
  2494  	fd, err = unix.Openat2(dirfd, "symlink", how)
  2495  	if err != nil {
  2496  		t.Errorf("Openat2 should succeed, got %v", err)
  2497  	}
  2498  	if err := unix.Close(fd); err != nil {
  2499  		t.Fatalf("close: %v", err)
  2500  	}
  2501  
  2502  	// open with RESOLVE_BENEATH, should result in EXDEV
  2503  	how.Resolve = unix.RESOLVE_BENEATH
  2504  	fd, err = unix.Openat2(dirfd, "symlink", how)
  2505  	if err == nil {
  2506  		if err := unix.Close(fd); err != nil {
  2507  			t.Fatalf("close: %v", err)
  2508  		}
  2509  	}
  2510  	if err != unix.EXDEV {
  2511  		t.Errorf("Openat2 should fail with EXDEV, got %v", err)
  2512  	}
  2513  }
  2514  
  2515  func TestUtimesNanoAt(t *testing.T) {
  2516  	// z/OS currently does not support setting milli/micro/nanoseconds for files
  2517  	// The Nsec field will be 0 when trying to get atime/mtime
  2518  
  2519  	// Create temp dir and file
  2520  	f, err := os.Create(filepath.Join(t.TempDir(), "utimesNanoAt_test_file"))
  2521  	if err != nil {
  2522  		t.Fatalf("TempFile: %v", err)
  2523  	}
  2524  	defer f.Close()
  2525  
  2526  	fd := int(f.Fd())
  2527  
  2528  	// Set atime and mtime
  2529  	ts := []unix.Timespec{
  2530  		unix.Timespec{123456789, 123456789},
  2531  		unix.Timespec{123456789, 123456789},
  2532  	}
  2533  	atimeTS := time.Unix(ts[0].Sec, ts[0].Nsec)
  2534  	mtimeTS := time.Unix(ts[1].Sec, ts[1].Nsec)
  2535  
  2536  	err = unix.UtimesNanoAt(fd, f.Name(), ts, 0)
  2537  	if err != nil {
  2538  		t.Fatalf("TestUtimesNanoAt: %v", err)
  2539  	}
  2540  
  2541  	// Compare atime and mtime
  2542  	var statAfter unix.Stat_t
  2543  	if err = unix.Fstat(fd, &statAfter); err != nil {
  2544  		t.Fatalf("Fstat: %v", err)
  2545  	}
  2546  	atimeAfter := time.Unix(statAfter.Atim.Sec, statAfter.Atim.Nsec)
  2547  	mtimeAfter := time.Unix(statAfter.Mtim.Sec, statAfter.Mtim.Nsec)
  2548  
  2549  	// TODO (joon): check using time.Equal() once z/OS supports finer timestamps for files
  2550  	if atimeAfter.Unix() != atimeTS.Unix() {
  2551  		t.Fatalf("Expected atime to be %v. Got %v", atimeAfter.Unix(), atimeTS.Unix())
  2552  	}
  2553  	if mtimeAfter.Unix() != mtimeTS.Unix() {
  2554  		t.Fatalf("Expected mtime to be %v. Got %v", atimeAfter.Unix(), atimeTS.Unix())
  2555  	}
  2556  }
  2557  
  2558  func TestPivotRoot(t *testing.T) {
  2559  	if euid != 0 {
  2560  		t.Skip("euid != 0")
  2561  	}
  2562  
  2563  	err := unix.Unshare(unix.CLONE_NEWNS)
  2564  	if err != nil {
  2565  		t.Fatalf("Unshare: %v", err)
  2566  	}
  2567  
  2568  	// Create our 'new_root' and bind mount it to satisfy one of the conditions of pivot_root
  2569  	newRoot := t.TempDir()
  2570  
  2571  	err = unix.Mount(newRoot, newRoot, "", unix.MS_BIND|unix.MS_REC, "")
  2572  	if err != nil {
  2573  		t.Fatalf("Mount: %v", err)
  2574  	}
  2575  
  2576  	// Create our 'old_root'
  2577  	oldRoot, err := os.MkdirTemp(newRoot, "oldRoot")
  2578  	if err != nil {
  2579  		t.Fatalf("TempDir: %v", err)
  2580  	}
  2581  
  2582  	// Perform the pivot and check that our old root is now a subfolder in our new root
  2583  	if err = unix.PivotRoot(newRoot, oldRoot); err != nil {
  2584  		t.Fatalf("PivotRoot: %v", err)
  2585  	}
  2586  
  2587  	err = unix.Chdir("/")
  2588  	if err != nil {
  2589  		t.Fatalf("Chdir: %v", err)
  2590  	}
  2591  
  2592  	if _, err := os.Stat("/" + filepath.Base(oldRoot)); os.IsNotExist(err) {
  2593  		t.Fatalf("Expected to see old root as a subdirectory.")
  2594  	}
  2595  }
  2596  
  2597  func TestMountUnmount(t *testing.T) {
  2598  	if v, r := zosLeVersion(); v < 2 || (v == 2 && r < 4) {
  2599  		t.Skipf("New mount can't be used in %d.%d < 2.5. Run TestLegacyMountUnmount", v, r)
  2600  	}
  2601  
  2602  	if _, err := os.Stat("/proc/self"); errors.Is(err, os.ErrNotExist) {
  2603  		t.Skip("/proc/self is not exist skipping the test")
  2604  	}
  2605  
  2606  	// Check that TFS is installed on the system, otherwise the test cannot be performed.
  2607  	b, err := os.ReadFile("/proc/filesystems")
  2608  	if err != nil {
  2609  		t.Fatalf("ReadFile: %v", err)
  2610  	}
  2611  	filesystems := string(b)
  2612  	if !strings.Contains(filesystems, "TFS") {
  2613  		t.Skip("Missing TFS filesystem")
  2614  	}
  2615  
  2616  	// Create a temp directory for the TFS
  2617  	tempSrc := t.TempDir()
  2618  
  2619  	// Mount the TFS
  2620  	tfs := "testTFS"
  2621  	err = exec.Command("/usr/sbin/mount", "-t", "TFS", "-f", tfs, tempSrc).Run()
  2622  	if err != nil {
  2623  		t.Skip("Could not create TFS")
  2624  	}
  2625  
  2626  	// Create a temp dir and test Mount()
  2627  	tempTgt := t.TempDir()
  2628  
  2629  	err = unix.Mount(tempSrc, tempTgt, "TFS", 0, "")
  2630  	if err != nil {
  2631  		t.Fatalf("Mount: %v", err)
  2632  	}
  2633  
  2634  	// Unmount and cleanup
  2635  	err = unix.Unmount(tempTgt, 0)
  2636  	if err != nil {
  2637  		t.Fatalf("Unmount: %v", err)
  2638  	}
  2639  	err = exec.Command("/usr/sbin/unmount", "-f", tfs).Run()
  2640  	if err != nil {
  2641  		t.Fatalf("Could not remove TFS")
  2642  	}
  2643  }
  2644  
  2645  func TestMountNamespace(t *testing.T) {
  2646  	if v, r := zosLeVersion(); v <= 2 && r <= 4 {
  2647  		t.Skipf("Namespaces not available on z/OS %v.%v", v, r)
  2648  	}
  2649  
  2650  	// Check that TFS is installed on the system, otherwise the test cannot be performed.
  2651  	b, err := os.ReadFile("/proc/filesystems")
  2652  	if err != nil {
  2653  		t.Skipf("Problem with reading /proc/filesystems: %v", err)
  2654  	}
  2655  	filesystems := string(b)
  2656  	if !strings.Contains(filesystems, "TFS") {
  2657  		t.Skipf("Missing TFS filesystem")
  2658  	}
  2659  
  2660  	if os.Getenv("SETNS_HELPER_PROCESS") == "1" {
  2661  		err := unix.Unshare(unix.CLONE_NEWNS)
  2662  		if err != nil {
  2663  			t.Skipf("Unshare: %v", err)
  2664  		}
  2665  
  2666  		// Create a temp directory for the TFS
  2667  		tempSrc := t.TempDir()
  2668  
  2669  		// Mount the TFS
  2670  		err = exec.Command("/usr/sbin/mount", "-t", "TFS", "-f", "testTFS", tempSrc).Run()
  2671  		if err != nil {
  2672  			t.Skipf("Could not create TFS")
  2673  		}
  2674  
  2675  		data, err := os.ReadFile("/proc/mounts")
  2676  		if err != nil {
  2677  			t.Fatalf("ReadFile: %v", err)
  2678  		}
  2679  
  2680  		err = os.WriteFile(os.Getenv("MNT_NS_FILE"), data, 644)
  2681  		if err != nil {
  2682  			t.Fatalf("WriteFile: %v", err)
  2683  		}
  2684  		return
  2685  	}
  2686  
  2687  	// Make a file to copy the child process' mount information
  2688  	f, err := os.CreateTemp("", "mntNsTestFile")
  2689  	if err != nil {
  2690  		t.Fatalf("Could not create temp file")
  2691  	}
  2692  	defer os.Remove(f.Name())
  2693  	f.Close()
  2694  
  2695  	exe, err := os.Executable()
  2696  	if err != nil {
  2697  		t.Fatal(err)
  2698  	}
  2699  	cmd := exec.Command(exe, "-test.v", "-test.run=^TestMountNamespace$")
  2700  	cmd.Env = append(os.Environ(), "SETNS_HELPER_PROCESS=1")
  2701  	cmd.Env = append(cmd.Env, "MNT_NS_FILE="+f.Name())
  2702  
  2703  	// Create the child process and get the path of the TFS mount to be cleaned up
  2704  	out, err := cmd.CombinedOutput()
  2705  	if err != nil {
  2706  		t.Fatalf("helper process failed: %v\n%v", err, string(out))
  2707  	}
  2708  	if strings.Contains(string(out), "SKIP") {
  2709  		t.Skipf("helper process: %v", string(out))
  2710  	}
  2711  	tfsDir := strings.Split(string(out), "\n")[1]
  2712  	defer os.RemoveAll(tfsDir)
  2713  
  2714  	d1, err := os.ReadFile(f.Name())
  2715  	if err != nil {
  2716  		t.Fatalf("ReadFile: %v", err)
  2717  	}
  2718  
  2719  	d2, err := os.ReadFile("/proc/mounts")
  2720  	if err != nil {
  2721  		t.Fatalf("ReadFile: %v", err)
  2722  	}
  2723  
  2724  	// Check that the TFS created in the child process was not made in the parent
  2725  	if !strings.Contains(string(d1), tfsDir) {
  2726  		t.Errorf("Expected to see %v in child process' /proc/mounts", tfsDir)
  2727  	}
  2728  
  2729  	if strings.Contains(string(d2), tfsDir) {
  2730  		t.Errorf("Expected not to see %v in parent process' /proc/mounts", tfsDir)
  2731  	}
  2732  }
  2733  func TestMkfifoat(t *testing.T) {
  2734  	name := fmt.Sprintf("fifo%d", os.Getpid())
  2735  	pname := fmt.Sprintf("/tmp/fifo%d", os.Getpid())
  2736  	dirStream, err := unix.Opendir("/tmp")
  2737  	if err != nil {
  2738  		t.Fatalf("Opendir: %v", err)
  2739  	}
  2740  	defer unix.Closedir(dirStream)
  2741  
  2742  	dirFd, err := unix.Dirfd(dirStream)
  2743  	if err != nil {
  2744  		t.Fatalf("Dirfd: %v", err)
  2745  	}
  2746  	if dirFd < 0 {
  2747  		t.Fatalf("Dirfd: fd < 0, (fd = %v)", dirFd)
  2748  	}
  2749  	err = unix.Mkfifoat(dirFd, name, 0666)
  2750  	if err != nil {
  2751  		t.Fatalf("Mkfifoat: failed to create FIFO: %v at %d", err, dirFd)
  2752  	}
  2753  	st, err := os.Stat(pname)
  2754  	if err != nil {
  2755  		t.Fatalf("Mkfifoat: failed to stat FIFO: %s %v", pname, err)
  2756  	}
  2757  	if st.Mode()&os.ModeNamedPipe != os.ModeNamedPipe {
  2758  		t.Fatalf("Mkfifoat: %s is not a FIFO", pname)
  2759  	}
  2760  
  2761  	os.Remove(pname)
  2762  }
  2763  
  2764  func TestMkdirat(t *testing.T) {
  2765  	name := fmt.Sprintf("dir%d", os.Getpid())
  2766  	pname := fmt.Sprintf("/tmp/dir%d", os.Getpid())
  2767  	dirStream, err := unix.Opendir("/tmp")
  2768  	if err != nil {
  2769  		t.Fatalf("Opendir: %v", err)
  2770  	}
  2771  	defer unix.Closedir(dirStream)
  2772  
  2773  	dirFd, err := unix.Dirfd(dirStream)
  2774  	if err != nil {
  2775  		t.Fatalf("Dirfd: %v", err)
  2776  	}
  2777  	if dirFd < 0 {
  2778  		t.Fatalf("Dirfd: fd < 0, (fd = %v)", dirFd)
  2779  	}
  2780  	err = unix.Mkdirat(dirFd, name, 0777)
  2781  	if err != nil {
  2782  		t.Fatalf("Mkdirat: failed to create directory: %v at %d", err, dirFd)
  2783  	}
  2784  	st, err := os.Stat(pname)
  2785  	if err != nil {
  2786  		t.Fatalf("Mkdirat: failed to stat directory: %s %v", pname, err)
  2787  	}
  2788  	if !st.Mode().IsDir() {
  2789  		t.Fatalf("Mkdirat: %s is not a directory", pname)
  2790  	}
  2791  	os.Remove(pname)
  2792  }
  2793  
  2794  func TestLinkat(t *testing.T) {
  2795  	lName := fmt.Sprintf("testLinkatLink%d", os.Getpid())
  2796  
  2797  	dirStream, err := unix.Opendir("/tmp")
  2798  	if err != nil {
  2799  		t.Fatalf("Opendir: %v", err)
  2800  	}
  2801  	defer unix.Closedir(dirStream)
  2802  
  2803  	dirFd, err := unix.Dirfd(dirStream)
  2804  	if err != nil {
  2805  		t.Fatalf("Dirfd: %v", err)
  2806  	}
  2807  	if dirFd < 0 {
  2808  		t.Fatalf("Dirfd: fd < 0, (fd = %v)", dirFd)
  2809  	}
  2810  
  2811  	f, err := os.CreateTemp("/tmp", "tesLinkatFile")
  2812  	if err != nil {
  2813  		t.Fatalf("CreateTemp: %v", err)
  2814  	}
  2815  	defer os.Remove(f.Name())
  2816  	defer f.Close()
  2817  
  2818  	err = unix.Linkat(dirFd, f.Name(), dirFd, lName, 0)
  2819  	if err != nil {
  2820  		t.Fatalf("Linkat: Failed to create link: %v", err)
  2821  	}
  2822  	defer os.Remove("/tmp/" + lName)
  2823  
  2824  	fInfo, err := os.Lstat(f.Name())
  2825  	if err != nil {
  2826  		t.Fatalf("Lstat: %v", err)
  2827  	}
  2828  	lInfo, err := os.Lstat(filepath.Join("/tmp/", lName))
  2829  	if err != nil {
  2830  		t.Fatalf("Lstat: %v", err)
  2831  	}
  2832  
  2833  	if !os.SameFile(fInfo, lInfo) {
  2834  		t.Errorf("Expected FileInfo for %s to match %s", lName, f.Name())
  2835  	}
  2836  }
  2837  
  2838  func TestSymlinkat(t *testing.T) {
  2839  	f, err := os.Create(filepath.Join(t.TempDir(), "symlinkatTestFile"))
  2840  	if err != nil {
  2841  		t.Fatal("CreateTemp:", err)
  2842  	}
  2843  	f.Close()
  2844  
  2845  	dir, err := os.Open(filepath.Dir(f.Name()))
  2846  	if err != nil {
  2847  		t.Fatal("Open:", err)
  2848  	}
  2849  	defer dir.Close()
  2850  
  2851  	linkName := fmt.Sprintf("testSymlink%d", os.Getpid())
  2852  	err = unix.Symlinkat(f.Name(), int(dir.Fd()), linkName)
  2853  	if err != nil {
  2854  		t.Fatal("Symlinkat:", err)
  2855  	}
  2856  
  2857  	buf := make([]byte, 256)
  2858  	_, err = unix.Readlinkat(int(dir.Fd()), linkName, buf)
  2859  	if err != nil {
  2860  		t.Fatal("Readlink:", err)
  2861  	}
  2862  
  2863  	if string(f.Name()) != string(buf[:len(f.Name())]) {
  2864  		t.Errorf("Expected buffer contents to be: %s. Got: %s.", f.Name(), string(buf[:]))
  2865  	}
  2866  }
  2867  
  2868  func TestMknodat(t *testing.T) {
  2869  	if euid != 0 {
  2870  		t.Skip("euid != 0")
  2871  	}
  2872  
  2873  	dirStream, err := unix.Opendir("/tmp")
  2874  	if err != nil {
  2875  		t.Fatalf("Opendir: %v", err)
  2876  	}
  2877  	defer unix.Closedir(dirStream)
  2878  
  2879  	dirFd, err := unix.Dirfd(dirStream)
  2880  	if err != nil {
  2881  		t.Fatalf("Dirfd: %v", err)
  2882  	}
  2883  	if dirFd < 0 {
  2884  		t.Fatalf("Dirfd: fd < 0, (fd = %v)", dirFd)
  2885  	}
  2886  
  2887  	name := fmt.Sprintf("mknodatTest%d", os.Getpid())
  2888  	fifoName := fmt.Sprintf("mknodatTestFIFO%d", os.Getpid())
  2889  	scfName := fmt.Sprintf("mknodatTestSCF%d", os.Getpid())
  2890  
  2891  	err = unix.Mknodat(dirFd, name, unix.S_IFREG, 0)
  2892  	if err != nil {
  2893  		t.Fatalf("Mknodat - regular: %v", err)
  2894  	}
  2895  	defer os.Remove("/tmp/" + name)
  2896  
  2897  	err = unix.Mknodat(dirFd, fifoName, unix.S_IFIFO, 0)
  2898  	if err != nil {
  2899  		t.Fatalf("Mknodat - directory: %v", err)
  2900  	}
  2901  	defer os.Remove("/tmp/" + fifoName)
  2902  
  2903  	err = unix.Mknodat(dirFd, scfName, unix.S_IFCHR|unix.S_IRUSR|unix.S_IWUSR, 0x00010000|0x0001)
  2904  	if err != nil {
  2905  		t.Fatalf("Mknodat - character special file: %v", err)
  2906  	}
  2907  	defer os.Remove("/tmp/" + scfName)
  2908  }
  2909  
  2910  func TestFchownat(t *testing.T) {
  2911  	if euid != 0 {
  2912  		t.Skip("euid != 0")
  2913  	}
  2914  
  2915  	f, err := os.Create(filepath.Join(t.TempDir(), "fchownatTestFile"))
  2916  	if err != nil {
  2917  		t.Fatalf("CreateTemp: %v", err)
  2918  	}
  2919  	defer f.Close()
  2920  
  2921  	dir, err := os.Open(filepath.Dir(f.Name()))
  2922  	if err != nil {
  2923  		t.Fatalf("Open: %v", err)
  2924  	}
  2925  	defer dir.Close()
  2926  
  2927  	dirfd := int(dir.Fd())
  2928  
  2929  	err = unix.Fchownat(0, f.Name(), os.Getuid(), os.Getgid(), 0)
  2930  	if err != nil {
  2931  		t.Errorf("Fchownat: %v", err)
  2932  	}
  2933  
  2934  	unix.Fchownat(dirfd, filepath.Base(f.Name()), os.Getuid(), os.Getgid(), 0)
  2935  	if err != nil {
  2936  		t.Errorf("Fchownat: %v", err)
  2937  	}
  2938  	err = unix.Fchownat(dirfd, "blah", os.Getuid(), os.Getgid(), 0)
  2939  	if err != nil {
  2940  		if !strings.Contains(err.Error(), "EDC5129I No such file or directory.") {
  2941  			t.Errorf("Expected: EDC5129I No such file or directory. Got: %v", err)
  2942  		}
  2943  	} else {
  2944  		t.Error("Fchownat: Expected to get error \"EDC5129I No such file or directory.\"")
  2945  	}
  2946  }
  2947  
  2948  func TestFaccessat(t *testing.T) {
  2949  	f, err := os.CreateTemp("/tmp", "faccessatTestFile")
  2950  	if err != nil {
  2951  		t.Fatalf("CreateTemp: %v", err)
  2952  	}
  2953  	defer os.Remove(f.Name())
  2954  	defer f.Close()
  2955  
  2956  	dirStream, err := unix.Opendir("/tmp")
  2957  	if err != nil {
  2958  		t.Fatalf("Opendir: %v", err)
  2959  	}
  2960  	defer unix.Closedir(dirStream)
  2961  
  2962  	dirfd, err := unix.Dirfd(dirStream)
  2963  	if err != nil {
  2964  		t.Fatalf("Dirfd: %v", err)
  2965  	}
  2966  	if dirfd < 0 {
  2967  		t.Fatalf("Dirfd: fd < 0, (fd = %v)", dirfd)
  2968  	}
  2969  
  2970  	err = unix.Faccessat(dirfd, filepath.Base(f.Name()), unix.R_OK|unix.W_OK, unix.AT_EACCESS)
  2971  	if err != nil {
  2972  		t.Errorf("Faccessat - relative file path: %v", err)
  2973  	}
  2974  	err = unix.Faccessat2(dirfd, filepath.Base(f.Name()), unix.R_OK|unix.W_OK, unix.AT_EACCESS)
  2975  	if err != nil {
  2976  		t.Errorf("Faccessat - relative file path: %v", err)
  2977  	}
  2978  
  2979  	err = unix.Faccessat(dirfd, f.Name(), unix.R_OK|unix.W_OK, unix.AT_EACCESS)
  2980  	if err != nil {
  2981  		t.Errorf("Faccessat - absolute file path: %v", err)
  2982  	}
  2983  
  2984  	err = unix.Faccessat(0, filepath.Base(f.Name()), unix.R_OK, unix.AT_EACCESS)
  2985  	if err != nil {
  2986  		if !strings.Contains(err.Error(), "EDC5135I Not a directory.") {
  2987  			t.Errorf("Expected: EDC5135I Not a directory. Got: %v", err)
  2988  		}
  2989  	} else {
  2990  		t.Error("Faccessat: Expected to get error \"EDC5135I Not a directory.\"")
  2991  	}
  2992  
  2993  	err = unix.Faccessat(0, "/", unix.R_OK, unix.AT_EACCESS)
  2994  	if err != nil {
  2995  		t.Errorf("Faccessat - read root directory: %v", err)
  2996  	}
  2997  
  2998  	err = unix.Faccessat(0, "/", unix.W_OK, unix.AT_EACCESS)
  2999  	if err != nil {
  3000  		if !strings.Contains(err.Error(), "EDC5141I Read-only file system.") {
  3001  			t.Errorf("Expected: EDC5141I Read-only file system. Got: %v", err)
  3002  		}
  3003  	} else {
  3004  		if BypassTestOnUntil("zoscan56", "2024-04-01T12:45:21.123Z") {
  3005  			fmt.Fprintf(os.Stderr, "Faccessat: Expected to get error \"EDC5141I Read-only file system.\"")
  3006  		} else {
  3007  			t.Error("Faccessat: Expected to get error \"EDC5141I Read-only file system.\"")
  3008  		}
  3009  	}
  3010  }
  3011  
  3012  func TestUnlinkat(t *testing.T) {
  3013  	tmpdir := t.TempDir()
  3014  	f, err := os.CreateTemp(tmpdir, "unlinkatTestFile")
  3015  	if err != nil {
  3016  		log.Fatal("CreateTemp:", err)
  3017  	}
  3018  	// file close later
  3019  
  3020  	dirStream, err := unix.Opendir(tmpdir)
  3021  	if err != nil {
  3022  		t.Fatalf("Opendir: %v", err)
  3023  	}
  3024  	defer unix.Closedir(dirStream)
  3025  
  3026  	dirfd, err := unix.Dirfd(dirStream)
  3027  	if err != nil {
  3028  		t.Fatalf("Dirfd: %v", err)
  3029  	}
  3030  	if dirfd < 0 {
  3031  		t.Fatalf("Dirfd: fd < 0, (fd = %v)", dirfd)
  3032  	}
  3033  
  3034  	if err := f.Close(); err != nil {
  3035  		t.Fatalf("Close: %v", err)
  3036  	}
  3037  
  3038  	err = unix.Unlinkat(dirfd, filepath.Base(f.Name()), 0)
  3039  	if err != nil {
  3040  		t.Fatalf("Unlinkat: %v", err)
  3041  	}
  3042  
  3043  	_, err = os.Open(f.Name())
  3044  	if err != nil {
  3045  		if !os.IsNotExist(err) {
  3046  			t.Errorf("Expected to get error \"EDC5129I No such file or directory\". Got: %v", err)
  3047  		}
  3048  	} else {
  3049  		t.Error("Unlinkat: Expected to get error \"EDC5129I No such file or directory\"")
  3050  	}
  3051  
  3052  	err = unix.Unlinkat(dirfd, tmpdir, unix.AT_REMOVEDIR)
  3053  	if err != nil {
  3054  		t.Fatalf("Unlinkat: %v", err)
  3055  	}
  3056  
  3057  	_, err = os.Open(tmpdir)
  3058  	if err != nil {
  3059  		if !os.IsNotExist(err) {
  3060  			t.Errorf("Expected to get error \"EDC5129I No such file or directory\". Got: %v", err)
  3061  		}
  3062  	} else {
  3063  		t.Error("Unlinkat: Expected to get error \"EDC5129I No such file or directory\"")
  3064  	}
  3065  }
  3066  
  3067  func TestRenameat(t *testing.T) {
  3068  	chtmpdir(t)
  3069  
  3070  	from, to := "renamefrom", "renameto"
  3071  
  3072  	touch(t, from)
  3073  
  3074  	err := unix.Renameat(unix.AT_FDCWD, from, unix.AT_FDCWD, to)
  3075  	if err != nil {
  3076  		t.Fatalf("Renameat: unexpected error: %v", err)
  3077  	}
  3078  
  3079  	_, err = os.Stat(to)
  3080  	if err != nil {
  3081  		t.Error(err)
  3082  	}
  3083  
  3084  	_, err = os.Stat(from)
  3085  	if err == nil {
  3086  		t.Errorf("Renameat: stat of renamed file %q unexpectedly succeeded", from)
  3087  	}
  3088  }
  3089  
  3090  func TestRenameat2(t *testing.T) {
  3091  	chtmpdir(t)
  3092  
  3093  	from, to := "renamefrom", "renameto"
  3094  
  3095  	touch(t, from)
  3096  
  3097  	err := unix.Renameat2(unix.AT_FDCWD, from, unix.AT_FDCWD, to, 0)
  3098  	if err != nil {
  3099  		t.Fatalf("Renameat2: unexpected error: %v", err)
  3100  	}
  3101  
  3102  	_, err = os.Stat(to)
  3103  	if err != nil {
  3104  		t.Error(err)
  3105  	}
  3106  
  3107  	_, err = os.Stat(from)
  3108  	if err == nil {
  3109  		t.Errorf("Renameat2: stat of renamed file %q unexpectedly succeeded", from)
  3110  	}
  3111  
  3112  	touch(t, from)
  3113  
  3114  	err = unix.Renameat2(unix.AT_FDCWD, from, unix.AT_FDCWD, to, unix.RENAME_NOREPLACE)
  3115  	if err != nil {
  3116  		if err.Error() != "EDC5117I File exists." {
  3117  			t.Errorf("Renameat2: expected to get error \"EDC5117I File exists.\" Got: %v", err)
  3118  		}
  3119  	} else {
  3120  		t.Errorf("Renameat2: Unexpected error: %v", err)
  3121  	}
  3122  }
  3123  
  3124  func TestFchmodat(t *testing.T) {
  3125  	chtmpdir(t)
  3126  
  3127  	touch(t, "file1")
  3128  	err := os.Symlink("file1", "symlink1")
  3129  	if err != nil {
  3130  		t.Fatal(err)
  3131  	}
  3132  
  3133  	mode := os.FileMode(0444)
  3134  	err = unix.Fchmodat(unix.AT_FDCWD, "symlink1", uint32(mode), 0)
  3135  	if err != nil {
  3136  		t.Fatalf("Fchmodat: unexpected error: %v", err)
  3137  	}
  3138  
  3139  	fi, err := os.Stat("file1")
  3140  	if err != nil {
  3141  		t.Fatal(err)
  3142  	}
  3143  
  3144  	if fi.Mode() != mode {
  3145  		t.Errorf("Fchmodat: failed to change file mode: expected %v, got %v", mode, fi.Mode())
  3146  	}
  3147  
  3148  	mode = os.FileMode(0644)
  3149  	didChmodSymlink := true
  3150  	err = unix.Fchmodat(unix.AT_FDCWD, "symlink1", uint32(mode), unix.AT_SYMLINK_NOFOLLOW)
  3151  	if err != nil {
  3152  		if err == unix.EOPNOTSUPP {
  3153  			didChmodSymlink = false
  3154  		} else {
  3155  			t.Fatalf("Fchmodat: unexpected error: %v", err)
  3156  		}
  3157  	}
  3158  
  3159  	if !didChmodSymlink {
  3160  		// Didn't change mode of the symlink. On Linux, the permissions
  3161  		// of a symbolic link are always 0777 according to symlink(7)
  3162  		mode = os.FileMode(0777)
  3163  	}
  3164  
  3165  	var st unix.Stat_t
  3166  	err = unix.Lstat("symlink1", &st)
  3167  	if err != nil {
  3168  		t.Fatal(err)
  3169  	}
  3170  
  3171  	got := os.FileMode(st.Mode & 0777)
  3172  	if got != mode {
  3173  		t.Errorf("Fchmodat: failed to change symlink mode: expected %v, got %v", mode, got)
  3174  	}
  3175  }
  3176  func TestPosix_openpt(t *testing.T) {
  3177  	masterfd, err := unix.Posix_openpt(unix.O_RDWR)
  3178  	if err != nil {
  3179  		t.Fatal(err)
  3180  	}
  3181  	defer unix.Close(masterfd)
  3182  	_, err = unix.Grantpt(masterfd)
  3183  	if err != nil {
  3184  		t.Fatal(err)
  3185  	}
  3186  	_, err = unix.Unlockpt(masterfd)
  3187  	if err != nil {
  3188  		t.Fatal(err)
  3189  	}
  3190  	slavename, err := unix.Ptsname(masterfd)
  3191  	if err != nil {
  3192  		t.Fatal(err)
  3193  	}
  3194  	fd, err := unix.Open(slavename, unix.O_RDWR, 0)
  3195  	if err != nil {
  3196  		t.Fatal(err)
  3197  	}
  3198  	unix.Close(fd)
  3199  }
  3200  
  3201  func compareStat_t(t *testing.T, otherStat string, st1, st2 *unix.Stat_t) {
  3202  	if st2.Dev != st1.Dev {
  3203  		t.Errorf("%s/Fstatat: got dev %v, expected %v", otherStat, st2.Dev, st1.Dev)
  3204  	}
  3205  	if st2.Ino != st1.Ino {
  3206  		t.Errorf("%s/Fstatat: got ino %v, expected %v", otherStat, st2.Ino, st1.Ino)
  3207  	}
  3208  	if st2.Mode != st1.Mode {
  3209  		t.Errorf("%s/Fstatat: got mode %v, expected %v", otherStat, st2.Mode, st1.Mode)
  3210  	}
  3211  	if st2.Uid != st1.Uid {
  3212  		t.Errorf("%s/Fstatat: got uid %v, expected %v", otherStat, st2.Uid, st1.Uid)
  3213  	}
  3214  	if st2.Gid != st1.Gid {
  3215  		t.Errorf("%s/Fstatat: got gid %v, expected %v", otherStat, st2.Gid, st1.Gid)
  3216  	}
  3217  	if st2.Size != st1.Size {
  3218  		t.Errorf("%s/Fstatat: got size %v, expected %v", otherStat, st2.Size, st1.Size)
  3219  	}
  3220  }
  3221  
  3222  func TestFstatat(t *testing.T) {
  3223  	chtmpdir(t)
  3224  
  3225  	touch(t, "file1")
  3226  
  3227  	var st1 unix.Stat_t
  3228  	err := unix.Stat("file1", &st1)
  3229  	if err != nil {
  3230  		t.Fatalf("Stat: %v", err)
  3231  	}
  3232  
  3233  	var st2 unix.Stat_t
  3234  	err = unix.Fstatat(unix.AT_FDCWD, "file1", &st2, 0)
  3235  	if err != nil {
  3236  		t.Fatalf("Fstatat: %v", err)
  3237  	}
  3238  
  3239  	compareStat_t(t, "Stat", &st1, &st2)
  3240  
  3241  	err = os.Symlink("file1", "symlink1")
  3242  	if err != nil {
  3243  		t.Fatal(err)
  3244  	}
  3245  
  3246  	err = unix.Lstat("symlink1", &st1)
  3247  	if err != nil {
  3248  		t.Fatalf("Lstat: %v", err)
  3249  	}
  3250  
  3251  	err = unix.Fstatat(unix.AT_FDCWD, "symlink1", &st2, unix.AT_SYMLINK_NOFOLLOW)
  3252  	if err != nil {
  3253  		t.Fatalf("Fstatat: %v", err)
  3254  	}
  3255  
  3256  	compareStat_t(t, "Lstat", &st1, &st2)
  3257  }
  3258  
  3259  func TestFreezeUnfreeze(t *testing.T) {
  3260  	rv, rc, rn := unix.Bpx4ptq(unix.QUIESCE_FREEZE, "FREEZE")
  3261  	if rc != 0 {
  3262  		t.Fatalf(fmt.Sprintf("Bpx4ptq FREEZE %v %v %v\n", rv, rc, rn))
  3263  	}
  3264  	rv, rc, rn = unix.Bpx4ptq(unix.QUIESCE_UNFREEZE, "UNFREEZE")
  3265  	if rc != 0 {
  3266  		t.Fatalf(fmt.Sprintf("Bpx4ptq UNFREEZE %v %v %v\n", rv, rc, rn))
  3267  	}
  3268  }
  3269  func TestPtrace(t *testing.T) {
  3270  	cmd := exec.Command("/bin/sleep", "1000")
  3271  	cmd.Stdout = os.Stdout
  3272  	err := cmd.Start()
  3273  	if err != nil {
  3274  		log.Fatal(err)
  3275  	}
  3276  	rv, rc, rn := unix.Bpx4ptr(unix.PT_ATTACH, int32(cmd.Process.Pid), unsafe.Pointer(uintptr(0)), unsafe.Pointer(uintptr(0)), unsafe.Pointer(uintptr(0)))
  3277  	if rc != 0 {
  3278  		t.Fatalf("ptrace: Bpx4ptr rv %d, rc %d, rn %d\n", rv, rc, rn)
  3279  	}
  3280  	cmd.Process.Kill()
  3281  }
  3282  
  3283  func TestFutimesat(t *testing.T) {
  3284  	// Create temp dir and file
  3285  	tempDir := t.TempDir()
  3286  
  3287  	dir, err := os.Open(tempDir)
  3288  	if err != nil {
  3289  		t.Fatal("Can not open tempDir: ", tempDir)
  3290  	}
  3291  	defer dir.Close()
  3292  
  3293  	tempFile, err := os.CreateTemp(tempDir, "futimesat_test_file")
  3294  	if err != nil {
  3295  		t.Fatalf("TempFile: %s", err.Error())
  3296  	}
  3297  	defer tempFile.Close()
  3298  
  3299  	// Set mod time to newTime
  3300  	newTime := time.Date(2001, time.Month(2), 15, 7, 7, 7, 0, time.UTC)
  3301  	err = unix.Futimesat(
  3302  		int(dir.Fd()),
  3303  		filepath.Base(tempFile.Name()),
  3304  		[]unix.Timeval{
  3305  			unix.Timeval{Sec: newTime.Unix(), Usec: 0},
  3306  			unix.Timeval{Sec: newTime.Unix(), Usec: 0},
  3307  		})
  3308  	if err != nil {
  3309  		t.Fatalf("TestFutimes: %v", err)
  3310  	}
  3311  
  3312  	// Compare mod time
  3313  	stats, err := tempFile.Stat()
  3314  	if err != nil {
  3315  		t.Fatalf("Stat: %v", err)
  3316  	}
  3317  
  3318  	modTime := stats.ModTime()
  3319  	if modTime.UTC() != newTime {
  3320  		t.Fatalf("TestFutimes: modTime = %v, want %v", modTime.UTC(), newTime)
  3321  	}
  3322  }
  3323  
  3324  func TestInotifyAccess(t *testing.T) {
  3325  	// Create temporary files
  3326  	tempFile, err := os.Create(filepath.Join(t.TempDir(), "inotify_access_test_file"))
  3327  	if err != nil {
  3328  		t.Fatalf("TempFile: %v", err)
  3329  	}
  3330  	defer tempFile.Close()
  3331  
  3332  	// Setup iNotify
  3333  	infd, err := unix.InotifyInit()
  3334  	if err != nil {
  3335  		t.Fatalf("InotifyInit1: %v", err)
  3336  	}
  3337  
  3338  	wd, err := unix.InotifyAddWatch(infd, tempFile.Name(), unix.IN_ACCESS)
  3339  	if err != nil {
  3340  		t.Fatalf("InotifyAddWatch: %v", err)
  3341  	}
  3342  
  3343  	// Trigger Event
  3344  	n, err := tempFile.Write([]byte("Writing before reading"))
  3345  	if err != nil {
  3346  		t.Fatalf("Write: %v", err)
  3347  	}
  3348  	if n <= 0 {
  3349  		t.Fatalf("Did not write any data")
  3350  	}
  3351  	tempFile.Seek(0, 0)
  3352  
  3353  	buf := make([]byte, 64)
  3354  	n, err = tempFile.Read(buf)
  3355  	if err != nil {
  3356  		t.Fatalf("Read: %v", err)
  3357  	}
  3358  	if n <= 0 {
  3359  		t.Fatalf("Did not read any data")
  3360  	}
  3361  
  3362  	// Expect event
  3363  	buf = make([]byte, unix.SizeofInotifyEvent)
  3364  	n, err = unix.Read(infd, buf[:])
  3365  	if n == -1 {
  3366  		t.Fatalf("No event was read from the iNotify fd")
  3367  	}
  3368  
  3369  	// Remove Watch
  3370  	if _, err = unix.InotifyRmWatch(infd, uint32(wd)); err != nil {
  3371  		t.Fatalf("InotifyRmWatch: %v", err)
  3372  	}
  3373  }
  3374  
  3375  func TestAccess(t *testing.T) {
  3376  	tempFile, err := os.Create(filepath.Join(t.TempDir(), "test_access"))
  3377  	if err != nil {
  3378  		t.Fatal("fail to create temp file ", tempFile)
  3379  	}
  3380  	defer tempFile.Close()
  3381  	err = unix.Access(tempFile.Name(), unix.R_OK|unix.W_OK)
  3382  	if err != nil {
  3383  		t.Fatalf("error when access %s: %v", tempFile.Name(), err)
  3384  	}
  3385  	err = unix.Access("not_exist_file", unix.F_OK)
  3386  	if err == nil {
  3387  		t.Fatalf("error when access not exist file: %v", err)
  3388  	}
  3389  }
  3390  
  3391  func TestCreat(t *testing.T) {
  3392  	tempFile, err := os.Create(filepath.Join(t.TempDir(), "test_create"))
  3393  	if err != nil {
  3394  		t.Fatal("fail to create temp file ", tempFile)
  3395  	}
  3396  	defer tempFile.Close()
  3397  
  3398  	tempFile.Write([]byte("random1"))
  3399  	if err != nil {
  3400  		t.Fatal("error write to file: ", err)
  3401  	}
  3402  	// creat
  3403  	fd, err := unix.Creat(tempFile.Name(), 0o777)
  3404  	if err != nil {
  3405  		t.Fatal("Creat error: ", err)
  3406  	}
  3407  	writeContent := []byte("random2")
  3408  	n, err := unix.Write(fd, writeContent)
  3409  	if err != nil {
  3410  		t.Fatal("Write error: ", err)
  3411  	} else if n <= 0 {
  3412  		t.Fatal("Write error: 0 is written")
  3413  	}
  3414  	// Using creat is the equivalent of using the open callable service
  3415  	// with the create, truncate, and write-only options:
  3416  	// so we can not use the same file descriptor
  3417  	b, err := os.ReadFile(tempFile.Name())
  3418  	if err != nil {
  3419  		t.Fatal("Read error: ", err)
  3420  	}
  3421  	if n <= 0 {
  3422  		t.Fatal("Creat error: Cannot truncate file")
  3423  	}
  3424  	if string(b) != string(writeContent) {
  3425  		t.Fatal("data mismatch: expect ", string(writeContent), " actual: ", string(b))
  3426  	}
  3427  
  3428  	// testing file create function
  3429  	newFile := tempFile.Name() + "2"
  3430  	fd2, err := unix.Creat(newFile, 0o777)
  3431  	if err != nil {
  3432  		t.Fatal("Creat error: ", err)
  3433  	}
  3434  	writeContent = []byte("random3")
  3435  	n, err = unix.Write(fd2, writeContent)
  3436  	if err != nil {
  3437  		t.Fatal("Write error: ", err)
  3438  	} else if n <= 0 {
  3439  		t.Fatal("Write error: 0 is written")
  3440  	}
  3441  
  3442  	b, err = os.ReadFile(newFile)
  3443  	if err != nil {
  3444  		t.Fatal("Read error: ", err)
  3445  	}
  3446  	if n <= 0 {
  3447  		t.Fatal("Creat error: Cannot truncate file")
  3448  	}
  3449  	if string(b) != string(writeContent) {
  3450  		t.Fatal("data mismatch: expect ", string(writeContent), " actual: ", string(b))
  3451  	}
  3452  
  3453  }
  3454  
  3455  func TestGetPageSize(t *testing.T) {
  3456  	size := unix.Getpagesize()
  3457  	if size <= 0 {
  3458  		t.Fatal("get page size return: ", size)
  3459  	}
  3460  }
  3461  
  3462  func TestSyscallSetegid(t *testing.T) {
  3463  	err := unix.Setegid(unix.Getgid())
  3464  	if err != nil {
  3465  		t.Fatal("error setting euid: ", err)
  3466  	}
  3467  	id := unix.Getegid()
  3468  	if id != unix.Getgid() {
  3469  		t.Fatal("euid mismatch: expect ", unix.Getgid(), ", actual ", id)
  3470  	}
  3471  }
  3472  
  3473  func TestSyscallSeteuid(t *testing.T) {
  3474  	err := unix.Seteuid(unix.Getuid())
  3475  	if err != nil {
  3476  		t.Fatal("error setting euid: ", err)
  3477  	}
  3478  	id := unix.Geteuid()
  3479  	if id != unix.Getuid() {
  3480  		t.Fatal("euid mismatch: expect ", unix.Getuid(), ", actual ", id)
  3481  	}
  3482  }
  3483  
  3484  func TestSyscallSetgid(t *testing.T) {
  3485  	err := unix.Setgid(unix.Getegid())
  3486  	if err != nil {
  3487  		t.Fatal("error setting gid: ", err)
  3488  	}
  3489  	id := unix.Getgid()
  3490  	if id != unix.Getegid() {
  3491  		t.Fatal("guid mismatch: expect 0, actual ", id)
  3492  	}
  3493  }
  3494  
  3495  func TestSyscallSetpgid(t *testing.T) {
  3496  	if euid != 0 {
  3497  		t.Skip("euid != 0")
  3498  	}
  3499  
  3500  	pid := unix.Getpid()
  3501  	pgid, _ := unix.Getpgid(pid)
  3502  	err := unix.Setpgid(pid, pgid)
  3503  	if err != nil {
  3504  		t.Fatal("error setting pgid: ", err)
  3505  	}
  3506  	id, err := unix.Getpgid(pid)
  3507  	if err != nil {
  3508  		t.Fatal("Getpgid error: ", err)
  3509  	}
  3510  	if gid, _ := unix.Getpgid(pid); gid != id {
  3511  		t.Fatal("pgid mismatch: expect ", gid, ", actual ", id)
  3512  	}
  3513  }
  3514  
  3515  func TestSyscallSetregid(t *testing.T) {
  3516  	gid := unix.Getgid()
  3517  	err := unix.Setregid(gid, gid)
  3518  	if err != nil {
  3519  		t.Fatal("error setting regid: ", err)
  3520  	}
  3521  	// currently missing Getresgid can not validate
  3522  	// The get function also not provided in syscall package as well as other platform
  3523  }
  3524  
  3525  func TestSyscallSetreuid(t *testing.T) {
  3526  	uid := unix.Getuid()
  3527  	err := unix.Setreuid(uid, uid)
  3528  	if err != nil {
  3529  		t.Fatal("error setting reuid: ", err)
  3530  	}
  3531  	// currently missing Getresgid can not validate
  3532  	// The get function also not provided in syscall package as well as other platform
  3533  
  3534  }
  3535  
  3536  func TestWriteAndSync(t *testing.T) {
  3537  	// this test cannot really test sync function
  3538  	// since unix.write does not require a sync function to actual write to the file
  3539  
  3540  	tempFile, err := os.Create(filepath.Join(t.TempDir(), "test_write_and_sync"))
  3541  	if err != nil {
  3542  		t.Fatal("error: ", err)
  3543  	}
  3544  	defer tempFile.Close()
  3545  	fileContent := "hello world"
  3546  	n, err := unix.Write(int(tempFile.Fd()), []byte(fileContent))
  3547  	if err != nil {
  3548  		t.Fatal("write error: ", err)
  3549  	}
  3550  	if n != len(fileContent) {
  3551  		t.Fatal("error: write length mismatch")
  3552  	}
  3553  	unix.Sync()
  3554  
  3555  	b := make([]byte, len(fileContent), 256)
  3556  	unix.Seek(int(tempFile.Fd()), 0, 0)
  3557  	_, err = unix.Read(int(tempFile.Fd()), b)
  3558  	if err != nil {
  3559  		t.Fatal("read error: ", err)
  3560  	}
  3561  	if string(b) != fileContent {
  3562  		t.Fatal("file data mismatch: expect ", fileContent, " actual", string(b))
  3563  	}
  3564  }
  3565  
  3566  func TestTimes(t *testing.T) {
  3567  	var startTimes, endTimes unix.Tms
  3568  
  3569  	// Get the start time
  3570  	_, err := unix.Times(&startTimes)
  3571  	if err != nil {
  3572  		t.Fatal("times error: ", err)
  3573  	}
  3574  
  3575  	sum := 0
  3576  	// Perform some operations
  3577  	for i := 0; i < 1000000000; i++ {
  3578  		sum += i % 100
  3579  	}
  3580  
  3581  	// Get the end time
  3582  	_, err = unix.Times(&endTimes)
  3583  	if err != nil {
  3584  		t.Fatal("times error: ", err)
  3585  	}
  3586  
  3587  	if int64(endTimes.Utime)-int64(startTimes.Utime) <= 0 || int64(endTimes.Stime)-int64(startTimes.Stime) <= 0 {
  3588  		t.Fatal("times error: endtime - starttime <= 0")
  3589  	}
  3590  }
  3591  
  3592  func TestMlock(t *testing.T) {
  3593  	if euid != 0 {
  3594  		t.Skip("euid != 0")
  3595  	}
  3596  
  3597  	twoM := 2 * 1024 * 1024
  3598  	b := make([]byte, twoM, twoM)
  3599  	for i := 0; i < twoM; i++ {
  3600  		b[i] = byte(i % 127)
  3601  	}
  3602  	err := unix.Mlock(b)
  3603  	if err != nil {
  3604  		t.Fatal("mlock error: ", err)
  3605  	}
  3606  	for i := 0; i < twoM; i++ {
  3607  		if b[i] != byte(i%127) {
  3608  			t.Fatal("error: memory not correct: expect ", i%127, " actual ", b[i])
  3609  		}
  3610  	}
  3611  
  3612  	err = unix.Munlock(b)
  3613  	if err != nil {
  3614  		t.Fatal("munlock error: ", err)
  3615  	}
  3616  	for i := 0; i < twoM; i++ {
  3617  		if b[i] != byte(i%127) {
  3618  			t.Fatal("error: memory not correct: expect ", i%127, " actual ", b[i])
  3619  		}
  3620  	}
  3621  
  3622  }
  3623  
  3624  func TestMlockAll(t *testing.T) {
  3625  	if euid != 0 {
  3626  		t.Skip("euid != 0")
  3627  	}
  3628  
  3629  	twoM := 2 * 1024 * 1024
  3630  	b := make([]byte, twoM, twoM)
  3631  	for i := 0; i < twoM; i++ {
  3632  		b[i] = byte(i % 127)
  3633  	}
  3634  	// Mlockall flag do not have zos semantics, so passing 0
  3635  	err := unix.Mlockall(0)
  3636  	if err != nil {
  3637  		t.Fatal("mlock error: ", err)
  3638  	}
  3639  	for i := 0; i < twoM; i++ {
  3640  		if b[i] != byte(i%127) {
  3641  			t.Fatal("error: memory not correct: expect ", i%127, " actual ", b[i])
  3642  		}
  3643  	}
  3644  
  3645  	err = unix.Munlockall()
  3646  	if err != nil {
  3647  		t.Fatal("munlock error: ", err)
  3648  	}
  3649  	for i := 0; i < twoM; i++ {
  3650  		if b[i] != byte(i%127) {
  3651  			t.Fatal("error: memory not correct: expect ", i%127, " actual ", b[i])
  3652  		}
  3653  	}
  3654  }
  3655  
  3656  func TestGettid(t *testing.T) {
  3657  	tid := unix.Gettid()
  3658  	if tid < 0 {
  3659  		t.Fatal("error: tid less than 0: tid = ", tid)
  3660  	}
  3661  }
  3662  
  3663  func TestSetns(t *testing.T) {
  3664  	// TODO (joon): for some reason changing ipc on zos fails
  3665  	namespaces := map[string]int{
  3666  		// "ipc": unix.CLONE_NEWIPC,
  3667  		"uts": unix.CLONE_NEWUTS,
  3668  		"net": unix.CLONE_NEWNET,
  3669  		// "pid": unix.CLONE_NEWPID,
  3670  	}
  3671  
  3672  	if unix.Geteuid() != 0 {
  3673  		t.Skip("euid != 0")
  3674  	}
  3675  
  3676  	if os.Getenv("SETNS_HELPER_PROCESS") == "1" {
  3677  		pid := unix.Getppid()
  3678  
  3679  		fmt.Scanln()
  3680  
  3681  		for k, v := range namespaces {
  3682  			path := fmt.Sprintf("/proc/%d/ns/%s", pid, k)
  3683  			fd, err := unix.Open(path, unix.O_RDONLY, 0)
  3684  			err = unix.Setns(fd, v)
  3685  			if err != nil {
  3686  				t.Fatalf("Setns failed: %v", err)
  3687  			}
  3688  		}
  3689  		for {
  3690  		}
  3691  	}
  3692  
  3693  	exe, err := os.Executable()
  3694  	if err != nil {
  3695  		t.Fatal(err)
  3696  	}
  3697  	cmd := exec.Command(exe, "-test.run=^TestSetns$")
  3698  	cmd.Env = append(os.Environ(), "SETNS_HELPER_PROCESS=1")
  3699  	stdin, err := cmd.StdinPipe()
  3700  	if err != nil {
  3701  		t.Fatalf("Failed to get stdin for helper process: %v\n", err)
  3702  	}
  3703  
  3704  	if err := cmd.Start(); err != nil {
  3705  		t.Fatalf("failed to create helper process: %v\n", err)
  3706  	}
  3707  	defer cmd.Process.Kill()
  3708  
  3709  	ppid := unix.Getpid()
  3710  	pid := cmd.Process.Pid
  3711  
  3712  	for k, _ := range namespaces {
  3713  		hPath := fmt.Sprintf("/proc/%d/ns/%s", pid, k)
  3714  		pPath := fmt.Sprintf("/proc/%d/ns/%s", ppid, k)
  3715  
  3716  		hFI, _ := os.Stat(hPath)
  3717  		pFI, _ := os.Stat(pPath)
  3718  
  3719  		if !os.SameFile(hFI, pFI) {
  3720  			t.Fatalf("namespace links for %s did not match before calling Unshare in parent\n", k)
  3721  		}
  3722  	}
  3723  
  3724  	unix.Unshare(unix.CLONE_NEWUTS | unix.CLONE_NEWNET)
  3725  
  3726  	for k, _ := range namespaces {
  3727  		hPath := fmt.Sprintf("/proc/%d/ns/%s", pid, k)
  3728  		pPath := fmt.Sprintf("/proc/%d/ns/%s", ppid, k)
  3729  
  3730  		hFI, _ := os.Stat(hPath)
  3731  		pFI, _ := os.Stat(pPath)
  3732  
  3733  		if os.SameFile(hFI, pFI) {
  3734  			t.Fatalf("Setns: namespace link for %s matched after calling Unshare but before Setns\n", k)
  3735  		}
  3736  	}
  3737  
  3738  	stdin.Write([]byte("\n"))
  3739  	stdin.Close()
  3740  	time.Sleep(1000 * time.Millisecond)
  3741  
  3742  	for k, _ := range namespaces {
  3743  		hPath := fmt.Sprintf("/proc/%d/ns/%s", pid, k)
  3744  		pPath := fmt.Sprintf("/proc/%d/ns/%s", ppid, k)
  3745  
  3746  		hFI, _ := os.Stat(hPath)
  3747  		pFI, _ := os.Stat(pPath)
  3748  
  3749  		if !os.SameFile(hFI, pFI) {
  3750  			t.Errorf("Setns: namespace link for %s did not match after calling Setns\n", k)
  3751  		}
  3752  	}
  3753  
  3754  }
  3755  
  3756  func stringsFromByteSlice(buf []byte) []string {
  3757  	var result []string
  3758  	off := 0
  3759  	for i, b := range buf {
  3760  		if b == 0 {
  3761  			result = append(result, string(buf[off:i]))
  3762  			off = i + 1
  3763  		}
  3764  	}
  3765  	return result
  3766  }
  3767  
  3768  // This test is based on mmap_unix_test, but tweaked for z/OS, which does not support memadvise
  3769  // or anonymous mmapping.
  3770  func TestConsole2(t *testing.T) {
  3771  	var cmsg unix.ConsMsg2
  3772  	var nullptr *byte
  3773  	var cmsg_cmd uint32
  3774  
  3775  	cmsg_rout := [2]uint32{1, 0}
  3776  	cmsg_desc := [2]uint32{12, 0}
  3777  	cmsg.Cm2Format = unix.CONSOLE_FORMAT_2
  3778  	msg := "__console2 test"
  3779  	cmsg.Cm2Msg = &unix.ZosStringToEbcdicBytes(msg, true)[0]
  3780  	cmsg.Cm2Msglength = uint32(len(msg))
  3781  	cmsg.Cm2Routcde = &cmsg_rout[0]
  3782  	cmsg.Cm2Descr = &cmsg_desc[0]
  3783  	cmsg.Cm2Token = 0
  3784  
  3785  	err := unix.Console2(&cmsg, nullptr, &cmsg_cmd)
  3786  	if err != nil {
  3787  		t.Fatalf("__console2: %v", err)
  3788  	}
  3789  }
  3790  
  3791  func TestConsole2modify(t *testing.T) {
  3792  	if os.Getenv("ZOS_MANUAL_TEST") != "1" {
  3793  		t.Skip("This test is not run unless env-var ZOS_MANUAL_TEST=1 is set")
  3794  	}
  3795  
  3796  	job, err := unix.ZosJobname()
  3797  	if err != nil {
  3798  		t.Fatalf("Failed to get jobname  %v", err)
  3799  	}
  3800  
  3801  	var cmsg unix.ConsMsg2
  3802  	var cmsg_cmd uint32
  3803  	cmsg_rout := [2]uint32{1, 0}
  3804  	cmsg_desc := [2]uint32{12, 0}
  3805  	cmsg.Cm2Format = unix.CONSOLE_FORMAT_2
  3806  	msg := "Issue console command 'F " + job + ",APPL=123' to continue"
  3807  	cmsg.Cm2Msg = &unix.ZosStringToEbcdicBytes(msg, true)[0]
  3808  	cmsg.Cm2Msglength = uint32(len(msg))
  3809  	cmsg.Cm2Routcde = &cmsg_rout[0]
  3810  	cmsg.Cm2Descr = &cmsg_desc[0]
  3811  	cmsg.Cm2Token = 0
  3812  
  3813  	var modstr [128]byte
  3814  	t.Logf("Issue console command 'F %s,APPL=123' to continue\n", job)
  3815  
  3816  	err = unix.Console2(&cmsg, &modstr[0], &cmsg_cmd)
  3817  	if err != nil {
  3818  		t.Fatalf("__console2: %v", err)
  3819  	}
  3820  
  3821  	recv := unix.ZosEbcdicBytesToString(modstr[:], true)
  3822  	if recv != "123" || cmsg_cmd != 1 {
  3823  		t.Fatalf("__console2 modify: Got %s %x, Expect 123 1\n", unix.ZosEbcdicBytesToString(modstr[:], true), cmsg_cmd)
  3824  	}
  3825  
  3826  	t.Logf("Got %s %x\n", unix.ZosEbcdicBytesToString(modstr[:], true), cmsg_cmd)
  3827  }
  3828  func TestTty(t *testing.T) {
  3829  	ptmxfd, err := unix.Posix_openpt(unix.O_RDWR)
  3830  	if err != nil {
  3831  		t.Fatalf("Posix_openpt %+v\n", err)
  3832  	}
  3833  	t.Logf("ptmxfd %v\n", ptmxfd)
  3834  
  3835  	// convert to EBCDIC
  3836  	cvtreq := unix.F_cnvrt{Cvtcmd: unix.SETCVTON, Pccsid: 0, Fccsid: 1047}
  3837  	if _, err = unix.Fcntl(uintptr(ptmxfd), unix.F_CONTROL_CVT, &cvtreq); err != nil {
  3838  		t.Fatalf("fcntl F_CONTROL_CVT %+v\n", err)
  3839  	}
  3840  	p := os.NewFile(uintptr(ptmxfd), "/dev/ptmx")
  3841  	if p == nil {
  3842  		t.Fatalf("NewFile %d /dev/ptmx failed\n", ptmxfd)
  3843  	}
  3844  
  3845  	// In case of error after this point, make sure we close the ptmx fd.
  3846  	defer func() {
  3847  		if err != nil {
  3848  			_ = p.Close() // Best effort.
  3849  		}
  3850  	}()
  3851  	sname, err := unix.Ptsname(ptmxfd)
  3852  	if err != nil {
  3853  		t.Fatalf("Ptsname %+v\n", err)
  3854  	}
  3855  	t.Logf("sname %v\n", sname)
  3856  
  3857  	_, err = unix.Grantpt(ptmxfd)
  3858  	if err != nil {
  3859  		t.Fatalf("Grantpt %+v\n", err)
  3860  	}
  3861  
  3862  	if _, err = unix.Unlockpt(ptmxfd); err != nil {
  3863  		t.Fatalf("Unlockpt %+v\n", err)
  3864  	}
  3865  
  3866  	ptsfd, err := syscall.Open(sname, os.O_RDWR|syscall.O_NOCTTY, 0)
  3867  	if err != nil {
  3868  		t.Fatalf("Open %s %+v\n", sname, err)
  3869  	}
  3870  	if _, err = unix.Fcntl(uintptr(ptsfd), unix.F_CONTROL_CVT, &cvtreq); err != nil {
  3871  		t.Fatalf("fcntl F_CONTROL_CVT ptsfd %+v\n", err)
  3872  	}
  3873  
  3874  	tt := os.NewFile(uintptr(ptsfd), sname)
  3875  	if err != nil {
  3876  		t.Fatalf("NewFile %d %+v %+v\n", ptsfd, sname, err)
  3877  	}
  3878  	text := []byte("11111111")
  3879  
  3880  	n, err := tt.Write(text)
  3881  	if err != nil {
  3882  		t.Fatalf("ptsfd Write %+v\n", err)
  3883  	}
  3884  	t.Logf("bytes %d\n", n)
  3885  
  3886  	var buffer [1024]byte
  3887  
  3888  	n, err = p.Read(buffer[:n])
  3889  	if err != nil {
  3890  		t.Fatalf("ptmx read %+v\n", err)
  3891  	}
  3892  	t.Logf("Buffer %+v\n", buffer[:n])
  3893  
  3894  	if !bytes.Equal(text, buffer[:n]) {
  3895  		t.Fatalf("Expected %+v, read %+v\n", text, buffer[:n])
  3896  
  3897  	}
  3898  
  3899  }
  3900  
  3901  func TestSendfile(t *testing.T) {
  3902  	srcContent := "hello, world"
  3903  	srcFile, err := os.Create(filepath.Join(t.TempDir(), "source"))
  3904  	if err != nil {
  3905  		t.Fatal("error: ", err)
  3906  	}
  3907  	defer srcFile.Close()
  3908  
  3909  	dstFile, err := os.Create(filepath.Join(t.TempDir(), "dst"))
  3910  	if err != nil {
  3911  		t.Fatal("error: ", err)
  3912  	}
  3913  	defer dstFile.Close()
  3914  
  3915  	err = os.WriteFile(srcFile.Name(), []byte(srcContent), 0644)
  3916  	if err != nil {
  3917  		t.Fatal("error: ", err)
  3918  	}
  3919  
  3920  	n, err := unix.Sendfile(int(dstFile.Fd()), int(srcFile.Fd()), nil, len(srcContent))
  3921  	if n != len(srcContent) {
  3922  		t.Fatal("error: mismatch content length want ", len(srcContent), " got ", n)
  3923  	}
  3924  	if err != nil {
  3925  		t.Fatal("error: ", err)
  3926  	}
  3927  
  3928  	b, err := os.ReadFile(dstFile.Name())
  3929  	if err != nil {
  3930  		t.Fatal("error: ", err)
  3931  	}
  3932  
  3933  	content := string(b)
  3934  	if content != srcContent {
  3935  		t.Fatal("content mismatch: ", content, " vs ", srcContent)
  3936  	}
  3937  }
  3938  
  3939  func TestSendfileSocket(t *testing.T) {
  3940  	// Set up source data file.
  3941  	name := filepath.Join(t.TempDir(), "source")
  3942  	const contents = "contents"
  3943  	err := os.WriteFile(name, []byte(contents), 0666)
  3944  	if err != nil {
  3945  		t.Fatal(err)
  3946  	}
  3947  
  3948  	done := make(chan bool)
  3949  
  3950  	// Start server listening on a socket.
  3951  	ln, err := net.Listen("tcp", "127.0.0.1:0")
  3952  	if err != nil {
  3953  		t.Skipf("listen failed: %s\n", err)
  3954  	}
  3955  	defer ln.Close()
  3956  	go func() {
  3957  		conn, err := ln.Accept()
  3958  		if err != nil {
  3959  			t.Errorf("failed to accept: %v", err)
  3960  			return
  3961  		}
  3962  		defer conn.Close()
  3963  		b, err := io.ReadAll(conn)
  3964  		if err != nil {
  3965  			t.Errorf("failed to read: %v", err)
  3966  			return
  3967  		}
  3968  		if string(b) != contents {
  3969  			t.Errorf("contents not transmitted: got %s (len=%d), want %s", string(b), len(b), contents)
  3970  		}
  3971  		done <- true
  3972  	}()
  3973  
  3974  	// Open source file.
  3975  	src, err := os.Open(name)
  3976  	if err != nil {
  3977  		t.Fatal(err)
  3978  	}
  3979  
  3980  	// Send source file to server.
  3981  	conn, err := net.Dial("tcp", ln.Addr().String())
  3982  	if err != nil {
  3983  		t.Fatal(err)
  3984  	}
  3985  	file, err := conn.(*net.TCPConn).File()
  3986  	if err != nil {
  3987  		t.Fatal(err)
  3988  	}
  3989  	var off int64
  3990  	n, err := unix.Sendfile(int(file.Fd()), int(src.Fd()), &off, len(contents))
  3991  	if err != nil {
  3992  		t.Errorf("Sendfile failed %s\n", err)
  3993  	}
  3994  	if n != len(contents) {
  3995  		t.Errorf("written count wrong: want %d, got %d", len(contents), n)
  3996  	}
  3997  	// Note: off is updated on some systems and not others. Oh well.
  3998  	// Linux: increments off by the amount sent.
  3999  	// Darwin: leaves off unchanged.
  4000  	// It would be nice to fix Darwin if we can.
  4001  	if off != 0 && off != int64(len(contents)) {
  4002  		t.Errorf("offset wrong: god %d, want %d or %d", off, 0, len(contents))
  4003  	}
  4004  	// The cursor position should be unchanged.
  4005  	pos, err := src.Seek(0, 1)
  4006  	if err != nil {
  4007  		t.Errorf("can't get cursor position %s\n", err)
  4008  	}
  4009  	if pos != 0 {
  4010  		t.Errorf("cursor position wrong: got %d, want 0", pos)
  4011  	}
  4012  
  4013  	file.Close() // Note: required to have the close below really send EOF to the server.
  4014  	conn.Close()
  4015  
  4016  	// Wait for server to close.
  4017  	<-done
  4018  }
  4019  

View as plain text