mirror of
https://github.com/rwinkhart/sys.git
synced 2026-08-28 04:46:44 -04:00
unix: add support for zos/s390x
This adds sys/unix support for zos/s390x. These changes should not affect other platforms. Fixes golang/go#43230 Change-Id: If1c1d9df134fbc44f95ca1b214e836508696da93 Reviewed-on: https://go-review.googlesource.com/c/sys/+/275992 Trust: Emmanuel Odeke <emmanuel@orijtech.com> Trust: Tobias Klauser <tobias.klauser@gmail.com> Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com> Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
committed by
Emmanuel Odeke
parent
eede4237b3
commit
5640770f5e
+2
-2
@@ -2,8 +2,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris) && go1.9
|
//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) && go1.9
|
||||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
// +build go1.9
|
// +build go1.9
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|||||||
@@ -0,0 +1,426 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build zos && s390x && gc
|
||||||
|
// +build zos
|
||||||
|
// +build s390x
|
||||||
|
// +build gc
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
#define PSALAA 1208(R0)
|
||||||
|
#define GTAB64(x) 80(x)
|
||||||
|
#define LCA64(x) 88(x)
|
||||||
|
#define CAA(x) 8(x)
|
||||||
|
#define EDCHPXV(x) 1016(x) // in the CAA
|
||||||
|
#define SAVSTACK_ASYNC(x) 336(x) // in the LCA
|
||||||
|
|
||||||
|
// SS_*, where x=SAVSTACK_ASYNC
|
||||||
|
#define SS_LE(x) 0(x)
|
||||||
|
#define SS_GO(x) 8(x)
|
||||||
|
#define SS_ERRNO(x) 16(x)
|
||||||
|
#define SS_ERRNOJR(x) 20(x)
|
||||||
|
|
||||||
|
#define LE_CALL BYTE $0x0D; BYTE $0x76; // BL R7, R6
|
||||||
|
|
||||||
|
TEXT ·clearErrno(SB),NOSPLIT,$0-0
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVD $0, 0(R3)
|
||||||
|
RET
|
||||||
|
|
||||||
|
// Returns the address of errno in R3.
|
||||||
|
TEXT addrerrno<>(SB),NOSPLIT|NOFRAME,$0-0
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get __errno FuncDesc.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
ADD $(0x156*16), R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Switch to saved LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Call __errno function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
|
||||||
|
// Switch back to Go stack.
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_syscall(SB),NOSPLIT,$0-56
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+32(FP)
|
||||||
|
MOVD R0, r2+40(FP)
|
||||||
|
MOVD R0, err+48(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+48(FP)
|
||||||
|
done:
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_rawsyscall(SB),NOSPLIT,$0-56
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+32(FP)
|
||||||
|
MOVD R0, r2+40(FP)
|
||||||
|
MOVD R0, err+48(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+48(FP)
|
||||||
|
done:
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_syscall6(SB),NOSPLIT,$0-80
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Fill in parameter list.
|
||||||
|
MOVD a4+32(FP), R12
|
||||||
|
MOVD R12, (2176+24)(R4)
|
||||||
|
MOVD a5+40(FP), R12
|
||||||
|
MOVD R12, (2176+32)(R4)
|
||||||
|
MOVD a6+48(FP), R12
|
||||||
|
MOVD R12, (2176+40)(R4)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+56(FP)
|
||||||
|
MOVD R0, r2+64(FP)
|
||||||
|
MOVD R0, err+72(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+72(FP)
|
||||||
|
done:
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_rawsyscall6(SB),NOSPLIT,$0-80
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Fill in parameter list.
|
||||||
|
MOVD a4+32(FP), R12
|
||||||
|
MOVD R12, (2176+24)(R4)
|
||||||
|
MOVD a5+40(FP), R12
|
||||||
|
MOVD R12, (2176+32)(R4)
|
||||||
|
MOVD a6+48(FP), R12
|
||||||
|
MOVD R12, (2176+40)(R4)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+56(FP)
|
||||||
|
MOVD R0, r2+64(FP)
|
||||||
|
MOVD R0, err+72(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL ·rrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+72(FP)
|
||||||
|
done:
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_syscall9(SB),NOSPLIT,$0
|
||||||
|
BL runtime·entersyscall(SB)
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Fill in parameter list.
|
||||||
|
MOVD a4+32(FP), R12
|
||||||
|
MOVD R12, (2176+24)(R4)
|
||||||
|
MOVD a5+40(FP), R12
|
||||||
|
MOVD R12, (2176+32)(R4)
|
||||||
|
MOVD a6+48(FP), R12
|
||||||
|
MOVD R12, (2176+40)(R4)
|
||||||
|
MOVD a7+56(FP), R12
|
||||||
|
MOVD R12, (2176+48)(R4)
|
||||||
|
MOVD a8+64(FP), R12
|
||||||
|
MOVD R12, (2176+56)(R4)
|
||||||
|
MOVD a9+72(FP), R12
|
||||||
|
MOVD R12, (2176+64)(R4)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+80(FP)
|
||||||
|
MOVD R0, r2+88(FP)
|
||||||
|
MOVD R0, err+96(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+96(FP)
|
||||||
|
done:
|
||||||
|
BL runtime·exitsyscall(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·syscall_rawsyscall9(SB),NOSPLIT,$0
|
||||||
|
MOVD a1+8(FP), R1
|
||||||
|
MOVD a2+16(FP), R2
|
||||||
|
MOVD a3+24(FP), R3
|
||||||
|
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get function.
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD EDCHPXV(R9), R9
|
||||||
|
MOVD trap+0(FP), R5
|
||||||
|
SLD $4, R5
|
||||||
|
ADD R5, R9
|
||||||
|
LMG 0(R9), R5, R6
|
||||||
|
|
||||||
|
// Restore LE stack.
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R4
|
||||||
|
MOVD $0, 0(R9)
|
||||||
|
|
||||||
|
// Fill in parameter list.
|
||||||
|
MOVD a4+32(FP), R12
|
||||||
|
MOVD R12, (2176+24)(R4)
|
||||||
|
MOVD a5+40(FP), R12
|
||||||
|
MOVD R12, (2176+32)(R4)
|
||||||
|
MOVD a6+48(FP), R12
|
||||||
|
MOVD R12, (2176+40)(R4)
|
||||||
|
MOVD a7+56(FP), R12
|
||||||
|
MOVD R12, (2176+48)(R4)
|
||||||
|
MOVD a8+64(FP), R12
|
||||||
|
MOVD R12, (2176+56)(R4)
|
||||||
|
MOVD a9+72(FP), R12
|
||||||
|
MOVD R12, (2176+64)(R4)
|
||||||
|
|
||||||
|
// Call function.
|
||||||
|
LE_CALL
|
||||||
|
NOPH
|
||||||
|
XOR R0, R0 // Restore R0 to $0.
|
||||||
|
MOVD R4, 0(R9) // Save stack pointer.
|
||||||
|
|
||||||
|
MOVD R3, r1+80(FP)
|
||||||
|
MOVD R0, r2+88(FP)
|
||||||
|
MOVD R0, err+96(FP)
|
||||||
|
MOVW R3, R4
|
||||||
|
CMP R4, $-1
|
||||||
|
BNE done
|
||||||
|
BL addrerrno<>(SB)
|
||||||
|
MOVWZ 0(R3), R3
|
||||||
|
MOVD R3, err+96(FP)
|
||||||
|
done:
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
|
||||||
|
TEXT ·svcCall(SB),NOSPLIT,$0
|
||||||
|
BL runtime·save_g(SB) // Save g and stack pointer
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD R15, 0(R9)
|
||||||
|
|
||||||
|
MOVD argv+8(FP), R1 // Move function arguments into registers
|
||||||
|
MOVD dsa+16(FP), g
|
||||||
|
MOVD fnptr+0(FP), R15
|
||||||
|
|
||||||
|
BYTE $0x0D // Branch to function
|
||||||
|
BYTE $0xEF
|
||||||
|
|
||||||
|
BL runtime·load_g(SB) // Restore g and stack pointer
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
MOVD SAVSTACK_ASYNC(R8), R9
|
||||||
|
MOVD 0(R9), R15
|
||||||
|
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func svcLoad(name *byte) unsafe.Pointer
|
||||||
|
TEXT ·svcLoad(SB),NOSPLIT,$0
|
||||||
|
MOVD R15, R2 // Save go stack pointer
|
||||||
|
MOVD name+0(FP), R0 // Move SVC args into registers
|
||||||
|
MOVD $0x80000000, R1
|
||||||
|
MOVD $0, R15
|
||||||
|
BYTE $0x0A // SVC 08 LOAD
|
||||||
|
BYTE $0x08
|
||||||
|
MOVW R15, R3 // Save return code from SVC
|
||||||
|
MOVD R2, R15 // Restore go stack pointer
|
||||||
|
CMP R3, $0 // Check SVC return code
|
||||||
|
BNE error
|
||||||
|
|
||||||
|
MOVD $-2, R3 // Reset last bit of entry point to zero
|
||||||
|
AND R0, R3
|
||||||
|
MOVD R3, addr+8(FP) // Return entry point returned by SVC
|
||||||
|
CMP R0, R3 // Check if last bit of entry point was set
|
||||||
|
BNE done
|
||||||
|
|
||||||
|
MOVD R15, R2 // Save go stack pointer
|
||||||
|
MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08)
|
||||||
|
BYTE $0x0A // SVC 09 DELETE
|
||||||
|
BYTE $0x09
|
||||||
|
MOVD R2, R15 // Restore go stack pointer
|
||||||
|
|
||||||
|
error:
|
||||||
|
MOVD $0, addr+8(FP) // Return 0 on failure
|
||||||
|
done:
|
||||||
|
XOR R0, R0 // Reset r0 to 0
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func svcUnload(name *byte, fnptr unsafe.Pointer) int64
|
||||||
|
TEXT ·svcUnload(SB),NOSPLIT,$0
|
||||||
|
MOVD R15, R2 // Save go stack pointer
|
||||||
|
MOVD name+0(FP), R0 // Move SVC args into registers
|
||||||
|
MOVD addr+8(FP), R15
|
||||||
|
BYTE $0x0A // SVC 09
|
||||||
|
BYTE $0x09
|
||||||
|
XOR R0, R0 // Reset r0 to 0
|
||||||
|
MOVD R15, R1 // Save SVC return code
|
||||||
|
MOVD R2, R15 // Restore go stack pointer
|
||||||
|
MOVD R1, rc+0(FP) // Return SVC return code
|
||||||
|
RET
|
||||||
|
|
||||||
|
// func gettid() uint64
|
||||||
|
TEXT ·gettid(SB), NOSPLIT, $0
|
||||||
|
// Get library control area (LCA).
|
||||||
|
MOVW PSALAA, R8
|
||||||
|
MOVD LCA64(R8), R8
|
||||||
|
|
||||||
|
// Get CEECAATHDID
|
||||||
|
MOVD CAA(R8), R9
|
||||||
|
MOVD 0x3D0(R9), R9
|
||||||
|
MOVD R9, ret+0(FP)
|
||||||
|
|
||||||
|
RET
|
||||||
+2
-2
@@ -2,8 +2,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
// Functions to access/create device major and minor numbers matching the
|
||||||
|
// encoding used by z/OS.
|
||||||
|
//
|
||||||
|
// The information below is extracted and adapted from <sys/stat.h> macros.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
// Major returns the major component of a z/OS device number.
|
||||||
|
func Major(dev uint64) uint32 {
|
||||||
|
return uint32((dev >> 16) & 0x0000FFFF)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minor returns the minor component of a z/OS device number.
|
||||||
|
func Minor(dev uint64) uint32 {
|
||||||
|
return uint32(dev & 0x0000FFFF)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mkdev returns a z/OS device number generated from the given major and minor
|
||||||
|
// components.
|
||||||
|
func Mkdev(major, minor uint32) uint64 {
|
||||||
|
return (uint64(major) << 16) | uint64(minor)
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
package unix_test
|
||||||
|
|
||||||
|
// Modified from Linux tests for device numbers.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDevices(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
path string
|
||||||
|
major uint32
|
||||||
|
minor uint32
|
||||||
|
}{
|
||||||
|
// Device nums found using ls -l on z/OS
|
||||||
|
{"/dev/null", 4, 0},
|
||||||
|
{"/dev/zero", 4, 1},
|
||||||
|
{"/dev/random", 4, 2},
|
||||||
|
{"/dev/urandom", 4, 2},
|
||||||
|
{"/dev/tty", 3, 0},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(fmt.Sprintf("%s %v:%v", tc.path, tc.major, tc.minor), func(t *testing.T) {
|
||||||
|
var stat unix.Stat_t
|
||||||
|
err := unix.Stat(tc.path, &stat)
|
||||||
|
if err != nil {
|
||||||
|
if err == unix.EACCES {
|
||||||
|
t.Skip("no permission to stat device, skipping test")
|
||||||
|
}
|
||||||
|
t.Errorf("failed to stat device: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dev := uint64(stat.Rdev)
|
||||||
|
if unix.Major(dev) != tc.major {
|
||||||
|
t.Errorf("for %s Major(%#x) == %d, want %d", tc.path, dev, unix.Major(dev), tc.major)
|
||||||
|
}
|
||||||
|
if unix.Minor(dev) != tc.minor {
|
||||||
|
t.Errorf("for %s Minor(%#x) == %d, want %d", tc.path, dev, unix.Minor(dev), tc.minor)
|
||||||
|
}
|
||||||
|
if unix.Mkdev(tc.major, tc.minor) != dev {
|
||||||
|
t.Errorf("for %s Mkdev(%d, %d) == %#x, want %#x", tc.path, tc.major, tc.minor, unix.Mkdev(tc.major, tc.minor), dev)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -2,8 +2,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
// Unix environment variables.
|
// Unix environment variables.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,221 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This file simulates epoll on z/OS using poll.
|
||||||
|
|
||||||
|
// Analogous to epoll_event on Linux.
|
||||||
|
// TODO(neeilan): Pad is because the Linux kernel expects a 96-bit struct. We never pass this to the kernel; remove?
|
||||||
|
type EpollEvent struct {
|
||||||
|
Events uint32
|
||||||
|
Fd int32
|
||||||
|
Pad int32
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
EPOLLERR = 0x8
|
||||||
|
EPOLLHUP = 0x10
|
||||||
|
EPOLLIN = 0x1
|
||||||
|
EPOLLMSG = 0x400
|
||||||
|
EPOLLOUT = 0x4
|
||||||
|
EPOLLPRI = 0x2
|
||||||
|
EPOLLRDBAND = 0x80
|
||||||
|
EPOLLRDNORM = 0x40
|
||||||
|
EPOLLWRBAND = 0x200
|
||||||
|
EPOLLWRNORM = 0x100
|
||||||
|
EPOLL_CTL_ADD = 0x1
|
||||||
|
EPOLL_CTL_DEL = 0x2
|
||||||
|
EPOLL_CTL_MOD = 0x3
|
||||||
|
// The following constants are part of the epoll API, but represent
|
||||||
|
// currently unsupported functionality on z/OS.
|
||||||
|
// EPOLL_CLOEXEC = 0x80000
|
||||||
|
// EPOLLET = 0x80000000
|
||||||
|
// EPOLLONESHOT = 0x40000000
|
||||||
|
// EPOLLRDHUP = 0x2000 // Typically used with edge-triggered notis
|
||||||
|
// EPOLLEXCLUSIVE = 0x10000000 // Exclusive wake-up mode
|
||||||
|
// EPOLLWAKEUP = 0x20000000 // Relies on Linux's BLOCK_SUSPEND capability
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO(neeilan): We can eliminate these epToPoll / pToEpoll calls by using identical mask values for POLL/EPOLL
|
||||||
|
// constants where possible The lower 16 bits of epoll events (uint32) can fit any system poll event (int16).
|
||||||
|
|
||||||
|
// epToPollEvt converts epoll event field to poll equivalent.
|
||||||
|
// In epoll, Events is a 32-bit field, while poll uses 16 bits.
|
||||||
|
func epToPollEvt(events uint32) int16 {
|
||||||
|
var ep2p = map[uint32]int16{
|
||||||
|
EPOLLIN: POLLIN,
|
||||||
|
EPOLLOUT: POLLOUT,
|
||||||
|
EPOLLHUP: POLLHUP,
|
||||||
|
EPOLLPRI: POLLPRI,
|
||||||
|
EPOLLERR: POLLERR,
|
||||||
|
}
|
||||||
|
|
||||||
|
var pollEvts int16 = 0
|
||||||
|
for epEvt, pEvt := range ep2p {
|
||||||
|
if (events & epEvt) != 0 {
|
||||||
|
pollEvts |= pEvt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pollEvts
|
||||||
|
}
|
||||||
|
|
||||||
|
// pToEpollEvt converts 16 bit poll event bitfields to 32-bit epoll event fields.
|
||||||
|
func pToEpollEvt(revents int16) uint32 {
|
||||||
|
var p2ep = map[int16]uint32{
|
||||||
|
POLLIN: EPOLLIN,
|
||||||
|
POLLOUT: EPOLLOUT,
|
||||||
|
POLLHUP: EPOLLHUP,
|
||||||
|
POLLPRI: EPOLLPRI,
|
||||||
|
POLLERR: EPOLLERR,
|
||||||
|
}
|
||||||
|
|
||||||
|
var epollEvts uint32 = 0
|
||||||
|
for pEvt, epEvt := range p2ep {
|
||||||
|
if (revents & pEvt) != 0 {
|
||||||
|
epollEvts |= epEvt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return epollEvts
|
||||||
|
}
|
||||||
|
|
||||||
|
// Per-process epoll implementation.
|
||||||
|
type epollImpl struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
epfd2ep map[int]*eventPoll
|
||||||
|
nextEpfd int
|
||||||
|
}
|
||||||
|
|
||||||
|
// eventPoll holds a set of file descriptors being watched by the process. A process can have multiple epoll instances.
|
||||||
|
// On Linux, this is an in-kernel data structure accessed through a fd.
|
||||||
|
type eventPoll struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
fds map[int]*EpollEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
// epoll impl for this process.
|
||||||
|
var impl epollImpl = epollImpl{
|
||||||
|
epfd2ep: make(map[int]*eventPoll),
|
||||||
|
nextEpfd: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *epollImpl) epollcreate(size int) (epfd int, err error) {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
epfd = e.nextEpfd
|
||||||
|
e.nextEpfd++
|
||||||
|
|
||||||
|
e.epfd2ep[epfd] = &eventPoll{
|
||||||
|
fds: make(map[int]*EpollEvent),
|
||||||
|
}
|
||||||
|
return epfd, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *epollImpl) epollcreate1(flag int) (fd int, err error) {
|
||||||
|
return e.epollcreate(4)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *epollImpl) epollctl(epfd int, op int, fd int, event *EpollEvent) (err error) {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
|
||||||
|
ep, ok := e.epfd2ep[epfd]
|
||||||
|
if !ok {
|
||||||
|
|
||||||
|
return EBADF
|
||||||
|
}
|
||||||
|
|
||||||
|
switch op {
|
||||||
|
case EPOLL_CTL_ADD:
|
||||||
|
// TODO(neeilan): When we make epfds and fds disjoint, detect epoll
|
||||||
|
// loops here (instances watching each other) and return ELOOP.
|
||||||
|
if _, ok := ep.fds[fd]; ok {
|
||||||
|
return EEXIST
|
||||||
|
}
|
||||||
|
ep.fds[fd] = event
|
||||||
|
case EPOLL_CTL_MOD:
|
||||||
|
if _, ok := ep.fds[fd]; !ok {
|
||||||
|
return ENOENT
|
||||||
|
}
|
||||||
|
ep.fds[fd] = event
|
||||||
|
case EPOLL_CTL_DEL:
|
||||||
|
if _, ok := ep.fds[fd]; !ok {
|
||||||
|
return ENOENT
|
||||||
|
}
|
||||||
|
delete(ep.fds, fd)
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must be called while holding ep.mu
|
||||||
|
func (ep *eventPoll) getFds() []int {
|
||||||
|
fds := make([]int, len(ep.fds))
|
||||||
|
for fd := range ep.fds {
|
||||||
|
fds = append(fds, fd)
|
||||||
|
}
|
||||||
|
return fds
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *epollImpl) epollwait(epfd int, events []EpollEvent, msec int) (n int, err error) {
|
||||||
|
e.mu.Lock() // in [rare] case of concurrent epollcreate + epollwait
|
||||||
|
ep, ok := e.epfd2ep[epfd]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
e.mu.Unlock()
|
||||||
|
return 0, EBADF
|
||||||
|
}
|
||||||
|
|
||||||
|
pollfds := make([]PollFd, 4)
|
||||||
|
for fd, epollevt := range ep.fds {
|
||||||
|
pollfds = append(pollfds, PollFd{Fd: int32(fd), Events: epToPollEvt(epollevt.Events)})
|
||||||
|
}
|
||||||
|
e.mu.Unlock()
|
||||||
|
|
||||||
|
n, err = Poll(pollfds, msec)
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
for _, pFd := range pollfds {
|
||||||
|
if pFd.Revents != 0 {
|
||||||
|
events[i] = EpollEvent{Fd: pFd.Fd, Events: pToEpollEvt(pFd.Revents)}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
if i == n {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func EpollCreate(size int) (fd int, err error) {
|
||||||
|
return impl.epollcreate(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func EpollCreate1(flag int) (fd int, err error) {
|
||||||
|
return impl.epollcreate1(flag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
|
||||||
|
return impl.epollctl(epfd, op, fd, event)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because EpollWait mutates events, the caller is expected to coordinate
|
||||||
|
// concurrent access if calling with the same epfd from multiple goroutines.
|
||||||
|
func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
|
||||||
|
return impl.epollwait(epfd, events, msec)
|
||||||
|
}
|
||||||
@@ -0,0 +1,277 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
package unix_test
|
||||||
|
|
||||||
|
// Modified from Linux tests for epoll.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEpollIn(t *testing.T) {
|
||||||
|
efd, err := unix.EpollCreate1(0) // no CLOEXEC equivalent on z/OS
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollCreate1: %v", err)
|
||||||
|
}
|
||||||
|
// no need to defer a close on efd, as it's not a real file descriptor on zos
|
||||||
|
|
||||||
|
r, w, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
defer w.Close()
|
||||||
|
|
||||||
|
fd := int(r.Fd())
|
||||||
|
ev := unix.EpollEvent{Events: unix.EPOLLIN, Fd: int32(fd)}
|
||||||
|
|
||||||
|
err = unix.EpollCtl(efd, unix.EPOLL_CTL_ADD, fd, &ev)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollCtl: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := w.Write([]byte("HELLO GOPHER")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
events := make([]unix.EpollEvent, 128)
|
||||||
|
n, err := unix.EpollWait(efd, events, 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollWait: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != 1 {
|
||||||
|
t.Errorf("EpollWait: wrong number of events: got %v, expected 1", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
got := int(events[0].Fd)
|
||||||
|
if got != fd {
|
||||||
|
t.Errorf("EpollWait: wrong Fd in event: got %v, expected %v", got, fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
if events[0].Events&unix.EPOLLIN == 0 {
|
||||||
|
t.Errorf("Expected EPOLLIN flag to be set, got %b", events[0].Events)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEpollHup(t *testing.T) {
|
||||||
|
efd, err := unix.EpollCreate1(0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollCreate1: %v", err)
|
||||||
|
}
|
||||||
|
// no need to defer a close on efd, as it's not a real file descriptor on zos
|
||||||
|
|
||||||
|
r, w, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
|
||||||
|
fd := int(r.Fd())
|
||||||
|
// EPOLLHUP should be reported even if not explicitly requested
|
||||||
|
ev := unix.EpollEvent{Events: unix.EPOLLIN, Fd: int32(fd)}
|
||||||
|
|
||||||
|
err = unix.EpollCtl(efd, unix.EPOLL_CTL_ADD, fd, &ev)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollCtl: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
events := make([]unix.EpollEvent, 128)
|
||||||
|
n, err := unix.EpollWait(efd, events, 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollWait: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if events[0].Events&unix.EPOLLHUP != 0 {
|
||||||
|
t.Errorf("EPOLLHUP flag aset without hangup event; got n=%d, flags=%b", n, events[0].Events)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Close()
|
||||||
|
|
||||||
|
events = make([]unix.EpollEvent, 128)
|
||||||
|
n, err = unix.EpollWait(efd, events, 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollWait: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n < 1 || events[0].Events&unix.EPOLLHUP == 0 {
|
||||||
|
t.Errorf("Expected EPOLLHUP flag to be set, got n=%d, flags=%b", n, events[0].Events)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEpollInManyFds(t *testing.T) {
|
||||||
|
efd, err := unix.EpollCreate1(4) // Like on Linux, size arg is ignored.
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollCreate: %v", err)
|
||||||
|
}
|
||||||
|
// no need to defer a close on efd, as it's not a real file descriptor on zos
|
||||||
|
|
||||||
|
rFds := make([]int, 10)
|
||||||
|
wPipes := make([]*os.File, 10)
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
r, w, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
defer w.Close()
|
||||||
|
|
||||||
|
rFds[i] = int(r.Fd())
|
||||||
|
wPipes[i] = w
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monitor all 10 read pipes
|
||||||
|
for _, fd := range rFds {
|
||||||
|
ev := unix.EpollEvent{Events: unix.EPOLLIN, Fd: int32(fd)}
|
||||||
|
err = unix.EpollCtl(efd, unix.EPOLL_CTL_ADD, fd, &ev)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollCtl: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to only 5 odd-numbered pipes
|
||||||
|
for i, w := range wPipes {
|
||||||
|
if i%2 == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, err := w.Write([]byte("HELLO")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
events := make([]unix.EpollEvent, 128)
|
||||||
|
n, err := unix.EpollWait(efd, events, 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollWait: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != 5 {
|
||||||
|
t.Errorf("EpollWait: wrong number of events: got %v, expected 5", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check level triggering here
|
||||||
|
if _, err := wPipes[0].Write([]byte("HELLO")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, a total of 6 pipes have been written to - level triggered notifis should number 6
|
||||||
|
events = make([]unix.EpollEvent, 128)
|
||||||
|
n, err = unix.EpollWait(efd, events, 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollWait: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != 6 {
|
||||||
|
t.Errorf("EpollWait: wrong number of events: got %v, expected 6", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMultipleEpolls(t *testing.T) {
|
||||||
|
efd1, err := unix.EpollCreate1(4)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollCreate: %v", err)
|
||||||
|
}
|
||||||
|
// no need to defer a close on efd1, as it's not a real file descriptor on zos
|
||||||
|
|
||||||
|
efd2, err := unix.EpollCreate1(4)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollCreate: %v", err)
|
||||||
|
}
|
||||||
|
// no need to defer a close on efd2, as it's not a real file descriptor on zos
|
||||||
|
|
||||||
|
rFds := make([]int, 10)
|
||||||
|
wPipes := make([]*os.File, 10)
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
r, w, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
defer w.Close()
|
||||||
|
|
||||||
|
rFds[i] = int(r.Fd())
|
||||||
|
wPipes[i] = w
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monitor first 7 read pipes on epoll1, last 3 on epoll2
|
||||||
|
for i, fd := range rFds {
|
||||||
|
var efd int
|
||||||
|
if i < 7 {
|
||||||
|
efd = efd1
|
||||||
|
} else {
|
||||||
|
efd = efd2
|
||||||
|
}
|
||||||
|
ev := unix.EpollEvent{Events: unix.EPOLLIN, Fd: int32(fd)}
|
||||||
|
err = unix.EpollCtl(efd, unix.EPOLL_CTL_ADD, fd, &ev)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollCtl: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to all 10 pipes
|
||||||
|
for _, w := range wPipes {
|
||||||
|
if _, err := w.Write([]byte("HELLO")); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
events := make([]unix.EpollEvent, 128)
|
||||||
|
n, err := unix.EpollWait(efd1, events, 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollWait: %v", err)
|
||||||
|
}
|
||||||
|
if n != 7 {
|
||||||
|
t.Errorf("EpollWait: wrong number of events on ep1: got %v, expected 7", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
events = make([]unix.EpollEvent, 128)
|
||||||
|
n, err = unix.EpollWait(efd2, events, 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollWait: %v", err)
|
||||||
|
}
|
||||||
|
if n != 3 {
|
||||||
|
t.Errorf("EpollWait: wrong number of events on ep2: got %v, expected 3", n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEpollErrors(t *testing.T) {
|
||||||
|
efd, err := unix.EpollCreate1(4)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("EpollCreate: %v", err)
|
||||||
|
}
|
||||||
|
// no need to defer a close on efd, as it's not a real file descriptor on zos
|
||||||
|
|
||||||
|
r, w, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
defer w.Close()
|
||||||
|
|
||||||
|
fd := int(r.Fd())
|
||||||
|
|
||||||
|
ev := unix.EpollEvent{Events: unix.EPOLLIN, Fd: int32(fd)}
|
||||||
|
if err = unix.EpollCtl(efd+1, unix.EPOLL_CTL_ADD, fd, &ev); err != unix.EBADF {
|
||||||
|
t.Errorf("EpollCtl: got %v when EpollCtl ADD called with invalid epfd, expected EBADF", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = unix.EpollCtl(efd, unix.EPOLL_CTL_ADD, fd, &ev); err != nil {
|
||||||
|
t.Fatalf("EpollCtl: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = unix.EpollCtl(efd, unix.EPOLL_CTL_MOD, -2, &ev); err != unix.ENOENT {
|
||||||
|
t.Errorf("EpollCtl: got %v when EpollCtl MOD called with invalid fd, expected ENOENT", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This file simulates fstatfs on z/OS using fstatvfs and w_getmntent.
|
||||||
|
|
||||||
|
func Fstatfs(fd int, stat *Statfs_t) (err error) {
|
||||||
|
var stat_v Statvfs_t
|
||||||
|
err = Fstatvfs(fd, &stat_v)
|
||||||
|
if err == nil {
|
||||||
|
// populate stat
|
||||||
|
stat.Type = 0
|
||||||
|
stat.Bsize = stat_v.Bsize
|
||||||
|
stat.Blocks = stat_v.Blocks
|
||||||
|
stat.Bfree = stat_v.Bfree
|
||||||
|
stat.Bavail = stat_v.Bavail
|
||||||
|
stat.Files = stat_v.Files
|
||||||
|
stat.Ffree = stat_v.Ffree
|
||||||
|
stat.Fsid = stat_v.Fsid
|
||||||
|
stat.Namelen = stat_v.Namemax
|
||||||
|
stat.Frsize = stat_v.Frsize
|
||||||
|
stat.Flags = stat_v.Flag
|
||||||
|
for passn := 0; passn < 5; passn++ {
|
||||||
|
switch passn {
|
||||||
|
case 0:
|
||||||
|
err = tryGetmntent64(stat)
|
||||||
|
break
|
||||||
|
case 1:
|
||||||
|
err = tryGetmntent128(stat)
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
err = tryGetmntent256(stat)
|
||||||
|
break
|
||||||
|
case 3:
|
||||||
|
err = tryGetmntent512(stat)
|
||||||
|
break
|
||||||
|
case 4:
|
||||||
|
err = tryGetmntent1024(stat)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
//proceed to return if: err is nil (found), err is nonnil but not ERANGE (another error occurred)
|
||||||
|
if err == nil || err != nil && err != ERANGE {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryGetmntent64(stat *Statfs_t) (err error) {
|
||||||
|
var mnt_ent_buffer struct {
|
||||||
|
header W_Mnth
|
||||||
|
filesys_info [64]W_Mntent
|
||||||
|
}
|
||||||
|
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||||
|
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ERANGE //return ERANGE if no match is found in this batch
|
||||||
|
for i := 0; i < fs_count; i++ {
|
||||||
|
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||||
|
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryGetmntent128(stat *Statfs_t) (err error) {
|
||||||
|
var mnt_ent_buffer struct {
|
||||||
|
header W_Mnth
|
||||||
|
filesys_info [128]W_Mntent
|
||||||
|
}
|
||||||
|
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||||
|
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ERANGE //return ERANGE if no match is found in this batch
|
||||||
|
for i := 0; i < fs_count; i++ {
|
||||||
|
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||||
|
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryGetmntent256(stat *Statfs_t) (err error) {
|
||||||
|
var mnt_ent_buffer struct {
|
||||||
|
header W_Mnth
|
||||||
|
filesys_info [256]W_Mntent
|
||||||
|
}
|
||||||
|
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||||
|
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ERANGE //return ERANGE if no match is found in this batch
|
||||||
|
for i := 0; i < fs_count; i++ {
|
||||||
|
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||||
|
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryGetmntent512(stat *Statfs_t) (err error) {
|
||||||
|
var mnt_ent_buffer struct {
|
||||||
|
header W_Mnth
|
||||||
|
filesys_info [512]W_Mntent
|
||||||
|
}
|
||||||
|
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||||
|
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ERANGE //return ERANGE if no match is found in this batch
|
||||||
|
for i := 0; i < fs_count; i++ {
|
||||||
|
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||||
|
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryGetmntent1024(stat *Statfs_t) (err error) {
|
||||||
|
var mnt_ent_buffer struct {
|
||||||
|
header W_Mnth
|
||||||
|
filesys_info [1024]W_Mntent
|
||||||
|
}
|
||||||
|
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||||
|
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ERANGE //return ERANGE if no match is found in this batch
|
||||||
|
for i := 0; i < fs_count; i++ {
|
||||||
|
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||||
|
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
package unix_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFstatfs(t *testing.T) {
|
||||||
|
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
file, err := os.Open(wd)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Query Statfs_t and Statvfs_t from wd, check content
|
||||||
|
var stat unix.Statfs_t
|
||||||
|
err = unix.Fstatfs(int(file.Fd()), &stat)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
var stat_v unix.Statvfs_t
|
||||||
|
err = unix.Fstatvfs(int(file.Fd()), &stat_v)
|
||||||
|
if stat.Bsize != stat_v.Bsize ||
|
||||||
|
stat.Blocks != stat_v.Blocks ||
|
||||||
|
stat.Bfree != stat_v.Bfree ||
|
||||||
|
stat.Bavail != stat_v.Bavail ||
|
||||||
|
stat.Files != stat_v.Files ||
|
||||||
|
stat.Ffree != stat_v.Ffree ||
|
||||||
|
stat.Fsid != stat_v.Fsid ||
|
||||||
|
stat.Namelen != stat_v.Namemax ||
|
||||||
|
stat.Frsize != stat_v.Frsize ||
|
||||||
|
stat.Flags != stat_v.Flag {
|
||||||
|
t.Errorf("Mismatching fields in Statfs_t and Statvfs_t.\nStatfs_t = %+v\nStatvfs_t = %+v", stat, stat_v)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Initialize W_Mntent, find corresponding device and check filesystem type
|
||||||
|
var mnt_ent_buffer struct {
|
||||||
|
header unix.W_Mnth
|
||||||
|
filesys_info [128]unix.W_Mntent
|
||||||
|
}
|
||||||
|
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||||
|
var fs_count int = -1
|
||||||
|
for fs_count < 0 {
|
||||||
|
fs_count, err = unix.W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i := 0; i < fs_count; i++ {
|
||||||
|
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||||
|
correct_type := uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||||
|
if stat.Type != correct_type {
|
||||||
|
t.Errorf("File system type is 0x%x. Should be 0x%x instead", stat.Type, correct_type)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ioctl itself should not be exposed directly, but additional get/set
|
||||||
|
// functions for specific types are permissible.
|
||||||
|
|
||||||
|
// IoctlSetInt performs an ioctl operation which sets an integer value
|
||||||
|
// on fd, using the specified request number.
|
||||||
|
func IoctlSetInt(fd int, req uint, value int) error {
|
||||||
|
return ioctl(fd, req, uintptr(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
|
||||||
|
//
|
||||||
|
// To change fd's window size, the req argument should be TIOCSWINSZ.
|
||||||
|
func IoctlSetWinsize(fd int, req uint, value *Winsize) error {
|
||||||
|
// TODO: if we get the chance, remove the req parameter and
|
||||||
|
// hardcode TIOCSWINSZ.
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(value)))
|
||||||
|
runtime.KeepAlive(value)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlSetTermios performs an ioctl on fd with a *Termios.
|
||||||
|
//
|
||||||
|
// The req value is expected to be TCSETS, TCSETSW, or TCSETSF
|
||||||
|
func IoctlSetTermios(fd int, req uint, value *Termios) error {
|
||||||
|
if (req != TCSETS) && (req != TCSETSW) && (req != TCSETSF) {
|
||||||
|
return ENOSYS
|
||||||
|
}
|
||||||
|
err := Tcsetattr(fd, int(req), value)
|
||||||
|
runtime.KeepAlive(value)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlGetInt performs an ioctl operation which gets an integer value
|
||||||
|
// from fd, using the specified request number.
|
||||||
|
//
|
||||||
|
// A few ioctl requests use the return value as an output parameter;
|
||||||
|
// for those, IoctlRetInt should be used instead of this function.
|
||||||
|
func IoctlGetInt(fd int, req uint) (int, error) {
|
||||||
|
var value int
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
|
||||||
|
var value Winsize
|
||||||
|
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoctlGetTermios performs an ioctl on fd with a *Termios.
|
||||||
|
//
|
||||||
|
// The req value is expected to be TCGETS
|
||||||
|
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
|
||||||
|
var value Termios
|
||||||
|
if req != TCGETS {
|
||||||
|
return &value, ENOSYS
|
||||||
|
}
|
||||||
|
err := Tcgetattr(fd, &value)
|
||||||
|
return &value, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
// This test is based on mmap_unix_test, but tweaked for z/OS, which does not support memadvise
|
||||||
|
// or anonymous mmapping.
|
||||||
|
|
||||||
|
package unix_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMmap(t *testing.T) {
|
||||||
|
tmpdir := mktmpdir(t)
|
||||||
|
filename := filepath.Join(filepath.Join(tmpdir, "testdata"), "memmapped_file")
|
||||||
|
destination, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("os.Create:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tmpdir)
|
||||||
|
|
||||||
|
fmt.Fprintf(destination, "%s\n", "0 <- Flipped between 0 and 1 when test runs successfully")
|
||||||
|
fmt.Fprintf(destination, "%s\n", "//Do not change contents - mmap test relies on this")
|
||||||
|
destination.Close()
|
||||||
|
fd, err := unix.Open(filename, unix.O_RDWR, 0o777)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Open: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := unix.Mmap(fd, 0, 8, unix.PROT_READ, unix.MAP_SHARED)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Mmap: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := unix.Mprotect(b, unix.PROT_READ|unix.PROT_WRITE); err != nil {
|
||||||
|
t.Fatalf("Mprotect: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flip flag in test file via mapped memory
|
||||||
|
flagWasZero := true
|
||||||
|
if b[0] == '0' {
|
||||||
|
b[0] = '1'
|
||||||
|
} else if b[0] == '1' {
|
||||||
|
b[0] = '0'
|
||||||
|
flagWasZero = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := unix.Msync(b, unix.MS_SYNC); err != nil {
|
||||||
|
t.Fatalf("Msync: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read file from FS to ensure flag flipped after msync
|
||||||
|
buf, err := ioutil.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Could not read mmapped file from disc for test: %v", err)
|
||||||
|
}
|
||||||
|
if flagWasZero && buf[0] != '1' || !flagWasZero && buf[0] != '0' {
|
||||||
|
t.Error("Flag flip in MAP_SHARED mmapped file not visible")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := unix.Munmap(b); err != nil {
|
||||||
|
t.Fatalf("Munmap: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mktmpdir(t *testing.T) string {
|
||||||
|
tmpdir, err := ioutil.TempDir("", "memmapped_file")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("mktmpdir:", err)
|
||||||
|
}
|
||||||
|
if err := os.Mkdir(filepath.Join(tmpdir, "testdata"), 0700); err != nil {
|
||||||
|
os.RemoveAll(tmpdir)
|
||||||
|
t.Fatal("mktmpdir:", err)
|
||||||
|
}
|
||||||
|
return tmpdir
|
||||||
|
}
|
||||||
+2
-2
@@ -2,8 +2,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix || (darwin && !race) || (linux && !race) || (freebsd && !race) || netbsd || openbsd || solaris || dragonfly
|
//go:build aix || (darwin && !race) || (linux && !race) || (freebsd && !race) || netbsd || openbsd || solaris || dragonfly || zos
|
||||||
// +build aix darwin,!race linux,!race freebsd,!race netbsd openbsd solaris dragonfly
|
// +build aix darwin,!race linux,!race freebsd,!race netbsd openbsd solaris dragonfly zos
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
// Socket control messages
|
// Socket control messages
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix || darwin || freebsd || linux || netbsd || openbsd || solaris
|
//go:build aix || darwin || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
// +build aix darwin freebsd linux netbsd openbsd solaris
|
// +build aix darwin freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
@@ -37,6 +37,10 @@ func cmsgAlignOf(salen int) int {
|
|||||||
if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm64" {
|
if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm64" {
|
||||||
salign = 16
|
salign = 16
|
||||||
}
|
}
|
||||||
|
case "zos":
|
||||||
|
// z/OS socket macros use [32-bit] sizeof(int) alignment,
|
||||||
|
// not pointer width.
|
||||||
|
salign = SizeofInt
|
||||||
}
|
}
|
||||||
|
|
||||||
return (salen + salign - 1) & ^(salign - 1)
|
return (salen + salign - 1) & ^(salign - 1)
|
||||||
|
|||||||
+2
-2
@@ -2,8 +2,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
// Package unix contains an interface to the low-level operating system
|
// Package unix contains an interface to the low-level operating system
|
||||||
// primitives. OS details vary depending on the underlying system, and
|
// primitives. OS details vary depending on the underlying system, and
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,608 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
package unix_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"syscall"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tests that below functions, structures and constants are consistent
|
||||||
|
// on all Unix-like systems.
|
||||||
|
func _() {
|
||||||
|
// program scheduling priority functions and constants
|
||||||
|
var (
|
||||||
|
_ func(int, int, int) error = unix.Setpriority
|
||||||
|
_ func(int, int) (int, error) = unix.Getpriority
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
_ int = unix.PRIO_USER
|
||||||
|
_ int = unix.PRIO_PROCESS
|
||||||
|
_ int = unix.PRIO_PGRP
|
||||||
|
)
|
||||||
|
|
||||||
|
// termios constants
|
||||||
|
const (
|
||||||
|
_ int = unix.TCIFLUSH
|
||||||
|
_ int = unix.TCIOFLUSH
|
||||||
|
_ int = unix.TCOFLUSH
|
||||||
|
)
|
||||||
|
|
||||||
|
// fcntl file locking structure and constants
|
||||||
|
var (
|
||||||
|
_ = unix.Flock_t{
|
||||||
|
Type: int16(0),
|
||||||
|
Whence: int16(0),
|
||||||
|
Start: int64(0),
|
||||||
|
Len: int64(0),
|
||||||
|
Pid: int32(0),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
_ = unix.F_GETLK
|
||||||
|
_ = unix.F_SETLK
|
||||||
|
_ = unix.F_SETLKW
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestErrnoSignalName(t *testing.T) {
|
||||||
|
testErrors := []struct {
|
||||||
|
num syscall.Errno
|
||||||
|
name string
|
||||||
|
}{
|
||||||
|
{syscall.EPERM, "EDC5139I"},
|
||||||
|
{syscall.EINVAL, "EDC5121I"},
|
||||||
|
{syscall.ENOENT, "EDC5129I"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, te := range testErrors {
|
||||||
|
t.Run(fmt.Sprintf("%d/%s", te.num, te.name), func(t *testing.T) {
|
||||||
|
e := unix.ErrnoName(te.num)
|
||||||
|
if e != te.name {
|
||||||
|
t.Errorf("ErrnoName(%d) returned %s, want %s", te.num, e, te.name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
testSignals := []struct {
|
||||||
|
num syscall.Signal
|
||||||
|
name string
|
||||||
|
}{
|
||||||
|
{syscall.SIGHUP, "SIGHUP"},
|
||||||
|
{syscall.SIGPIPE, "SIGPIPE"},
|
||||||
|
{syscall.SIGSEGV, "SIGSEGV"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ts := range testSignals {
|
||||||
|
t.Run(fmt.Sprintf("%d/%s", ts.num, ts.name), func(t *testing.T) {
|
||||||
|
s := unix.SignalName(ts.num)
|
||||||
|
if s != ts.name {
|
||||||
|
t.Errorf("SignalName(%d) returned %s, want %s", ts.num, s, ts.name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSignalNum(t *testing.T) {
|
||||||
|
testSignals := []struct {
|
||||||
|
name string
|
||||||
|
want syscall.Signal
|
||||||
|
}{
|
||||||
|
{"SIGHUP", syscall.SIGHUP},
|
||||||
|
{"SIGPIPE", syscall.SIGPIPE},
|
||||||
|
{"SIGSEGV", syscall.SIGSEGV},
|
||||||
|
{"NONEXISTS", 0},
|
||||||
|
}
|
||||||
|
for _, ts := range testSignals {
|
||||||
|
t.Run(fmt.Sprintf("%s/%d", ts.name, ts.want), func(t *testing.T) {
|
||||||
|
got := unix.SignalNum(ts.name)
|
||||||
|
if got != ts.want {
|
||||||
|
t.Errorf("SignalNum(%s) returned %d, want %d", ts.name, got, ts.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFcntlInt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
file, err := ioutil.TempFile("", "TestFnctlInt")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer os.Remove(file.Name())
|
||||||
|
defer file.Close()
|
||||||
|
f := file.Fd()
|
||||||
|
flags, err := unix.FcntlInt(f, unix.F_GETFD, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if flags&unix.FD_CLOEXEC == 0 {
|
||||||
|
t.Errorf("flags %#x do not include FD_CLOEXEC", flags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestFcntlFlock tests whether the file locking structure matches
|
||||||
|
// the calling convention of each kernel.
|
||||||
|
func TestFcntlFlock(t *testing.T) {
|
||||||
|
name := filepath.Join(os.TempDir(), "TestFcntlFlock")
|
||||||
|
fd, err := unix.Open(name, unix.O_CREAT|unix.O_RDWR|unix.O_CLOEXEC, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Open failed: %v", err)
|
||||||
|
}
|
||||||
|
defer unix.Unlink(name)
|
||||||
|
defer unix.Close(fd)
|
||||||
|
flock := unix.Flock_t{
|
||||||
|
Type: unix.F_RDLCK,
|
||||||
|
Start: 0, Len: 0, Whence: 1,
|
||||||
|
}
|
||||||
|
if err := unix.FcntlFlock(uintptr(fd), unix.F_GETLK, &flock); err != nil {
|
||||||
|
t.Fatalf("FcntlFlock failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestPassFD tests passing a file descriptor over a Unix socket.
|
||||||
|
//
|
||||||
|
// This test involved both a parent and child process. The parent
|
||||||
|
// process is invoked as a normal test, with "go test", which then
|
||||||
|
// runs the child process by running the current test binary with args
|
||||||
|
// "-test.run=^TestPassFD$" and an environment variable used to signal
|
||||||
|
// that the test should become the child process instead.
|
||||||
|
func TestPassFD(t *testing.T) {
|
||||||
|
if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
|
||||||
|
t.Skip("cannot exec subprocess on iOS, skipping test")
|
||||||
|
}
|
||||||
|
|
||||||
|
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
|
||||||
|
passFDChild()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if runtime.GOOS == "aix" {
|
||||||
|
// Unix network isn't properly working on AIX
|
||||||
|
// 7.2 with Technical Level < 2
|
||||||
|
out, err := exec.Command("oslevel", "-s").Output()
|
||||||
|
if err != nil {
|
||||||
|
t.Skipf("skipping on AIX because oslevel -s failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(out) < len("7200-XX-ZZ-YYMM") { // AIX 7.2, Tech Level XX, Service Pack ZZ, date YYMM
|
||||||
|
t.Skip("skipping on AIX because oslevel -s hasn't the right length")
|
||||||
|
}
|
||||||
|
aixVer := string(out[:4])
|
||||||
|
tl, err := strconv.Atoi(string(out[5:7]))
|
||||||
|
if err != nil {
|
||||||
|
t.Skipf("skipping on AIX because oslevel -s output cannot be parsed: %v", err)
|
||||||
|
}
|
||||||
|
if aixVer < "7200" || (aixVer == "7200" && tl < 2) {
|
||||||
|
t.Skip("skipped on AIX versions previous to 7.2 TL 2")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tempDir, err := ioutil.TempDir("", "TestPassFD")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tempDir)
|
||||||
|
|
||||||
|
fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Socketpair: %v", err)
|
||||||
|
}
|
||||||
|
defer unix.Close(fds[0])
|
||||||
|
defer unix.Close(fds[1])
|
||||||
|
writeFile := os.NewFile(uintptr(fds[0]), "child-writes")
|
||||||
|
readFile := os.NewFile(uintptr(fds[1]), "parent-reads")
|
||||||
|
defer writeFile.Close()
|
||||||
|
defer readFile.Close()
|
||||||
|
|
||||||
|
cmd := exec.Command(os.Args[0], "-test.run=^TestPassFD$", "--", tempDir)
|
||||||
|
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
|
||||||
|
if lp := os.Getenv("LD_LIBRARY_PATH"); lp != "" {
|
||||||
|
cmd.Env = append(cmd.Env, "LD_LIBRARY_PATH="+lp)
|
||||||
|
}
|
||||||
|
cmd.ExtraFiles = []*os.File{writeFile}
|
||||||
|
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if len(out) > 0 || err != nil {
|
||||||
|
t.Fatalf("child process: %q, %v", out, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := net.FileConn(readFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("FileConn: %v", err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
uc, ok := c.(*net.UnixConn)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("unexpected FileConn type; expected UnixConn, got %T", c)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, 32) // expect 1 byte
|
||||||
|
oob := make([]byte, 32) // expect 24 bytes
|
||||||
|
closeUnix := time.AfterFunc(5*time.Second, func() {
|
||||||
|
t.Logf("timeout reading from unix socket")
|
||||||
|
uc.Close()
|
||||||
|
})
|
||||||
|
_, oobn, _, _, err := uc.ReadMsgUnix(buf, oob)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("ReadMsgUnix: %v", err)
|
||||||
|
}
|
||||||
|
closeUnix.Stop()
|
||||||
|
|
||||||
|
scms, err := unix.ParseSocketControlMessage(oob[:oobn])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("ParseSocketControlMessage: %v", err)
|
||||||
|
}
|
||||||
|
if len(scms) != 1 {
|
||||||
|
t.Fatalf("expected 1 SocketControlMessage; got scms = %#v", scms)
|
||||||
|
}
|
||||||
|
scm := scms[0]
|
||||||
|
gotFds, err := unix.ParseUnixRights(&scm)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unix.ParseUnixRights: %v", err)
|
||||||
|
}
|
||||||
|
if len(gotFds) != 1 {
|
||||||
|
t.Fatalf("wanted 1 fd; got %#v", gotFds)
|
||||||
|
}
|
||||||
|
|
||||||
|
f := os.NewFile(uintptr(gotFds[0]), "fd-from-child")
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
got, err := ioutil.ReadAll(f)
|
||||||
|
want := "Hello from child process!\n"
|
||||||
|
if string(got) != want {
|
||||||
|
t.Errorf("child process ReadAll: %q, %v; want %q", got, err, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// passFDChild is the child process used by TestPassFD.
|
||||||
|
func passFDChild() {
|
||||||
|
defer os.Exit(0)
|
||||||
|
|
||||||
|
// Look for our fd. It should be fd 3, but we work around an fd leak
|
||||||
|
// bug here (http://golang.org/issue/2603) to let it be elsewhere.
|
||||||
|
var uc *net.UnixConn
|
||||||
|
for fd := uintptr(3); fd <= 10; fd++ {
|
||||||
|
f := os.NewFile(fd, "unix-conn")
|
||||||
|
var ok bool
|
||||||
|
netc, _ := net.FileConn(f)
|
||||||
|
uc, ok = netc.(*net.UnixConn)
|
||||||
|
if ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if uc == nil {
|
||||||
|
fmt.Println("failed to find unix fd")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a file f to send to our parent process on uc.
|
||||||
|
// We make it in tempDir, which our parent will clean up.
|
||||||
|
flag.Parse()
|
||||||
|
tempDir := flag.Arg(0)
|
||||||
|
f, err := ioutil.TempFile(tempDir, "")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("TempFile: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Write([]byte("Hello from child process!\n"))
|
||||||
|
f.Seek(0, 0)
|
||||||
|
|
||||||
|
rights := unix.UnixRights(int(f.Fd()))
|
||||||
|
dummyByte := []byte("x")
|
||||||
|
n, oobn, err := uc.WriteMsgUnix(dummyByte, rights, nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("WriteMsgUnix: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if n != 1 || oobn != len(rights) {
|
||||||
|
fmt.Printf("WriteMsgUnix = %d, %d; want 1, %d", n, oobn, len(rights))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestUnixRightsRoundtrip tests that UnixRights, ParseSocketControlMessage,
|
||||||
|
// and ParseUnixRights are able to successfully round-trip lists of file descriptors.
|
||||||
|
func TestUnixRightsRoundtrip(t *testing.T) {
|
||||||
|
testCases := [...][][]int{
|
||||||
|
{{42}},
|
||||||
|
{{1, 2}},
|
||||||
|
{{3, 4, 5}},
|
||||||
|
{{}},
|
||||||
|
{{1, 2}, {3, 4, 5}, {}, {7}},
|
||||||
|
}
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
b := []byte{}
|
||||||
|
var n int
|
||||||
|
for _, fds := range testCase {
|
||||||
|
// Last assignment to n wins
|
||||||
|
n = len(b) + unix.CmsgLen(4*len(fds))
|
||||||
|
b = append(b, unix.UnixRights(fds...)...)
|
||||||
|
}
|
||||||
|
// Truncate b
|
||||||
|
b = b[:n]
|
||||||
|
|
||||||
|
scms, err := unix.ParseSocketControlMessage(b)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("ParseSocketControlMessage: %v", err)
|
||||||
|
}
|
||||||
|
if len(scms) != len(testCase) {
|
||||||
|
t.Fatalf("expected %v SocketControlMessage; got scms = %#v", len(testCase), scms)
|
||||||
|
}
|
||||||
|
for i, scm := range scms {
|
||||||
|
gotFds, err := unix.ParseUnixRights(&scm)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("ParseUnixRights: %v", err)
|
||||||
|
}
|
||||||
|
wantFds := testCase[i]
|
||||||
|
if len(gotFds) != len(wantFds) {
|
||||||
|
t.Fatalf("expected %v fds, got %#v", len(wantFds), gotFds)
|
||||||
|
}
|
||||||
|
for j, fd := range gotFds {
|
||||||
|
if fd != wantFds[j] {
|
||||||
|
t.Fatalf("expected fd %v, got %v", wantFds[j], fd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRlimit(t *testing.T) {
|
||||||
|
var rlimit, zero unix.Rlimit
|
||||||
|
err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Getrlimit: save failed: %v", err)
|
||||||
|
}
|
||||||
|
if zero == rlimit {
|
||||||
|
t.Fatalf("Getrlimit: save failed: got zero value %#v", rlimit)
|
||||||
|
}
|
||||||
|
set := rlimit
|
||||||
|
set.Cur = set.Max - 1
|
||||||
|
if runtime.GOOS == "darwin" && set.Cur > 10240 {
|
||||||
|
// The max file limit is 10240, even though
|
||||||
|
// the max returned by Getrlimit is 1<<63-1.
|
||||||
|
// This is OPEN_MAX in sys/syslimits.h.
|
||||||
|
set.Cur = 10240
|
||||||
|
}
|
||||||
|
err = unix.Setrlimit(unix.RLIMIT_NOFILE, &set)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Setrlimit: set failed: %#v %v", set, err)
|
||||||
|
}
|
||||||
|
var get unix.Rlimit
|
||||||
|
err = unix.Getrlimit(unix.RLIMIT_NOFILE, &get)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Getrlimit: get failed: %v", err)
|
||||||
|
}
|
||||||
|
set = rlimit
|
||||||
|
set.Cur = set.Max - 1
|
||||||
|
if set != get {
|
||||||
|
// Seems like Darwin requires some privilege to
|
||||||
|
// increase the soft limit of rlimit sandbox, though
|
||||||
|
// Setrlimit never reports an error.
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin":
|
||||||
|
default:
|
||||||
|
t.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = unix.Setrlimit(unix.RLIMIT_NOFILE, &rlimit)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Setrlimit: restore failed: %#v %v", rlimit, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSeekFailure(t *testing.T) {
|
||||||
|
_, err := unix.Seek(-1, 0, 0)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("Seek(-1, 0, 0) did not fail")
|
||||||
|
}
|
||||||
|
str := err.Error() // used to crash on Linux
|
||||||
|
t.Logf("Seek: %v", str)
|
||||||
|
if str == "" {
|
||||||
|
t.Fatalf("Seek(-1, 0, 0) return error with empty message")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetsockoptString(t *testing.T) {
|
||||||
|
// should not panic on empty string, see issue #31277
|
||||||
|
err := unix.SetsockoptString(-1, 0, 0, "")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("SetsockoptString: did not fail")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDup(t *testing.T) {
|
||||||
|
file, err := ioutil.TempFile("", "TestDup")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Tempfile failed: %v", err)
|
||||||
|
}
|
||||||
|
defer os.Remove(file.Name())
|
||||||
|
defer file.Close()
|
||||||
|
f := int(file.Fd())
|
||||||
|
|
||||||
|
newFd, err := unix.Dup(f)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Dup: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and reserve a file descriptor.
|
||||||
|
// Dup2 automatically closes it before reusing it.
|
||||||
|
nullFile, err := os.Open("/dev/null")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
dupFd := int(file.Fd())
|
||||||
|
err = unix.Dup2(newFd, dupFd)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Dup2: %v", err)
|
||||||
|
}
|
||||||
|
// Keep the dummy file open long enough to not be closed in
|
||||||
|
// its finalizer.
|
||||||
|
runtime.KeepAlive(nullFile)
|
||||||
|
|
||||||
|
b1 := []byte("Test123")
|
||||||
|
b2 := make([]byte, 7)
|
||||||
|
_, err = unix.Write(dupFd, b1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Write to dup2 fd failed: %v", err)
|
||||||
|
}
|
||||||
|
_, err = unix.Seek(f, 0, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Seek failed: %v", err)
|
||||||
|
}
|
||||||
|
_, err = unix.Read(f, b2)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Read back failed: %v", err)
|
||||||
|
}
|
||||||
|
if string(b1) != string(b2) {
|
||||||
|
t.Errorf("Dup: stdout write not in file, expected %v, got %v", string(b1), string(b2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetwd(t *testing.T) {
|
||||||
|
fd, err := os.Open(".")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Open .: %s", err)
|
||||||
|
}
|
||||||
|
defer fd.Close()
|
||||||
|
// Directory list for test. Do not worry if any are symlinks or do not
|
||||||
|
// exist on some common unix desktop environments. That will be checked.
|
||||||
|
dirs := []string{"/", "/usr/bin", "/etc", "/var", "/opt"}
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "android":
|
||||||
|
dirs = []string{"/", "/system/bin"}
|
||||||
|
case "darwin":
|
||||||
|
switch runtime.GOARCH {
|
||||||
|
case "arm", "arm64":
|
||||||
|
d1, err := ioutil.TempDir("", "d1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("TempDir: %v", err)
|
||||||
|
}
|
||||||
|
d2, err := ioutil.TempDir("", "d2")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("TempDir: %v", err)
|
||||||
|
}
|
||||||
|
dirs = []string{d1, d2}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oldwd := os.Getenv("PWD")
|
||||||
|
for _, d := range dirs {
|
||||||
|
// Check whether d exists, is a dir and that d's path does not contain a symlink
|
||||||
|
fi, err := os.Stat(d)
|
||||||
|
if err != nil || !fi.IsDir() {
|
||||||
|
t.Logf("Test dir %s stat error (%v) or not a directory, skipping", d, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
check, err := filepath.EvalSymlinks(d)
|
||||||
|
if err != nil || check != d {
|
||||||
|
t.Logf("Test dir %s (%s) is symlink or other error (%v), skipping", d, check, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
err = os.Chdir(d)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Chdir: %v", err)
|
||||||
|
}
|
||||||
|
pwd, err := unix.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Getwd in %s: %s", d, err)
|
||||||
|
}
|
||||||
|
os.Setenv("PWD", oldwd)
|
||||||
|
err = fd.Chdir()
|
||||||
|
if err != nil {
|
||||||
|
// We changed the current directory and cannot go back.
|
||||||
|
// Don't let the tests continue; they'll scribble
|
||||||
|
// all over some other directory.
|
||||||
|
fmt.Fprintf(os.Stderr, "fchdir back to dot failed: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if pwd != d {
|
||||||
|
t.Fatalf("Getwd returned %q want %q", pwd, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMkdev(t *testing.T) {
|
||||||
|
major := uint32(42)
|
||||||
|
minor := uint32(7)
|
||||||
|
dev := unix.Mkdev(major, minor)
|
||||||
|
|
||||||
|
if unix.Major(dev) != major {
|
||||||
|
t.Errorf("Major(%#x) == %d, want %d", dev, unix.Major(dev), major)
|
||||||
|
}
|
||||||
|
if unix.Minor(dev) != minor {
|
||||||
|
t.Errorf("Minor(%#x) == %d, want %d", dev, unix.Minor(dev), minor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mktmpfifo creates a temporary FIFO and provides a cleanup function.
|
||||||
|
func mktmpfifo(t *testing.T) (*os.File, func()) {
|
||||||
|
err := unix.Mkfifo("fifo", 0666)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("mktmpfifo: failed to create FIFO: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.OpenFile("fifo", os.O_RDWR, 0666)
|
||||||
|
if err != nil {
|
||||||
|
os.Remove("fifo")
|
||||||
|
t.Fatalf("mktmpfifo: failed to open FIFO: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return f, func() {
|
||||||
|
f.Close()
|
||||||
|
os.Remove("fifo")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// utilities taken from os/os_test.go
|
||||||
|
|
||||||
|
func touch(t *testing.T, name string) {
|
||||||
|
f, err := os.Create(name)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := f.Close(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// chtmpdir changes the working directory to a new temporary directory and
|
||||||
|
// provides a cleanup function. Used when PWD is read-only.
|
||||||
|
func chtmpdir(t *testing.T) func() {
|
||||||
|
oldwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("chtmpdir: %v", err)
|
||||||
|
}
|
||||||
|
d, err := ioutil.TempDir("", "test")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("chtmpdir: %v", err)
|
||||||
|
}
|
||||||
|
if err := os.Chdir(d); err != nil {
|
||||||
|
t.Fatalf("chtmpdir: %v", err)
|
||||||
|
}
|
||||||
|
return func() {
|
||||||
|
if err := os.Chdir(oldwd); err != nil {
|
||||||
|
t.Fatalf("chtmpdir: %v", err)
|
||||||
|
}
|
||||||
|
os.RemoveAll(d)
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -2,8 +2,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,831 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
// Hand edited based on zerrors_linux_s390x.go
|
||||||
|
// TODO: auto-generate.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
const (
|
||||||
|
BRKINT = 0x0001
|
||||||
|
CLOCK_MONOTONIC = 0x1
|
||||||
|
CLOCK_PROCESS_CPUTIME_ID = 0x2
|
||||||
|
CLOCK_REALTIME = 0x0
|
||||||
|
CLOCK_THREAD_CPUTIME_ID = 0x3
|
||||||
|
CS8 = 0x0030
|
||||||
|
CSIZE = 0x0030
|
||||||
|
ECHO = 0x00000008
|
||||||
|
ECHONL = 0x00000001
|
||||||
|
FD_CLOEXEC = 0x01
|
||||||
|
FD_CLOFORK = 0x02
|
||||||
|
FNDELAY = 0x04
|
||||||
|
F_CLOSFD = 9
|
||||||
|
F_CONTROL_CVT = 13
|
||||||
|
F_DUPFD = 0
|
||||||
|
F_DUPFD2 = 8
|
||||||
|
F_GETFD = 1
|
||||||
|
F_GETFL = 259
|
||||||
|
F_GETLK = 5
|
||||||
|
F_GETOWN = 10
|
||||||
|
F_OK = 0x0
|
||||||
|
F_RDLCK = 1
|
||||||
|
F_SETFD = 2
|
||||||
|
F_SETFL = 4
|
||||||
|
F_SETLK = 6
|
||||||
|
F_SETLKW = 7
|
||||||
|
F_SETOWN = 11
|
||||||
|
F_SETTAG = 12
|
||||||
|
F_UNLCK = 3
|
||||||
|
F_WRLCK = 2
|
||||||
|
FSTYPE_ZFS = 0xe9 //"Z"
|
||||||
|
FSTYPE_HFS = 0xc8 //"H"
|
||||||
|
FSTYPE_NFS = 0xd5 //"N"
|
||||||
|
FSTYPE_TFS = 0xe3 //"T"
|
||||||
|
FSTYPE_AUTOMOUNT = 0xc1 //"A"
|
||||||
|
IP6F_MORE_FRAG = 0x0001
|
||||||
|
IP6F_OFF_MASK = 0xfff8
|
||||||
|
IP6F_RESERVED_MASK = 0x0006
|
||||||
|
IP6OPT_JUMBO = 0xc2
|
||||||
|
IP6OPT_JUMBO_LEN = 6
|
||||||
|
IP6OPT_MUTABLE = 0x20
|
||||||
|
IP6OPT_NSAP_ADDR = 0xc3
|
||||||
|
IP6OPT_PAD1 = 0x00
|
||||||
|
IP6OPT_PADN = 0x01
|
||||||
|
IP6OPT_ROUTER_ALERT = 0x05
|
||||||
|
IP6OPT_TUNNEL_LIMIT = 0x04
|
||||||
|
IP6OPT_TYPE_DISCARD = 0x40
|
||||||
|
IP6OPT_TYPE_FORCEICMP = 0x80
|
||||||
|
IP6OPT_TYPE_ICMP = 0xc0
|
||||||
|
IP6OPT_TYPE_SKIP = 0x00
|
||||||
|
IP6_ALERT_AN = 0x0002
|
||||||
|
IP6_ALERT_MLD = 0x0000
|
||||||
|
IP6_ALERT_RSVP = 0x0001
|
||||||
|
IPPORT_RESERVED = 1024
|
||||||
|
IPPORT_USERRESERVED = 5000
|
||||||
|
IPPROTO_AH = 51
|
||||||
|
IPPROTO_DSTOPTS = 60
|
||||||
|
IPPROTO_EGP = 8
|
||||||
|
IPPROTO_ESP = 50
|
||||||
|
IPPROTO_FRAGMENT = 44
|
||||||
|
IPPROTO_GGP = 2
|
||||||
|
IPPROTO_HOPOPTS = 0
|
||||||
|
IPPROTO_ICMP = 1
|
||||||
|
IPPROTO_ICMPV6 = 58
|
||||||
|
IPPROTO_IDP = 22
|
||||||
|
IPPROTO_IP = 0
|
||||||
|
IPPROTO_IPV6 = 41
|
||||||
|
IPPROTO_MAX = 256
|
||||||
|
IPPROTO_NONE = 59
|
||||||
|
IPPROTO_PUP = 12
|
||||||
|
IPPROTO_RAW = 255
|
||||||
|
IPPROTO_ROUTING = 43
|
||||||
|
IPPROTO_TCP = 6
|
||||||
|
IPPROTO_UDP = 17
|
||||||
|
IPV6_ADDR_PREFERENCES = 32
|
||||||
|
IPV6_CHECKSUM = 19
|
||||||
|
IPV6_DONTFRAG = 29
|
||||||
|
IPV6_DSTOPTS = 23
|
||||||
|
IPV6_HOPLIMIT = 11
|
||||||
|
IPV6_HOPOPTS = 22
|
||||||
|
IPV6_JOIN_GROUP = 5
|
||||||
|
IPV6_LEAVE_GROUP = 6
|
||||||
|
IPV6_MULTICAST_HOPS = 9
|
||||||
|
IPV6_MULTICAST_IF = 7
|
||||||
|
IPV6_MULTICAST_LOOP = 4
|
||||||
|
IPV6_NEXTHOP = 20
|
||||||
|
IPV6_PATHMTU = 12
|
||||||
|
IPV6_PKTINFO = 13
|
||||||
|
IPV6_PREFER_SRC_CGA = 0x10
|
||||||
|
IPV6_PREFER_SRC_COA = 0x02
|
||||||
|
IPV6_PREFER_SRC_HOME = 0x01
|
||||||
|
IPV6_PREFER_SRC_NONCGA = 0x20
|
||||||
|
IPV6_PREFER_SRC_PUBLIC = 0x08
|
||||||
|
IPV6_PREFER_SRC_TMP = 0x04
|
||||||
|
IPV6_RECVDSTOPTS = 28
|
||||||
|
IPV6_RECVHOPLIMIT = 14
|
||||||
|
IPV6_RECVHOPOPTS = 26
|
||||||
|
IPV6_RECVPATHMTU = 16
|
||||||
|
IPV6_RECVPKTINFO = 15
|
||||||
|
IPV6_RECVRTHDR = 25
|
||||||
|
IPV6_RECVTCLASS = 31
|
||||||
|
IPV6_RTHDR = 21
|
||||||
|
IPV6_RTHDRDSTOPTS = 24
|
||||||
|
IPV6_RTHDR_TYPE_0 = 0
|
||||||
|
IPV6_TCLASS = 30
|
||||||
|
IPV6_UNICAST_HOPS = 3
|
||||||
|
IPV6_USE_MIN_MTU = 18
|
||||||
|
IPV6_V6ONLY = 10
|
||||||
|
IP_ADD_MEMBERSHIP = 5
|
||||||
|
IP_ADD_SOURCE_MEMBERSHIP = 12
|
||||||
|
IP_BLOCK_SOURCE = 10
|
||||||
|
IP_DEFAULT_MULTICAST_LOOP = 1
|
||||||
|
IP_DEFAULT_MULTICAST_TTL = 1
|
||||||
|
IP_DROP_MEMBERSHIP = 6
|
||||||
|
IP_DROP_SOURCE_MEMBERSHIP = 13
|
||||||
|
IP_MAX_MEMBERSHIPS = 20
|
||||||
|
IP_MULTICAST_IF = 7
|
||||||
|
IP_MULTICAST_LOOP = 4
|
||||||
|
IP_MULTICAST_TTL = 3
|
||||||
|
IP_OPTIONS = 1
|
||||||
|
IP_PKTINFO = 101
|
||||||
|
IP_RECVPKTINFO = 102
|
||||||
|
IP_TOS = 2
|
||||||
|
IP_TTL = 3
|
||||||
|
IP_UNBLOCK_SOURCE = 11
|
||||||
|
ICANON = 0x0010
|
||||||
|
ICRNL = 0x0002
|
||||||
|
IEXTEN = 0x0020
|
||||||
|
IGNBRK = 0x0004
|
||||||
|
IGNCR = 0x0008
|
||||||
|
INLCR = 0x0020
|
||||||
|
ISIG = 0x0040
|
||||||
|
ISTRIP = 0x0080
|
||||||
|
IXON = 0x0200
|
||||||
|
IXOFF = 0x0100
|
||||||
|
LOCK_SH = 0x1 // Not exist on zOS
|
||||||
|
LOCK_EX = 0x2 // Not exist on zOS
|
||||||
|
LOCK_NB = 0x4 // Not exist on zOS
|
||||||
|
LOCK_UN = 0x8 // Not exist on zOS
|
||||||
|
POLLIN = 0x0003
|
||||||
|
POLLOUT = 0x0004
|
||||||
|
POLLPRI = 0x0010
|
||||||
|
POLLERR = 0x0020
|
||||||
|
POLLHUP = 0x0040
|
||||||
|
POLLNVAL = 0x0080
|
||||||
|
PROT_READ = 0x1 // mmap - page can be read
|
||||||
|
PROT_WRITE = 0x2 // page can be written
|
||||||
|
PROT_NONE = 0x4 // can't be accessed
|
||||||
|
PROT_EXEC = 0x8 // can be executed
|
||||||
|
MAP_PRIVATE = 0x1 // changes are private
|
||||||
|
MAP_SHARED = 0x2 // changes are shared
|
||||||
|
MAP_FIXED = 0x4 // place exactly
|
||||||
|
MS_SYNC = 0x1 // msync - synchronous writes
|
||||||
|
MS_ASYNC = 0x2 // asynchronous writes
|
||||||
|
MS_INVALIDATE = 0x4 // invalidate mappings
|
||||||
|
MTM_RDONLY = 0x80000000
|
||||||
|
MTM_RDWR = 0x40000000
|
||||||
|
MTM_UMOUNT = 0x10000000
|
||||||
|
MTM_IMMED = 0x08000000
|
||||||
|
MTM_FORCE = 0x04000000
|
||||||
|
MTM_DRAIN = 0x02000000
|
||||||
|
MTM_RESET = 0x01000000
|
||||||
|
MTM_SAMEMODE = 0x00100000
|
||||||
|
MTM_UNQSEFORCE = 0x00040000
|
||||||
|
MTM_NOSUID = 0x00000400
|
||||||
|
MTM_SYNCHONLY = 0x00000200
|
||||||
|
MTM_REMOUNT = 0x00000100
|
||||||
|
MTM_NOSECURITY = 0x00000080
|
||||||
|
O_ACCMODE = 0x03
|
||||||
|
O_APPEND = 0x08
|
||||||
|
O_ASYNCSIG = 0x0200
|
||||||
|
O_CREAT = 0x80
|
||||||
|
O_EXCL = 0x40
|
||||||
|
O_GETFL = 0x0F
|
||||||
|
O_LARGEFILE = 0x0400
|
||||||
|
O_NONBLOCK = 0x04
|
||||||
|
O_RDONLY = 0x02
|
||||||
|
O_RDWR = 0x03
|
||||||
|
O_SYNC = 0x0100
|
||||||
|
O_TRUNC = 0x10
|
||||||
|
O_WRONLY = 0x01
|
||||||
|
O_NOCTTY = 0x20
|
||||||
|
OPOST = 0x0001
|
||||||
|
ONLCR = 0x0004
|
||||||
|
PARENB = 0x0200
|
||||||
|
PARMRK = 0x0400
|
||||||
|
QUERYCVT = 3
|
||||||
|
RUSAGE_CHILDREN = -0x1
|
||||||
|
RUSAGE_SELF = 0x0 // RUSAGE_THREAD unsupported on z/OS
|
||||||
|
SEEK_CUR = 1
|
||||||
|
SEEK_END = 2
|
||||||
|
SEEK_SET = 0
|
||||||
|
SETAUTOCVTALL = 5
|
||||||
|
SETAUTOCVTON = 2
|
||||||
|
SETCVTALL = 4
|
||||||
|
SETCVTOFF = 0
|
||||||
|
SETCVTON = 1
|
||||||
|
AF_APPLETALK = 16
|
||||||
|
AF_CCITT = 10
|
||||||
|
AF_CHAOS = 5
|
||||||
|
AF_DATAKIT = 9
|
||||||
|
AF_DLI = 13
|
||||||
|
AF_ECMA = 8
|
||||||
|
AF_HYLINK = 15
|
||||||
|
AF_IMPLINK = 3
|
||||||
|
AF_INET = 2
|
||||||
|
AF_INET6 = 19
|
||||||
|
AF_INTF = 20
|
||||||
|
AF_IUCV = 17
|
||||||
|
AF_LAT = 14
|
||||||
|
AF_LINK = 18
|
||||||
|
AF_MAX = 30
|
||||||
|
AF_NBS = 7
|
||||||
|
AF_NDD = 23
|
||||||
|
AF_NETWARE = 22
|
||||||
|
AF_NS = 6
|
||||||
|
AF_PUP = 4
|
||||||
|
AF_RIF = 21
|
||||||
|
AF_ROUTE = 20
|
||||||
|
AF_SNA = 11
|
||||||
|
AF_UNIX = 1
|
||||||
|
AF_UNSPEC = 0
|
||||||
|
IBMTCP_IMAGE = 1
|
||||||
|
MSG_ACK_EXPECTED = 0x10
|
||||||
|
MSG_ACK_GEN = 0x40
|
||||||
|
MSG_ACK_TIMEOUT = 0x20
|
||||||
|
MSG_CONNTERM = 0x80
|
||||||
|
MSG_CTRUNC = 0x20
|
||||||
|
MSG_DONTROUTE = 0x4
|
||||||
|
MSG_EOF = 0x8000
|
||||||
|
MSG_EOR = 0x8
|
||||||
|
MSG_MAXIOVLEN = 16
|
||||||
|
MSG_NONBLOCK = 0x4000
|
||||||
|
MSG_OOB = 0x1
|
||||||
|
MSG_PEEK = 0x2
|
||||||
|
MSG_TRUNC = 0x10
|
||||||
|
MSG_WAITALL = 0x40
|
||||||
|
PRIO_PROCESS = 1
|
||||||
|
PRIO_PGRP = 2
|
||||||
|
PRIO_USER = 3
|
||||||
|
RLIMIT_CPU = 0
|
||||||
|
RLIMIT_FSIZE = 1
|
||||||
|
RLIMIT_DATA = 2
|
||||||
|
RLIMIT_STACK = 3
|
||||||
|
RLIMIT_CORE = 4
|
||||||
|
RLIMIT_AS = 5
|
||||||
|
RLIMIT_NOFILE = 6
|
||||||
|
RLIMIT_MEMLIMIT = 7
|
||||||
|
RLIM_INFINITY = 2147483647
|
||||||
|
SCM_RIGHTS = 0x01
|
||||||
|
SF_CLOSE = 0x00000002
|
||||||
|
SF_REUSE = 0x00000001
|
||||||
|
SHUT_RD = 0
|
||||||
|
SHUT_RDWR = 2
|
||||||
|
SHUT_WR = 1
|
||||||
|
SOCK_CONN_DGRAM = 6
|
||||||
|
SOCK_DGRAM = 2
|
||||||
|
SOCK_RAW = 3
|
||||||
|
SOCK_RDM = 4
|
||||||
|
SOCK_SEQPACKET = 5
|
||||||
|
SOCK_STREAM = 1
|
||||||
|
SOL_SOCKET = 0xffff
|
||||||
|
SOMAXCONN = 10
|
||||||
|
SO_ACCEPTCONN = 0x0002
|
||||||
|
SO_ACCEPTECONNABORTED = 0x0006
|
||||||
|
SO_ACKNOW = 0x7700
|
||||||
|
SO_BROADCAST = 0x0020
|
||||||
|
SO_BULKMODE = 0x8000
|
||||||
|
SO_CKSUMRECV = 0x0800
|
||||||
|
SO_CLOSE = 0x01
|
||||||
|
SO_CLUSTERCONNTYPE = 0x00004001
|
||||||
|
SO_CLUSTERCONNTYPE_INTERNAL = 8
|
||||||
|
SO_CLUSTERCONNTYPE_NOCONN = 0
|
||||||
|
SO_CLUSTERCONNTYPE_NONE = 1
|
||||||
|
SO_CLUSTERCONNTYPE_SAME_CLUSTER = 2
|
||||||
|
SO_CLUSTERCONNTYPE_SAME_IMAGE = 4
|
||||||
|
SO_DEBUG = 0x0001
|
||||||
|
SO_DONTROUTE = 0x0010
|
||||||
|
SO_ERROR = 0x1007
|
||||||
|
SO_IGNOREINCOMINGPUSH = 0x1
|
||||||
|
SO_IGNORESOURCEVIPA = 0x0002
|
||||||
|
SO_KEEPALIVE = 0x0008
|
||||||
|
SO_LINGER = 0x0080
|
||||||
|
SO_NONBLOCKLOCAL = 0x8001
|
||||||
|
SO_NOREUSEADDR = 0x1000
|
||||||
|
SO_OOBINLINE = 0x0100
|
||||||
|
SO_OPTACK = 0x8004
|
||||||
|
SO_OPTMSS = 0x8003
|
||||||
|
SO_RCVBUF = 0x1002
|
||||||
|
SO_RCVLOWAT = 0x1004
|
||||||
|
SO_RCVTIMEO = 0x1006
|
||||||
|
SO_REUSEADDR = 0x0004
|
||||||
|
SO_REUSEPORT = 0x0200
|
||||||
|
SO_SECINFO = 0x00004002
|
||||||
|
SO_SET = 0x0200
|
||||||
|
SO_SNDBUF = 0x1001
|
||||||
|
SO_SNDLOWAT = 0x1003
|
||||||
|
SO_SNDTIMEO = 0x1005
|
||||||
|
SO_TYPE = 0x1008
|
||||||
|
SO_UNSET = 0x0400
|
||||||
|
SO_USELOOPBACK = 0x0040
|
||||||
|
SO_USE_IFBUFS = 0x0400
|
||||||
|
S_ISUID = 0x0800
|
||||||
|
S_ISGID = 0x0400
|
||||||
|
S_ISVTX = 0x0200
|
||||||
|
S_IRUSR = 0x0100
|
||||||
|
S_IWUSR = 0x0080
|
||||||
|
S_IXUSR = 0x0040
|
||||||
|
S_IRWXU = 0x01C0
|
||||||
|
S_IRGRP = 0x0020
|
||||||
|
S_IWGRP = 0x0010
|
||||||
|
S_IXGRP = 0x0008
|
||||||
|
S_IRWXG = 0x0038
|
||||||
|
S_IROTH = 0x0004
|
||||||
|
S_IWOTH = 0x0002
|
||||||
|
S_IXOTH = 0x0001
|
||||||
|
S_IRWXO = 0x0007
|
||||||
|
S_IREAD = S_IRUSR
|
||||||
|
S_IWRITE = S_IWUSR
|
||||||
|
S_IEXEC = S_IXUSR
|
||||||
|
S_IFDIR = 0x01000000
|
||||||
|
S_IFCHR = 0x02000000
|
||||||
|
S_IFREG = 0x03000000
|
||||||
|
S_IFFIFO = 0x04000000
|
||||||
|
S_IFIFO = 0x04000000
|
||||||
|
S_IFLNK = 0x05000000
|
||||||
|
S_IFBLK = 0x06000000
|
||||||
|
S_IFSOCK = 0x07000000
|
||||||
|
S_IFVMEXTL = 0xFE000000
|
||||||
|
S_IFVMEXTL_EXEC = 0x00010000
|
||||||
|
S_IFVMEXTL_DATA = 0x00020000
|
||||||
|
S_IFVMEXTL_MEL = 0x00030000
|
||||||
|
S_IFEXTL = 0x00000001
|
||||||
|
S_IFPROGCTL = 0x00000002
|
||||||
|
S_IFAPFCTL = 0x00000004
|
||||||
|
S_IFNOSHARE = 0x00000008
|
||||||
|
S_IFSHARELIB = 0x00000010
|
||||||
|
S_IFMT = 0xFF000000
|
||||||
|
S_IFMST = 0x00FF0000
|
||||||
|
TCP_KEEPALIVE = 0x8
|
||||||
|
TCP_NODELAY = 0x1
|
||||||
|
TIOCGWINSZ = 0x4008a368
|
||||||
|
TIOCSWINSZ = 0x8008a367
|
||||||
|
TIOCSBRK = 0x2000a77b
|
||||||
|
TIOCCBRK = 0x2000a77a
|
||||||
|
TIOCSTI = 0x8001a772
|
||||||
|
TIOCGPGRP = 0x4004a777 // _IOR(167, 119, int)
|
||||||
|
TCSANOW = 0
|
||||||
|
TCSETS = 0 // equivalent to TCSANOW for tcsetattr
|
||||||
|
TCSADRAIN = 1
|
||||||
|
TCSETSW = 1 // equivalent to TCSADRAIN for tcsetattr
|
||||||
|
TCSAFLUSH = 2
|
||||||
|
TCSETSF = 2 // equivalent to TCSAFLUSH for tcsetattr
|
||||||
|
TCGETS = 3 // not defined in ioctl.h -- zos golang only
|
||||||
|
TCIFLUSH = 0
|
||||||
|
TCOFLUSH = 1
|
||||||
|
TCIOFLUSH = 2
|
||||||
|
TCOOFF = 0
|
||||||
|
TCOON = 1
|
||||||
|
TCIOFF = 2
|
||||||
|
TCION = 3
|
||||||
|
TIOCSPGRP = 0x8004a776
|
||||||
|
TIOCNOTTY = 0x2000a771
|
||||||
|
TIOCEXCL = 0x2000a70d
|
||||||
|
TIOCNXCL = 0x2000a70e
|
||||||
|
TIOCGETD = 0x4004a700
|
||||||
|
TIOCSETD = 0x8004a701
|
||||||
|
TIOCPKT = 0x8004a770
|
||||||
|
TIOCSTOP = 0x2000a76f
|
||||||
|
TIOCSTART = 0x2000a76e
|
||||||
|
TIOCUCNTL = 0x8004a766
|
||||||
|
TIOCREMOTE = 0x8004a769
|
||||||
|
TIOCMGET = 0x4004a76a
|
||||||
|
TIOCMSET = 0x8004a76d
|
||||||
|
TIOCMBIC = 0x8004a76b
|
||||||
|
TIOCMBIS = 0x8004a76c
|
||||||
|
VINTR = 0
|
||||||
|
VQUIT = 1
|
||||||
|
VERASE = 2
|
||||||
|
VKILL = 3
|
||||||
|
VEOF = 4
|
||||||
|
VEOL = 5
|
||||||
|
VMIN = 6
|
||||||
|
VSTART = 7
|
||||||
|
VSTOP = 8
|
||||||
|
VSUSP = 9
|
||||||
|
VTIME = 10
|
||||||
|
WCONTINUED = 0x4
|
||||||
|
WNOHANG = 0x1
|
||||||
|
WUNTRACED = 0x2
|
||||||
|
_BPX_SWAP = 1
|
||||||
|
_BPX_NONSWAP = 2
|
||||||
|
MCL_CURRENT = 1 // for Linux compatibility -- no zos semantics
|
||||||
|
MCL_FUTURE = 2 // for Linux compatibility -- no zos semantics
|
||||||
|
MCL_ONFAULT = 3 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_NORMAL = 0 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_RANDOM = 1 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_SEQUENTIAL = 2 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_WILLNEED = 3 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_REMOVE = 4 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_DONTFORK = 5 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_DOFORK = 6 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_HWPOISON = 7 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_MERGEABLE = 8 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_UNMERGEABLE = 9 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_SOFT_OFFLINE = 10 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_HUGEPAGE = 11 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_NOHUGEPAGE = 12 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_DONTDUMP = 13 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_DODUMP = 14 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_FREE = 15 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_WIPEONFORK = 16 // for Linux compatibility -- no zos semantics
|
||||||
|
MADV_KEEPONFORK = 17 // for Linux compatibility -- no zos semantics
|
||||||
|
AT_SYMLINK_NOFOLLOW = 1 // for Unix compatibility -- no zos semantics
|
||||||
|
AT_FDCWD = 2 // for Unix compatibility -- no zos semantics
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
EDOM = Errno(1)
|
||||||
|
ERANGE = Errno(2)
|
||||||
|
EACCES = Errno(111)
|
||||||
|
EAGAIN = Errno(112)
|
||||||
|
EBADF = Errno(113)
|
||||||
|
EBUSY = Errno(114)
|
||||||
|
ECHILD = Errno(115)
|
||||||
|
EDEADLK = Errno(116)
|
||||||
|
EEXIST = Errno(117)
|
||||||
|
EFAULT = Errno(118)
|
||||||
|
EFBIG = Errno(119)
|
||||||
|
EINTR = Errno(120)
|
||||||
|
EINVAL = Errno(121)
|
||||||
|
EIO = Errno(122)
|
||||||
|
EISDIR = Errno(123)
|
||||||
|
EMFILE = Errno(124)
|
||||||
|
EMLINK = Errno(125)
|
||||||
|
ENAMETOOLONG = Errno(126)
|
||||||
|
ENFILE = Errno(127)
|
||||||
|
ENODEV = Errno(128)
|
||||||
|
ENOENT = Errno(129)
|
||||||
|
ENOEXEC = Errno(130)
|
||||||
|
ENOLCK = Errno(131)
|
||||||
|
ENOMEM = Errno(132)
|
||||||
|
ENOSPC = Errno(133)
|
||||||
|
ENOSYS = Errno(134)
|
||||||
|
ENOTDIR = Errno(135)
|
||||||
|
ENOTEMPTY = Errno(136)
|
||||||
|
ENOTTY = Errno(137)
|
||||||
|
ENXIO = Errno(138)
|
||||||
|
EPERM = Errno(139)
|
||||||
|
EPIPE = Errno(140)
|
||||||
|
EROFS = Errno(141)
|
||||||
|
ESPIPE = Errno(142)
|
||||||
|
ESRCH = Errno(143)
|
||||||
|
EXDEV = Errno(144)
|
||||||
|
E2BIG = Errno(145)
|
||||||
|
ELOOP = Errno(146)
|
||||||
|
EILSEQ = Errno(147)
|
||||||
|
ENODATA = Errno(148)
|
||||||
|
EOVERFLOW = Errno(149)
|
||||||
|
EMVSNOTUP = Errno(150)
|
||||||
|
ECMSSTORAGE = Errno(151)
|
||||||
|
EMVSDYNALC = Errno(151)
|
||||||
|
EMVSCVAF = Errno(152)
|
||||||
|
EMVSCATLG = Errno(153)
|
||||||
|
ECMSINITIAL = Errno(156)
|
||||||
|
EMVSINITIAL = Errno(156)
|
||||||
|
ECMSERR = Errno(157)
|
||||||
|
EMVSERR = Errno(157)
|
||||||
|
EMVSPARM = Errno(158)
|
||||||
|
ECMSPFSFILE = Errno(159)
|
||||||
|
EMVSPFSFILE = Errno(159)
|
||||||
|
EMVSBADCHAR = Errno(160)
|
||||||
|
ECMSPFSPERM = Errno(162)
|
||||||
|
EMVSPFSPERM = Errno(162)
|
||||||
|
EMVSSAFEXTRERR = Errno(163)
|
||||||
|
EMVSSAF2ERR = Errno(164)
|
||||||
|
EMVSTODNOTSET = Errno(165)
|
||||||
|
EMVSPATHOPTS = Errno(166)
|
||||||
|
EMVSNORTL = Errno(167)
|
||||||
|
EMVSEXPIRE = Errno(168)
|
||||||
|
EMVSPASSWORD = Errno(169)
|
||||||
|
EMVSWLMERROR = Errno(170)
|
||||||
|
EMVSCPLERROR = Errno(171)
|
||||||
|
EMVSARMERROR = Errno(172)
|
||||||
|
ELENOFORK = Errno(200)
|
||||||
|
ELEMSGERR = Errno(201)
|
||||||
|
EFPMASKINV = Errno(202)
|
||||||
|
EFPMODEINV = Errno(203)
|
||||||
|
EBUFLEN = Errno(227)
|
||||||
|
EEXTLINK = Errno(228)
|
||||||
|
ENODD = Errno(229)
|
||||||
|
ECMSESMERR = Errno(230)
|
||||||
|
ECPERR = Errno(231)
|
||||||
|
ELEMULTITHREAD = Errno(232)
|
||||||
|
ELEFENCE = Errno(244)
|
||||||
|
EBADDATA = Errno(245)
|
||||||
|
EUNKNOWN = Errno(246)
|
||||||
|
ENOTSUP = Errno(247)
|
||||||
|
EBADNAME = Errno(248)
|
||||||
|
ENOTSAFE = Errno(249)
|
||||||
|
ELEMULTITHREADFORK = Errno(257)
|
||||||
|
ECUNNOENV = Errno(258)
|
||||||
|
ECUNNOCONV = Errno(259)
|
||||||
|
ECUNNOTALIGNED = Errno(260)
|
||||||
|
ECUNERR = Errno(262)
|
||||||
|
EIBMBADCALL = Errno(1000)
|
||||||
|
EIBMBADPARM = Errno(1001)
|
||||||
|
EIBMSOCKOUTOFRANGE = Errno(1002)
|
||||||
|
EIBMSOCKINUSE = Errno(1003)
|
||||||
|
EIBMIUCVERR = Errno(1004)
|
||||||
|
EOFFLOADboxERROR = Errno(1005)
|
||||||
|
EOFFLOADboxRESTART = Errno(1006)
|
||||||
|
EOFFLOADboxDOWN = Errno(1007)
|
||||||
|
EIBMCONFLICT = Errno(1008)
|
||||||
|
EIBMCANCELLED = Errno(1009)
|
||||||
|
EIBMBADTCPNAME = Errno(1011)
|
||||||
|
ENOTBLK = Errno(1100)
|
||||||
|
ETXTBSY = Errno(1101)
|
||||||
|
EWOULDBLOCK = Errno(1102)
|
||||||
|
EINPROGRESS = Errno(1103)
|
||||||
|
EALREADY = Errno(1104)
|
||||||
|
ENOTSOCK = Errno(1105)
|
||||||
|
EDESTADDRREQ = Errno(1106)
|
||||||
|
EMSGSIZE = Errno(1107)
|
||||||
|
EPROTOTYPE = Errno(1108)
|
||||||
|
ENOPROTOOPT = Errno(1109)
|
||||||
|
EPROTONOSUPPORT = Errno(1110)
|
||||||
|
ESOCKTNOSUPPORT = Errno(1111)
|
||||||
|
EOPNOTSUPP = Errno(1112)
|
||||||
|
EPFNOSUPPORT = Errno(1113)
|
||||||
|
EAFNOSUPPORT = Errno(1114)
|
||||||
|
EADDRINUSE = Errno(1115)
|
||||||
|
EADDRNOTAVAIL = Errno(1116)
|
||||||
|
ENETDOWN = Errno(1117)
|
||||||
|
ENETUNREACH = Errno(1118)
|
||||||
|
ENETRESET = Errno(1119)
|
||||||
|
ECONNABORTED = Errno(1120)
|
||||||
|
ECONNRESET = Errno(1121)
|
||||||
|
ENOBUFS = Errno(1122)
|
||||||
|
EISCONN = Errno(1123)
|
||||||
|
ENOTCONN = Errno(1124)
|
||||||
|
ESHUTDOWN = Errno(1125)
|
||||||
|
ETOOMANYREFS = Errno(1126)
|
||||||
|
ETIMEDOUT = Errno(1127)
|
||||||
|
ECONNREFUSED = Errno(1128)
|
||||||
|
EHOSTDOWN = Errno(1129)
|
||||||
|
EHOSTUNREACH = Errno(1130)
|
||||||
|
EPROCLIM = Errno(1131)
|
||||||
|
EUSERS = Errno(1132)
|
||||||
|
EDQUOT = Errno(1133)
|
||||||
|
ESTALE = Errno(1134)
|
||||||
|
EREMOTE = Errno(1135)
|
||||||
|
ENOSTR = Errno(1136)
|
||||||
|
ETIME = Errno(1137)
|
||||||
|
ENOSR = Errno(1138)
|
||||||
|
ENOMSG = Errno(1139)
|
||||||
|
EBADMSG = Errno(1140)
|
||||||
|
EIDRM = Errno(1141)
|
||||||
|
ENONET = Errno(1142)
|
||||||
|
ERREMOTE = Errno(1143)
|
||||||
|
ENOLINK = Errno(1144)
|
||||||
|
EADV = Errno(1145)
|
||||||
|
ESRMNT = Errno(1146)
|
||||||
|
ECOMM = Errno(1147)
|
||||||
|
EPROTO = Errno(1148)
|
||||||
|
EMULTIHOP = Errno(1149)
|
||||||
|
EDOTDOT = Errno(1150)
|
||||||
|
EREMCHG = Errno(1151)
|
||||||
|
ECANCELED = Errno(1152)
|
||||||
|
EINTRNODATA = Errno(1159)
|
||||||
|
ENOREUSE = Errno(1160)
|
||||||
|
ENOMOVE = Errno(1161)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Signals
|
||||||
|
const (
|
||||||
|
SIGHUP = Signal(1)
|
||||||
|
SIGINT = Signal(2)
|
||||||
|
SIGABRT = Signal(3)
|
||||||
|
SIGILL = Signal(4)
|
||||||
|
SIGPOLL = Signal(5)
|
||||||
|
SIGURG = Signal(6)
|
||||||
|
SIGSTOP = Signal(7)
|
||||||
|
SIGFPE = Signal(8)
|
||||||
|
SIGKILL = Signal(9)
|
||||||
|
SIGBUS = Signal(10)
|
||||||
|
SIGSEGV = Signal(11)
|
||||||
|
SIGSYS = Signal(12)
|
||||||
|
SIGPIPE = Signal(13)
|
||||||
|
SIGALRM = Signal(14)
|
||||||
|
SIGTERM = Signal(15)
|
||||||
|
SIGUSR1 = Signal(16)
|
||||||
|
SIGUSR2 = Signal(17)
|
||||||
|
SIGABND = Signal(18)
|
||||||
|
SIGCONT = Signal(19)
|
||||||
|
SIGCHLD = Signal(20)
|
||||||
|
SIGTTIN = Signal(21)
|
||||||
|
SIGTTOU = Signal(22)
|
||||||
|
SIGIO = Signal(23)
|
||||||
|
SIGQUIT = Signal(24)
|
||||||
|
SIGTSTP = Signal(25)
|
||||||
|
SIGTRAP = Signal(26)
|
||||||
|
SIGIOERR = Signal(27)
|
||||||
|
SIGWINCH = Signal(28)
|
||||||
|
SIGXCPU = Signal(29)
|
||||||
|
SIGXFSZ = Signal(30)
|
||||||
|
SIGVTALRM = Signal(31)
|
||||||
|
SIGPROF = Signal(32)
|
||||||
|
SIGDANGER = Signal(33)
|
||||||
|
SIGTHSTOP = Signal(34)
|
||||||
|
SIGTHCONT = Signal(35)
|
||||||
|
SIGTRACE = Signal(37)
|
||||||
|
SIGDCE = Signal(38)
|
||||||
|
SIGDUMP = Signal(39)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Error table
|
||||||
|
var errorList = [...]struct {
|
||||||
|
num Errno
|
||||||
|
name string
|
||||||
|
desc string
|
||||||
|
}{
|
||||||
|
{1, "EDC5001I", "A domain error occurred."},
|
||||||
|
{2, "EDC5002I", "A range error occurred."},
|
||||||
|
{111, "EDC5111I", "Permission denied."},
|
||||||
|
{112, "EDC5112I", "Resource temporarily unavailable."},
|
||||||
|
{113, "EDC5113I", "Bad file descriptor."},
|
||||||
|
{114, "EDC5114I", "Resource busy."},
|
||||||
|
{115, "EDC5115I", "No child processes."},
|
||||||
|
{116, "EDC5116I", "Resource deadlock avoided."},
|
||||||
|
{117, "EDC5117I", "File exists."},
|
||||||
|
{118, "EDC5118I", "Incorrect address."},
|
||||||
|
{119, "EDC5119I", "File too large."},
|
||||||
|
{120, "EDC5120I", "Interrupted function call."},
|
||||||
|
{121, "EDC5121I", "Invalid argument."},
|
||||||
|
{122, "EDC5122I", "Input/output error."},
|
||||||
|
{123, "EDC5123I", "Is a directory."},
|
||||||
|
{124, "EDC5124I", "Too many open files."},
|
||||||
|
{125, "EDC5125I", "Too many links."},
|
||||||
|
{126, "EDC5126I", "Filename too long."},
|
||||||
|
{127, "EDC5127I", "Too many open files in system."},
|
||||||
|
{128, "EDC5128I", "No such device."},
|
||||||
|
{129, "EDC5129I", "No such file or directory."},
|
||||||
|
{130, "EDC5130I", "Exec format error."},
|
||||||
|
{131, "EDC5131I", "No locks available."},
|
||||||
|
{132, "EDC5132I", "Not enough memory."},
|
||||||
|
{133, "EDC5133I", "No space left on device."},
|
||||||
|
{134, "EDC5134I", "Function not implemented."},
|
||||||
|
{135, "EDC5135I", "Not a directory."},
|
||||||
|
{136, "EDC5136I", "Directory not empty."},
|
||||||
|
{137, "EDC5137I", "Inappropriate I/O control operation."},
|
||||||
|
{138, "EDC5138I", "No such device or address."},
|
||||||
|
{139, "EDC5139I", "Operation not permitted."},
|
||||||
|
{140, "EDC5140I", "Broken pipe."},
|
||||||
|
{141, "EDC5141I", "Read-only file system."},
|
||||||
|
{142, "EDC5142I", "Invalid seek."},
|
||||||
|
{143, "EDC5143I", "No such process."},
|
||||||
|
{144, "EDC5144I", "Improper link."},
|
||||||
|
{145, "EDC5145I", "The parameter list is too long, or the message to receive was too large for the buffer."},
|
||||||
|
{146, "EDC5146I", "Too many levels of symbolic links."},
|
||||||
|
{147, "EDC5147I", "Illegal byte sequence."},
|
||||||
|
{148, "", ""},
|
||||||
|
{149, "EDC5149I", "Value Overflow Error."},
|
||||||
|
{150, "EDC5150I", "UNIX System Services is not active."},
|
||||||
|
{151, "EDC5151I", "Dynamic allocation error."},
|
||||||
|
{152, "EDC5152I", "Common VTOC access facility (CVAF) error."},
|
||||||
|
{153, "EDC5153I", "Catalog obtain error."},
|
||||||
|
{156, "EDC5156I", "Process initialization error."},
|
||||||
|
{157, "EDC5157I", "An internal error has occurred."},
|
||||||
|
{158, "EDC5158I", "Bad parameters were passed to the service."},
|
||||||
|
{159, "EDC5159I", "The Physical File System encountered a permanent file error."},
|
||||||
|
{160, "EDC5160I", "Bad character in environment variable name."},
|
||||||
|
{162, "EDC5162I", "The Physical File System encountered a system error."},
|
||||||
|
{163, "EDC5163I", "SAF/RACF extract error."},
|
||||||
|
{164, "EDC5164I", "SAF/RACF error."},
|
||||||
|
{165, "EDC5165I", "System TOD clock not set."},
|
||||||
|
{166, "EDC5166I", "Access mode argument on function call conflicts with PATHOPTS parameter on JCL DD statement."},
|
||||||
|
{167, "EDC5167I", "Access to the UNIX System Services version of the C RTL is denied."},
|
||||||
|
{168, "EDC5168I", "Password has expired."},
|
||||||
|
{169, "EDC5169I", "Password is invalid."},
|
||||||
|
{170, "EDC5170I", "An error was encountered with WLM."},
|
||||||
|
{171, "EDC5171I", "An error was encountered with CPL."},
|
||||||
|
{172, "EDC5172I", "An error was encountered with Application Response Measurement (ARM) component."},
|
||||||
|
{200, "EDC5200I", "The application contains a Language Environment member language that cannot tolerate a fork()."},
|
||||||
|
{201, "EDC5201I", "The Language Environment message file was not found in the hierarchical file system."},
|
||||||
|
{202, "EDC5202E", "DLL facilities are not supported under SPC environment."},
|
||||||
|
{203, "EDC5203E", "DLL facilities are not supported under POSIX environment."},
|
||||||
|
{227, "EDC5227I", "Buffer is not long enough to contain a path definition"},
|
||||||
|
{228, "EDC5228I", "The file referred to is an external link"},
|
||||||
|
{229, "EDC5229I", "No path definition for ddname in effect"},
|
||||||
|
{230, "EDC5230I", "ESM error."},
|
||||||
|
{231, "EDC5231I", "CP or the external security manager had an error"},
|
||||||
|
{232, "EDC5232I", "The function failed because it was invoked from a multithread environment."},
|
||||||
|
{244, "EDC5244I", "The program, module or DLL is not supported in this environment."},
|
||||||
|
{245, "EDC5245I", "Data is not valid."},
|
||||||
|
{246, "EDC5246I", "Unknown system state."},
|
||||||
|
{247, "EDC5247I", "Operation not supported."},
|
||||||
|
{248, "EDC5248I", "The object name specified is not correct."},
|
||||||
|
{249, "EDC5249I", "The function is not allowed."},
|
||||||
|
{257, "EDC5257I", "Function cannot be called in the child process of a fork() from a multithreaded process until exec() is called."},
|
||||||
|
{258, "EDC5258I", "A CUN_RS_NO_UNI_ENV error was issued by Unicode Services."},
|
||||||
|
{259, "EDC5259I", "A CUN_RS_NO_CONVERSION error was issued by Unicode Services."},
|
||||||
|
{260, "EDC5260I", "A CUN_RS_TABLE_NOT_ALIGNED error was issued by Unicode Services."},
|
||||||
|
{262, "EDC5262I", "An iconv() function encountered an unexpected error while using Unicode Services."},
|
||||||
|
{1000, "EDC8000I", "A bad socket-call constant was found in the IUCV header."},
|
||||||
|
{1001, "EDC8001I", "An error was found in the IUCV header."},
|
||||||
|
{1002, "EDC8002I", "A socket descriptor is out of range."},
|
||||||
|
{1003, "EDC8003I", "A socket descriptor is in use."},
|
||||||
|
{1004, "EDC8004I", "Request failed because of an IUCV error."},
|
||||||
|
{1005, "EDC8005I", "Offload box error."},
|
||||||
|
{1006, "EDC8006I", "Offload box restarted."},
|
||||||
|
{1007, "EDC8007I", "Offload box down."},
|
||||||
|
{1008, "EDC8008I", "Already a conflicting call outstanding on socket."},
|
||||||
|
{1009, "EDC8009I", "Request cancelled using a SOCKcallCANCEL request."},
|
||||||
|
{1011, "EDC8011I", "A name of a PFS was specified that either is not configured or is not a Sockets PFS."},
|
||||||
|
{1100, "EDC8100I", "Block device required."},
|
||||||
|
{1101, "EDC8101I", "Text file busy."},
|
||||||
|
{1102, "EDC8102I", "Operation would block."},
|
||||||
|
{1103, "EDC8103I", "Operation now in progress."},
|
||||||
|
{1104, "EDC8104I", "Connection already in progress."},
|
||||||
|
{1105, "EDC8105I", "Socket operation on non-socket."},
|
||||||
|
{1106, "EDC8106I", "Destination address required."},
|
||||||
|
{1107, "EDC8107I", "Message too long."},
|
||||||
|
{1108, "EDC8108I", "Protocol wrong type for socket."},
|
||||||
|
{1109, "EDC8109I", "Protocol not available."},
|
||||||
|
{1110, "EDC8110I", "Protocol not supported."},
|
||||||
|
{1111, "EDC8111I", "Socket type not supported."},
|
||||||
|
{1112, "EDC8112I", "Operation not supported on socket."},
|
||||||
|
{1113, "EDC8113I", "Protocol family not supported."},
|
||||||
|
{1114, "EDC8114I", "Address family not supported."},
|
||||||
|
{1115, "EDC8115I", "Address already in use."},
|
||||||
|
{1116, "EDC8116I", "Address not available."},
|
||||||
|
{1117, "EDC8117I", "Network is down."},
|
||||||
|
{1118, "EDC8118I", "Network is unreachable."},
|
||||||
|
{1119, "EDC8119I", "Network dropped connection on reset."},
|
||||||
|
{1120, "EDC8120I", "Connection ended abnormally."},
|
||||||
|
{1121, "EDC8121I", "Connection reset."},
|
||||||
|
{1122, "EDC8122I", "No buffer space available."},
|
||||||
|
{1123, "EDC8123I", "Socket already connected."},
|
||||||
|
{1124, "EDC8124I", "Socket not connected."},
|
||||||
|
{1125, "EDC8125I", "Can't send after socket shutdown."},
|
||||||
|
{1126, "EDC8126I", "Too many references; can't splice."},
|
||||||
|
{1127, "EDC8127I", "Connection timed out."},
|
||||||
|
{1128, "EDC8128I", "Connection refused."},
|
||||||
|
{1129, "EDC8129I", "Host is not available."},
|
||||||
|
{1130, "EDC8130I", "Host cannot be reached."},
|
||||||
|
{1131, "EDC8131I", "Too many processes."},
|
||||||
|
{1132, "EDC8132I", "Too many users."},
|
||||||
|
{1133, "EDC8133I", "Disk quota exceeded."},
|
||||||
|
{1134, "EDC8134I", "Stale file handle."},
|
||||||
|
{1135, "", ""},
|
||||||
|
{1136, "EDC8136I", "File is not a STREAM."},
|
||||||
|
{1137, "EDC8137I", "STREAMS ioctl() timeout."},
|
||||||
|
{1138, "EDC8138I", "No STREAMS resources."},
|
||||||
|
{1139, "EDC8139I", "The message identified by set_id and msg_id is not in the message catalog."},
|
||||||
|
{1140, "EDC8140I", "Bad message."},
|
||||||
|
{1141, "EDC8141I", "Identifier removed."},
|
||||||
|
{1142, "", ""},
|
||||||
|
{1143, "", ""},
|
||||||
|
{1144, "EDC8144I", "The link has been severed."},
|
||||||
|
{1145, "", ""},
|
||||||
|
{1146, "", ""},
|
||||||
|
{1147, "", ""},
|
||||||
|
{1148, "EDC8148I", "Protocol error."},
|
||||||
|
{1149, "EDC8149I", "Multihop not allowed."},
|
||||||
|
{1150, "", ""},
|
||||||
|
{1151, "", ""},
|
||||||
|
{1152, "EDC8152I", "The asynchronous I/O request has been canceled."},
|
||||||
|
{1159, "EDC8159I", "Function call was interrupted before any data was received."},
|
||||||
|
{1160, "EDC8160I", "Socket reuse is not supported."},
|
||||||
|
{1161, "EDC8161I", "The file system cannot currently be moved."},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signal table
|
||||||
|
var signalList = [...]struct {
|
||||||
|
num Signal
|
||||||
|
name string
|
||||||
|
desc string
|
||||||
|
}{
|
||||||
|
{1, "SIGHUP", "hangup"},
|
||||||
|
{2, "SIGINT", "interrupt"},
|
||||||
|
{3, "SIGABT", "aborted"},
|
||||||
|
{4, "SIGILL", "illegal instruction"},
|
||||||
|
{5, "SIGPOLL", "pollable event"},
|
||||||
|
{6, "SIGURG", "urgent I/O condition"},
|
||||||
|
{7, "SIGSTOP", "stop process"},
|
||||||
|
{8, "SIGFPE", "floating point exception"},
|
||||||
|
{9, "SIGKILL", "killed"},
|
||||||
|
{10, "SIGBUS", "bus error"},
|
||||||
|
{11, "SIGSEGV", "segmentation fault"},
|
||||||
|
{12, "SIGSYS", "bad argument to routine"},
|
||||||
|
{13, "SIGPIPE", "broken pipe"},
|
||||||
|
{14, "SIGALRM", "alarm clock"},
|
||||||
|
{15, "SIGTERM", "terminated"},
|
||||||
|
{16, "SIGUSR1", "user defined signal 1"},
|
||||||
|
{17, "SIGUSR2", "user defined signal 2"},
|
||||||
|
{18, "SIGABND", "abend"},
|
||||||
|
{19, "SIGCONT", "continued"},
|
||||||
|
{20, "SIGCHLD", "child exited"},
|
||||||
|
{21, "SIGTTIN", "stopped (tty input)"},
|
||||||
|
{22, "SIGTTOU", "stopped (tty output)"},
|
||||||
|
{23, "SIGIO", "I/O possible"},
|
||||||
|
{24, "SIGQUIT", "quit"},
|
||||||
|
{25, "SIGTSTP", "stopped"},
|
||||||
|
{26, "SIGTRAP", "trace/breakpoint trap"},
|
||||||
|
{27, "SIGIOER", "I/O error"},
|
||||||
|
{28, "SIGWINCH", "window changed"},
|
||||||
|
{29, "SIGXCPU", "CPU time limit exceeded"},
|
||||||
|
{30, "SIGXFSZ", "file size limit exceeded"},
|
||||||
|
{31, "SIGVTALRM", "virtual timer expired"},
|
||||||
|
{32, "SIGPROF", "profiling timer expired"},
|
||||||
|
{33, "SIGDANGER", "danger"},
|
||||||
|
{34, "SIGTHSTOP", "stop thread"},
|
||||||
|
{35, "SIGTHCONT", "continue thread"},
|
||||||
|
{37, "SIGTRACE", "trace"},
|
||||||
|
{38, "", "DCE"},
|
||||||
|
{39, "SIGDUMP", "dump"},
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,402 @@
|
|||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build zos && s390x
|
||||||
|
// +build zos,s390x
|
||||||
|
|
||||||
|
// Hand edited based on ztypes_linux_s390x.go
|
||||||
|
// TODO: auto-generate.
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
const (
|
||||||
|
SizeofPtr = 0x8
|
||||||
|
SizeofShort = 0x2
|
||||||
|
SizeofInt = 0x4
|
||||||
|
SizeofLong = 0x8
|
||||||
|
SizeofLongLong = 0x8
|
||||||
|
PathMax = 0x1000
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SizeofSockaddrAny = 128
|
||||||
|
SizeofCmsghdr = 12
|
||||||
|
SizeofIPMreq = 8
|
||||||
|
SizeofIPv6Mreq = 20
|
||||||
|
SizeofICMPv6Filter = 32
|
||||||
|
SizeofIPv6MTUInfo = 32
|
||||||
|
SizeofLinger = 8
|
||||||
|
SizeofSockaddrInet4 = 16
|
||||||
|
SizeofSockaddrInet6 = 28
|
||||||
|
SizeofTCPInfo = 0x68
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
_C_short int16
|
||||||
|
_C_int int32
|
||||||
|
_C_long int64
|
||||||
|
_C_long_long int64
|
||||||
|
)
|
||||||
|
|
||||||
|
type Timespec struct {
|
||||||
|
Sec int64
|
||||||
|
Nsec int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Timeval struct {
|
||||||
|
Sec int64
|
||||||
|
Usec int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type timeval_zos struct { //correct (with padding and all)
|
||||||
|
Sec int64
|
||||||
|
_ [4]byte // pad
|
||||||
|
Usec int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tms struct { //clock_t is 4-byte unsigned int in zos
|
||||||
|
Utime uint32
|
||||||
|
Stime uint32
|
||||||
|
Cutime uint32
|
||||||
|
Cstime uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Time_t int64
|
||||||
|
|
||||||
|
type Utimbuf struct {
|
||||||
|
Actime int64
|
||||||
|
Modtime int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Utsname struct {
|
||||||
|
Sysname [65]byte
|
||||||
|
Nodename [65]byte
|
||||||
|
Release [65]byte
|
||||||
|
Version [65]byte
|
||||||
|
Machine [65]byte
|
||||||
|
Domainname [65]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type RawSockaddrInet4 struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Port uint16
|
||||||
|
Addr [4]byte /* in_addr */
|
||||||
|
Zero [8]uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type RawSockaddrInet6 struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Port uint16
|
||||||
|
Flowinfo uint32
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Scope_id uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type RawSockaddrUnix struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Path [108]int8
|
||||||
|
}
|
||||||
|
|
||||||
|
type RawSockaddr struct {
|
||||||
|
Len uint8
|
||||||
|
Family uint8
|
||||||
|
Data [14]uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type RawSockaddrAny struct {
|
||||||
|
Addr RawSockaddr
|
||||||
|
_ [112]uint8 // pad
|
||||||
|
}
|
||||||
|
|
||||||
|
type _Socklen uint32
|
||||||
|
|
||||||
|
type Linger struct {
|
||||||
|
Onoff int32
|
||||||
|
Linger int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Iovec struct {
|
||||||
|
Base *byte
|
||||||
|
Len uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type IPMreq struct {
|
||||||
|
Multiaddr [4]byte /* in_addr */
|
||||||
|
Interface [4]byte /* in_addr */
|
||||||
|
}
|
||||||
|
|
||||||
|
type IPv6Mreq struct {
|
||||||
|
Multiaddr [16]byte /* in6_addr */
|
||||||
|
Interface uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Msghdr struct {
|
||||||
|
Name *byte
|
||||||
|
Iov *Iovec
|
||||||
|
Control *byte
|
||||||
|
Flags int32
|
||||||
|
Namelen int32
|
||||||
|
Iovlen int32
|
||||||
|
Controllen int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Cmsghdr struct {
|
||||||
|
Len int32
|
||||||
|
Level int32
|
||||||
|
Type int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Inet4Pktinfo struct {
|
||||||
|
Addr [4]byte /* in_addr */
|
||||||
|
Ifindex uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Inet6Pktinfo struct {
|
||||||
|
Addr [16]byte /* in6_addr */
|
||||||
|
Ifindex uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type IPv6MTUInfo struct {
|
||||||
|
Addr RawSockaddrInet6
|
||||||
|
Mtu uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type ICMPv6Filter struct {
|
||||||
|
Data [8]uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type TCPInfo struct {
|
||||||
|
State uint8
|
||||||
|
Ca_state uint8
|
||||||
|
Retransmits uint8
|
||||||
|
Probes uint8
|
||||||
|
Backoff uint8
|
||||||
|
Options uint8
|
||||||
|
Rto uint32
|
||||||
|
Ato uint32
|
||||||
|
Snd_mss uint32
|
||||||
|
Rcv_mss uint32
|
||||||
|
Unacked uint32
|
||||||
|
Sacked uint32
|
||||||
|
Lost uint32
|
||||||
|
Retrans uint32
|
||||||
|
Fackets uint32
|
||||||
|
Last_data_sent uint32
|
||||||
|
Last_ack_sent uint32
|
||||||
|
Last_data_recv uint32
|
||||||
|
Last_ack_recv uint32
|
||||||
|
Pmtu uint32
|
||||||
|
Rcv_ssthresh uint32
|
||||||
|
Rtt uint32
|
||||||
|
Rttvar uint32
|
||||||
|
Snd_ssthresh uint32
|
||||||
|
Snd_cwnd uint32
|
||||||
|
Advmss uint32
|
||||||
|
Reordering uint32
|
||||||
|
Rcv_rtt uint32
|
||||||
|
Rcv_space uint32
|
||||||
|
Total_retrans uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type _Gid_t uint32
|
||||||
|
|
||||||
|
type rusage_zos struct {
|
||||||
|
Utime timeval_zos
|
||||||
|
Stime timeval_zos
|
||||||
|
}
|
||||||
|
|
||||||
|
type Rusage struct {
|
||||||
|
Utime Timeval
|
||||||
|
Stime Timeval
|
||||||
|
Maxrss int64
|
||||||
|
Ixrss int64
|
||||||
|
Idrss int64
|
||||||
|
Isrss int64
|
||||||
|
Minflt int64
|
||||||
|
Majflt int64
|
||||||
|
Nswap int64
|
||||||
|
Inblock int64
|
||||||
|
Oublock int64
|
||||||
|
Msgsnd int64
|
||||||
|
Msgrcv int64
|
||||||
|
Nsignals int64
|
||||||
|
Nvcsw int64
|
||||||
|
Nivcsw int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Rlimit struct {
|
||||||
|
Cur uint64
|
||||||
|
Max uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// { int, short, short } in poll.h
|
||||||
|
type PollFd struct {
|
||||||
|
Fd int32
|
||||||
|
Events int16
|
||||||
|
Revents int16
|
||||||
|
}
|
||||||
|
|
||||||
|
type Stat_t struct { //Linux Definition
|
||||||
|
Dev uint64
|
||||||
|
Ino uint64
|
||||||
|
Nlink uint64
|
||||||
|
Mode uint32
|
||||||
|
Uid uint32
|
||||||
|
Gid uint32
|
||||||
|
_ int32
|
||||||
|
Rdev uint64
|
||||||
|
Size int64
|
||||||
|
Atim Timespec
|
||||||
|
Mtim Timespec
|
||||||
|
Ctim Timespec
|
||||||
|
Blksize int64
|
||||||
|
Blocks int64
|
||||||
|
_ [3]int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Stat_LE_t struct {
|
||||||
|
_ [4]byte // eye catcher
|
||||||
|
Length uint16
|
||||||
|
Version uint16
|
||||||
|
Mode int32
|
||||||
|
Ino uint32
|
||||||
|
Dev uint32
|
||||||
|
Nlink int32
|
||||||
|
Uid int32
|
||||||
|
Gid int32
|
||||||
|
Size int64
|
||||||
|
Atim31 [4]byte
|
||||||
|
Mtim31 [4]byte
|
||||||
|
Ctim31 [4]byte
|
||||||
|
Rdev uint32
|
||||||
|
Auditoraudit uint32
|
||||||
|
Useraudit uint32
|
||||||
|
Blksize int32
|
||||||
|
Creatim31 [4]byte
|
||||||
|
AuditID [16]byte
|
||||||
|
_ [4]byte // rsrvd1
|
||||||
|
File_tag struct {
|
||||||
|
Ccsid uint16
|
||||||
|
Txtflag uint16 // aggregating Txflag:1 deferred:1 rsvflags:14
|
||||||
|
}
|
||||||
|
CharsetID [8]byte
|
||||||
|
Blocks int64
|
||||||
|
Genvalue uint32
|
||||||
|
Reftim31 [4]byte
|
||||||
|
Fid [8]byte
|
||||||
|
Filefmt byte
|
||||||
|
Fspflag2 byte
|
||||||
|
_ [2]byte // rsrvd2
|
||||||
|
Ctimemsec int32
|
||||||
|
Seclabel [8]byte
|
||||||
|
_ [4]byte // rsrvd3
|
||||||
|
_ [4]byte // rsrvd4
|
||||||
|
Atim Time_t
|
||||||
|
Mtim Time_t
|
||||||
|
Ctim Time_t
|
||||||
|
Creatim Time_t
|
||||||
|
Reftim Time_t
|
||||||
|
_ [24]byte // rsrvd5
|
||||||
|
}
|
||||||
|
|
||||||
|
type Statvfs_t struct {
|
||||||
|
ID [4]byte
|
||||||
|
Len int32
|
||||||
|
Bsize uint64
|
||||||
|
Blocks uint64
|
||||||
|
Usedspace uint64
|
||||||
|
Bavail uint64
|
||||||
|
Flag uint64
|
||||||
|
Maxfilesize int64
|
||||||
|
_ [16]byte
|
||||||
|
Frsize uint64
|
||||||
|
Bfree uint64
|
||||||
|
Files uint32
|
||||||
|
Ffree uint32
|
||||||
|
Favail uint32
|
||||||
|
Namemax31 uint32
|
||||||
|
Invarsec uint32
|
||||||
|
_ [4]byte
|
||||||
|
Fsid uint64
|
||||||
|
Namemax uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Statfs_t struct {
|
||||||
|
Type uint32
|
||||||
|
Bsize uint64
|
||||||
|
Blocks uint64
|
||||||
|
Bfree uint64
|
||||||
|
Bavail uint64
|
||||||
|
Files uint32
|
||||||
|
Ffree uint32
|
||||||
|
Fsid uint64
|
||||||
|
Namelen uint64
|
||||||
|
Frsize uint64
|
||||||
|
Flags uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Dirent struct {
|
||||||
|
Reclen uint16
|
||||||
|
Namlen uint16
|
||||||
|
Ino uint32
|
||||||
|
Extra uintptr
|
||||||
|
Name [256]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// This struct is packed on z/OS so it can't be used directly.
|
||||||
|
type Flock_t struct {
|
||||||
|
Type int16
|
||||||
|
Whence int16
|
||||||
|
Start int64
|
||||||
|
Len int64
|
||||||
|
Pid int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Termios struct {
|
||||||
|
Cflag uint32
|
||||||
|
Iflag uint32
|
||||||
|
Lflag uint32
|
||||||
|
Oflag uint32
|
||||||
|
Cc [11]uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type Winsize struct {
|
||||||
|
Row uint16
|
||||||
|
Col uint16
|
||||||
|
Xpixel uint16
|
||||||
|
Ypixel uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type W_Mnth struct {
|
||||||
|
Hid [4]byte
|
||||||
|
Size int32
|
||||||
|
Cur1 int32 //32bit pointer
|
||||||
|
Cur2 int32 //^
|
||||||
|
Devno uint32
|
||||||
|
_ [4]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type W_Mntent struct {
|
||||||
|
Fstype uint32
|
||||||
|
Mode uint32
|
||||||
|
Dev uint32
|
||||||
|
Parentdev uint32
|
||||||
|
Rootino uint32
|
||||||
|
Status byte
|
||||||
|
Ddname [9]byte
|
||||||
|
Fstname [9]byte
|
||||||
|
Fsname [45]byte
|
||||||
|
Pathlen uint32
|
||||||
|
Mountpoint [1024]byte
|
||||||
|
Jobname [8]byte
|
||||||
|
PID int32
|
||||||
|
Parmoffset int32
|
||||||
|
Parmlen int16
|
||||||
|
Owner [8]byte
|
||||||
|
Quiesceowner [8]byte
|
||||||
|
_ [38]byte
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user