unix: add Uname on Darwin

Darwin doesn't have a uname syscall but the same information can be
retrieved using sysctls. Use the raw sysctl numbers instead of doing the
roundtrip via SysctlString in order to void the additional sysctl calls
in nametomib and SysctlRaw.

This implementation follows the one in
https://opensource.apple.com/source/Libc/Libc-1244.1.7/gen/uname.c

Change-Id: I19541e2a6700f84ced0549a8fb86faa8cb5e6fbe
Reviewed-on: https://go-review.googlesource.com/77270
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/unix/mkerrors.sh b/unix/mkerrors.sh
index 2db9e0a..2a44da5 100755
--- a/unix/mkerrors.sh
+++ b/unix/mkerrors.sh
@@ -48,6 +48,7 @@
 #include <sys/sysctl.h>
 #include <sys/mman.h>
 #include <sys/mount.h>
+#include <sys/utsname.h>
 #include <sys/wait.h>
 #include <net/bpf.h>
 #include <net/if.h>
@@ -386,7 +387,9 @@
 		$2 == "SOMAXCONN" ||
 		$2 == "NAME_MAX" ||
 		$2 == "IFNAMSIZ" ||
-		$2 ~ /^CTL_(MAXNAME|NET|QUERY)$/ ||
+		$2 ~ /^CTL_(HW|KERN|MAXNAME|NET|QUERY)$/ ||
+		$2 ~ /^KERN_(HOSTNAME|OS(RELEASE|TYPE)|VERSION)$/ ||
+		$2 ~ /^HW_MACHINE$/ ||
 		$2 ~ /^SYSCTL_VERS/ ||
 		$2 ~ /^(MS|MNT|UMOUNT)_/ ||
 		$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
diff --git a/unix/syscall_darwin.go b/unix/syscall_darwin.go
index 9a6783e..d6c472a 100644
--- a/unix/syscall_darwin.go
+++ b/unix/syscall_darwin.go
@@ -270,6 +270,52 @@
 	return &value, err
 }
 
+func Uname(uname *Utsname) error {
+	mib := []_C_int{CTL_KERN, KERN_OSTYPE}
+	n := unsafe.Sizeof(uname.Sysname)
+	if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil {
+		return err
+	}
+
+	mib = []_C_int{CTL_KERN, KERN_HOSTNAME}
+	n = unsafe.Sizeof(uname.Nodename)
+	if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil {
+		return err
+	}
+
+	mib = []_C_int{CTL_KERN, KERN_OSRELEASE}
+	n = unsafe.Sizeof(uname.Release)
+	if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil {
+		return err
+	}
+
+	mib = []_C_int{CTL_KERN, KERN_VERSION}
+	n = unsafe.Sizeof(uname.Version)
+	if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil {
+		return err
+	}
+
+	// The version might have newlines or tabs in it, convert them to
+	// spaces.
+	for i, b := range uname.Version {
+		if b == '\n' || b == '\t' {
+			if i == len(uname.Version)-1 {
+				uname.Version[i] = 0
+			} else {
+				uname.Version[i] = ' '
+			}
+		}
+	}
+
+	mib = []_C_int{CTL_HW, HW_MACHINE}
+	n = unsafe.Sizeof(uname.Machine)
+	if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil {
+		return err
+	}
+
+	return nil
+}
+
 /*
  * Exposed directly
  */
diff --git a/unix/types_darwin.go b/unix/types_darwin.go
index 3a938ac..46b9908 100644
--- a/unix/types_darwin.go
+++ b/unix/types_darwin.go
@@ -39,6 +39,7 @@
 #include <sys/types.h>
 #include <sys/uio.h>
 #include <sys/un.h>
+#include <sys/utsname.h>
 #include <sys/wait.h>
 #include <net/bpf.h>
 #include <net/if.h>
@@ -270,3 +271,7 @@
 	POLLWRBAND = C.POLLWRBAND
 	POLLWRNORM = C.POLLWRNORM
 )
+
+// uname
+
+type Utsname C.struct_utsname
diff --git a/unix/zerrors_darwin_386.go b/unix/zerrors_darwin_386.go
index c90ebcf..dcba884 100644
--- a/unix/zerrors_darwin_386.go
+++ b/unix/zerrors_darwin_386.go
@@ -249,6 +249,8 @@
 	CSTOP                             = 0x13
 	CSTOPB                            = 0x400
 	CSUSP                             = 0x1a
+	CTL_HW                            = 0x6
+	CTL_KERN                          = 0x1
 	CTL_MAXNAME                       = 0xc
 	CTL_NET                           = 0x4
 	DLT_A429                          = 0xb8
@@ -532,6 +534,7 @@
 	F_VOLPOSMODE                      = 0x4
 	F_WRLCK                           = 0x3
 	HUPCL                             = 0x4000
+	HW_MACHINE                        = 0x1
 	ICANON                            = 0x100
 	ICMP6_FILTER                      = 0x12
 	ICRNL                             = 0x100
@@ -878,6 +881,10 @@
 	IXANY                             = 0x800
 	IXOFF                             = 0x400
 	IXON                              = 0x200
+	KERN_HOSTNAME                     = 0xa
+	KERN_OSRELEASE                    = 0x2
+	KERN_OSTYPE                       = 0x1
+	KERN_VERSION                      = 0x4
 	LOCK_EX                           = 0x2
 	LOCK_NB                           = 0x4
 	LOCK_SH                           = 0x1
diff --git a/unix/zerrors_darwin_amd64.go b/unix/zerrors_darwin_amd64.go
index 8991948..1a51c96 100644
--- a/unix/zerrors_darwin_amd64.go
+++ b/unix/zerrors_darwin_amd64.go
@@ -249,6 +249,8 @@
 	CSTOP                             = 0x13
 	CSTOPB                            = 0x400
 	CSUSP                             = 0x1a
+	CTL_HW                            = 0x6
+	CTL_KERN                          = 0x1
 	CTL_MAXNAME                       = 0xc
 	CTL_NET                           = 0x4
 	DLT_A429                          = 0xb8
@@ -532,6 +534,7 @@
 	F_VOLPOSMODE                      = 0x4
 	F_WRLCK                           = 0x3
 	HUPCL                             = 0x4000
+	HW_MACHINE                        = 0x1
 	ICANON                            = 0x100
 	ICMP6_FILTER                      = 0x12
 	ICRNL                             = 0x100
@@ -878,6 +881,10 @@
 	IXANY                             = 0x800
 	IXOFF                             = 0x400
 	IXON                              = 0x200
+	KERN_HOSTNAME                     = 0xa
+	KERN_OSRELEASE                    = 0x2
+	KERN_OSTYPE                       = 0x1
+	KERN_VERSION                      = 0x4
 	LOCK_EX                           = 0x2
 	LOCK_NB                           = 0x4
 	LOCK_SH                           = 0x1
diff --git a/unix/zerrors_darwin_arm.go b/unix/zerrors_darwin_arm.go
index c41a6b8..fa135b1 100644
--- a/unix/zerrors_darwin_arm.go
+++ b/unix/zerrors_darwin_arm.go
@@ -249,6 +249,8 @@
 	CSTOP                             = 0x13
 	CSTOPB                            = 0x400
 	CSUSP                             = 0x1a
+	CTL_HW                            = 0x6
+	CTL_KERN                          = 0x1
 	CTL_MAXNAME                       = 0xc
 	CTL_NET                           = 0x4
 	DLT_A429                          = 0xb8
@@ -532,6 +534,7 @@
 	F_VOLPOSMODE                      = 0x4
 	F_WRLCK                           = 0x3
 	HUPCL                             = 0x4000
+	HW_MACHINE                        = 0x1
 	ICANON                            = 0x100
 	ICMP6_FILTER                      = 0x12
 	ICRNL                             = 0x100
@@ -878,6 +881,10 @@
 	IXANY                             = 0x800
 	IXOFF                             = 0x400
 	IXON                              = 0x200
+	KERN_HOSTNAME                     = 0xa
+	KERN_OSRELEASE                    = 0x2
+	KERN_OSTYPE                       = 0x1
+	KERN_VERSION                      = 0x4
 	LOCK_EX                           = 0x2
 	LOCK_NB                           = 0x4
 	LOCK_SH                           = 0x1
diff --git a/unix/zerrors_darwin_arm64.go b/unix/zerrors_darwin_arm64.go
index 73f8c87..6419c65 100644
--- a/unix/zerrors_darwin_arm64.go
+++ b/unix/zerrors_darwin_arm64.go
@@ -249,6 +249,8 @@
 	CSTOP                             = 0x13
 	CSTOPB                            = 0x400
 	CSUSP                             = 0x1a
+	CTL_HW                            = 0x6
+	CTL_KERN                          = 0x1
 	CTL_MAXNAME                       = 0xc
 	CTL_NET                           = 0x4
 	DLT_A429                          = 0xb8
@@ -532,6 +534,7 @@
 	F_VOLPOSMODE                      = 0x4
 	F_WRLCK                           = 0x3
 	HUPCL                             = 0x4000
+	HW_MACHINE                        = 0x1
 	ICANON                            = 0x100
 	ICMP6_FILTER                      = 0x12
 	ICRNL                             = 0x100
@@ -878,6 +881,10 @@
 	IXANY                             = 0x800
 	IXOFF                             = 0x400
 	IXON                              = 0x200
+	KERN_HOSTNAME                     = 0xa
+	KERN_OSRELEASE                    = 0x2
+	KERN_OSTYPE                       = 0x1
+	KERN_VERSION                      = 0x4
 	LOCK_EX                           = 0x2
 	LOCK_NB                           = 0x4
 	LOCK_SH                           = 0x1
diff --git a/unix/ztypes_darwin_386.go b/unix/ztypes_darwin_386.go
index 4667c7b..bc4bc89 100644
--- a/unix/ztypes_darwin_386.go
+++ b/unix/ztypes_darwin_386.go
@@ -479,3 +479,11 @@
 	POLLWRBAND = 0x100
 	POLLWRNORM = 0x4
 )
+
+type Utsname struct {
+	Sysname  [256]byte
+	Nodename [256]byte
+	Release  [256]byte
+	Version  [256]byte
+	Machine  [256]byte
+}
diff --git a/unix/ztypes_darwin_amd64.go b/unix/ztypes_darwin_amd64.go
index 3f33b18..d8abcab 100644
--- a/unix/ztypes_darwin_amd64.go
+++ b/unix/ztypes_darwin_amd64.go
@@ -489,3 +489,11 @@
 	POLLWRBAND = 0x100
 	POLLWRNORM = 0x4
 )
+
+type Utsname struct {
+	Sysname  [256]byte
+	Nodename [256]byte
+	Release  [256]byte
+	Version  [256]byte
+	Machine  [256]byte
+}
diff --git a/unix/ztypes_darwin_arm.go b/unix/ztypes_darwin_arm.go
index 463a28b..9749c9f 100644
--- a/unix/ztypes_darwin_arm.go
+++ b/unix/ztypes_darwin_arm.go
@@ -480,3 +480,11 @@
 	POLLWRBAND = 0x100
 	POLLWRNORM = 0x4
 )
+
+type Utsname struct {
+	Sysname  [256]byte
+	Nodename [256]byte
+	Release  [256]byte
+	Version  [256]byte
+	Machine  [256]byte
+}
diff --git a/unix/ztypes_darwin_arm64.go b/unix/ztypes_darwin_arm64.go
index 1ec20a0..810b0bd 100644
--- a/unix/ztypes_darwin_arm64.go
+++ b/unix/ztypes_darwin_arm64.go
@@ -489,3 +489,11 @@
 	POLLWRBAND = 0x100
 	POLLWRNORM = 0x4
 )
+
+type Utsname struct {
+	Sysname  [256]byte
+	Nodename [256]byte
+	Release  [256]byte
+	Version  [256]byte
+	Machine  [256]byte
+}