unix: add Getcwd to support Getwd on all BSDs

All BSDs provide the SYS___GETCWD syscall which can be used to implement
Getwd.

Also add a test based on TestChdirAndGetwd from os/os_test.go

Change-Id: I243eae3e02a40e92afad317eb1f8a28b6032c131
Reviewed-on: https://go-review.googlesource.com/83755
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/unix/syscall_dragonfly.go b/unix/syscall_dragonfly.go
index 9f0143a..6dfc89a 100644
--- a/unix/syscall_dragonfly.go
+++ b/unix/syscall_dragonfly.go
@@ -110,6 +110,23 @@
 	return
 }
 
+const ImplementsGetwd = true
+
+//sys	Getcwd(buf []byte) (n int, err error) = SYS___GETCWD
+
+func Getwd() (string, error) {
+	var buf [PathMax]byte
+	_, err := Getcwd(buf[0:])
+	if err != nil {
+		return "", err
+	}
+	n := clen(buf[:])
+	if n < 1 {
+		return "", EINVAL
+	}
+	return string(buf[:n]), nil
+}
+
 func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
 	var _p0 unsafe.Pointer
 	var bufsize uintptr
diff --git a/unix/syscall_freebsd.go b/unix/syscall_freebsd.go
index f9b8281..f8979b4 100644
--- a/unix/syscall_freebsd.go
+++ b/unix/syscall_freebsd.go
@@ -105,6 +105,23 @@
 	return
 }
 
+const ImplementsGetwd = true
+
+//sys	Getcwd(buf []byte) (n int, err error) = SYS___GETCWD
+
+func Getwd() (string, error) {
+	var buf [PathMax]byte
+	_, err := Getcwd(buf[0:])
+	if err != nil {
+		return "", err
+	}
+	n := clen(buf[:])
+	if n < 1 {
+		return "", EINVAL
+	}
+	return string(buf[:n]), nil
+}
+
 func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
 	var _p0 unsafe.Pointer
 	var bufsize uintptr
diff --git a/unix/syscall_netbsd.go b/unix/syscall_netbsd.go
index 13b0a2d..d81106d 100644
--- a/unix/syscall_netbsd.go
+++ b/unix/syscall_netbsd.go
@@ -118,6 +118,23 @@
 	return getdents(fd, buf)
 }
 
+const ImplementsGetwd = true
+
+//sys	Getcwd(buf []byte) (n int, err error) = SYS___GETCWD
+
+func Getwd() (string, error) {
+	var buf [PathMax]byte
+	_, err := Getcwd(buf[0:])
+	if err != nil {
+		return "", err
+	}
+	n := clen(buf[:])
+	if n < 1 {
+		return "", EINVAL
+	}
+	return string(buf[:n]), nil
+}
+
 // TODO
 func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 	return -1, ENOSYS
diff --git a/unix/syscall_no_getwd.go b/unix/syscall_no_getwd.go
deleted file mode 100644
index 530792e..0000000
--- a/unix/syscall_no_getwd.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2013 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.
-
-// +build dragonfly freebsd netbsd openbsd
-
-package unix
-
-const ImplementsGetwd = false
-
-func Getwd() (string, error) { return "", ENOTSUP }
diff --git a/unix/syscall_openbsd.go b/unix/syscall_openbsd.go
index 19c4b1a..553c2fb 100644
--- a/unix/syscall_openbsd.go
+++ b/unix/syscall_openbsd.go
@@ -71,6 +71,23 @@
 	return getdents(fd, buf)
 }
 
+const ImplementsGetwd = true
+
+//sys	Getcwd(buf []byte) (n int, err error) = SYS___GETCWD
+
+func Getwd() (string, error) {
+	var buf [PathMax]byte
+	_, err := Getcwd(buf[0:])
+	if err != nil {
+		return "", err
+	}
+	n := clen(buf[:])
+	if n < 1 {
+		return "", EINVAL
+	}
+	return string(buf[:n]), nil
+}
+
 // TODO
 func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
 	return -1, ENOSYS
diff --git a/unix/syscall_solaris.go b/unix/syscall_solaris.go
index 3ab9e07..58b4e6d 100644
--- a/unix/syscall_solaris.go
+++ b/unix/syscall_solaris.go
@@ -34,15 +34,6 @@
 	raw    RawSockaddrDatalink
 }
 
-func clen(n []byte) int {
-	for i := 0; i < len(n); i++ {
-		if n[i] == 0 {
-			return i
-		}
-	}
-	return len(n)
-}
-
 func direntIno(buf []byte) (uint64, bool) {
 	return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
 }
diff --git a/unix/syscall_unix.go b/unix/syscall_unix.go
index 3ed8a91..35c1cd5 100644
--- a/unix/syscall_unix.go
+++ b/unix/syscall_unix.go
@@ -50,6 +50,17 @@
 	return e
 }
 
+// clen returns the index of the first NULL byte in n or len(n) if n contains no
+// NULL byte or len(n) if n contains no NULL byte
+func clen(n []byte) int {
+	for i := 0; i < len(n); i++ {
+		if n[i] == 0 {
+			return i
+		}
+	}
+	return len(n)
+}
+
 // Mmap manager, for use by operating system-specific implementations.
 
 type mmapper struct {
diff --git a/unix/syscall_unix_test.go b/unix/syscall_unix_test.go
index d0a09ce..72a8094 100644
--- a/unix/syscall_unix_test.go
+++ b/unix/syscall_unix_test.go
@@ -378,6 +378,60 @@
 	}
 }
 
+func TestGetwd(t *testing.T) {
+	fd, err := os.Open(".")
+	if err != nil {
+		t.Fatalf("Open .: %s", err)
+	}
+	// These are chosen carefully not to be symlinks on a Mac
+	// (unlike, say, /var, /etc)
+	dirs := []string{"/", "/usr/bin"}
+	if runtime.GOOS == "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 {
+		err = os.Chdir(d)
+		if err != nil {
+			t.Fatalf("Chdir: %v", err)
+		}
+		pwd, err1 := unix.Getwd()
+		os.Setenv("PWD", oldwd)
+		err2 := fd.Chdir()
+		if err2 != 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", err2)
+			os.Exit(1)
+		}
+		if err != nil {
+			fd.Close()
+			t.Fatalf("Chdir %s: %s", d, err)
+		}
+		if err1 != nil {
+			fd.Close()
+			t.Fatalf("Getwd in %s: %s", d, err1)
+		}
+		if pwd != d {
+			fd.Close()
+			t.Fatalf("Getwd returned %q want %q", pwd, d)
+		}
+	}
+	fd.Close()
+}
+
 // mktmpfifo creates a temporary FIFO and provides a cleanup function.
 func mktmpfifo(t *testing.T) (*os.File, func()) {
 	err := unix.Mkfifo("fifo", 0666)
diff --git a/unix/types_dragonfly.go b/unix/types_dragonfly.go
index d6ccfba..0c63304 100644
--- a/unix/types_dragonfly.go
+++ b/unix/types_dragonfly.go
@@ -127,6 +127,12 @@
 
 type Fsid C.struct_fsid
 
+// File system limits
+
+const (
+	PathMax = C.PATH_MAX
+)
+
 // Sockets
 
 type RawSockaddrInet4 C.struct_sockaddr_in
diff --git a/unix/types_freebsd.go b/unix/types_freebsd.go
index 8ba8b1d..4eb02cd 100644
--- a/unix/types_freebsd.go
+++ b/unix/types_freebsd.go
@@ -216,6 +216,12 @@
 
 type Fsid C.struct_fsid
 
+// File system limits
+
+const (
+	PathMax = C.PATH_MAX
+)
+
 // Advice to Fadvise
 
 const (
diff --git a/unix/types_netbsd.go b/unix/types_netbsd.go
index 9b082a2..10aa9b3 100644
--- a/unix/types_netbsd.go
+++ b/unix/types_netbsd.go
@@ -112,6 +112,12 @@
 
 type Fsid C.fsid_t
 
+// File system limits
+
+const (
+	PathMax = C.PATH_MAX
+)
+
 // Sockets
 
 type RawSockaddrInet4 C.struct_sockaddr_in
diff --git a/unix/types_openbsd.go b/unix/types_openbsd.go
index 4873f3d..649e559 100644
--- a/unix/types_openbsd.go
+++ b/unix/types_openbsd.go
@@ -128,6 +128,12 @@
 
 type Fsid C.fsid_t
 
+// File system limits
+
+const (
+	PathMax = C.PATH_MAX
+)
+
 // Sockets
 
 type RawSockaddrInet4 C.struct_sockaddr_in
diff --git a/unix/zsyscall_dragonfly_amd64.go b/unix/zsyscall_dragonfly_amd64.go
index 2ed340f..a0241de 100644
--- a/unix/zsyscall_dragonfly_amd64.go
+++ b/unix/zsyscall_dragonfly_amd64.go
@@ -423,6 +423,23 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Getcwd(buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func ioctl(fd int, req uint, arg uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
 	if e1 != 0 {
diff --git a/unix/zsyscall_freebsd_386.go b/unix/zsyscall_freebsd_386.go
index 4c9688a..fd9ca5a 100644
--- a/unix/zsyscall_freebsd_386.go
+++ b/unix/zsyscall_freebsd_386.go
@@ -389,6 +389,23 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Getcwd(buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func ioctl(fd int, req uint, arg uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
 	if e1 != 0 {
diff --git a/unix/zsyscall_freebsd_amd64.go b/unix/zsyscall_freebsd_amd64.go
index 434b339..a9f18b2 100644
--- a/unix/zsyscall_freebsd_amd64.go
+++ b/unix/zsyscall_freebsd_amd64.go
@@ -389,6 +389,23 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Getcwd(buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func ioctl(fd int, req uint, arg uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
 	if e1 != 0 {
diff --git a/unix/zsyscall_freebsd_arm.go b/unix/zsyscall_freebsd_arm.go
index ce78c61..9823e18 100644
--- a/unix/zsyscall_freebsd_arm.go
+++ b/unix/zsyscall_freebsd_arm.go
@@ -389,6 +389,23 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Getcwd(buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func ioctl(fd int, req uint, arg uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
 	if e1 != 0 {
diff --git a/unix/zsyscall_netbsd_386.go b/unix/zsyscall_netbsd_386.go
index 04a1ace..62eadff 100644
--- a/unix/zsyscall_netbsd_386.go
+++ b/unix/zsyscall_netbsd_386.go
@@ -406,6 +406,23 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Getcwd(buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func ioctl(fd int, req uint, arg uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
 	if e1 != 0 {
diff --git a/unix/zsyscall_netbsd_amd64.go b/unix/zsyscall_netbsd_amd64.go
index 079824a..307f4e9 100644
--- a/unix/zsyscall_netbsd_amd64.go
+++ b/unix/zsyscall_netbsd_amd64.go
@@ -406,6 +406,23 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Getcwd(buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func ioctl(fd int, req uint, arg uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
 	if e1 != 0 {
diff --git a/unix/zsyscall_netbsd_arm.go b/unix/zsyscall_netbsd_arm.go
index 05f8b49..6110931 100644
--- a/unix/zsyscall_netbsd_arm.go
+++ b/unix/zsyscall_netbsd_arm.go
@@ -406,6 +406,23 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Getcwd(buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func ioctl(fd int, req uint, arg uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
 	if e1 != 0 {
diff --git a/unix/zsyscall_openbsd_386.go b/unix/zsyscall_openbsd_386.go
index 3b55544..003f820 100644
--- a/unix/zsyscall_openbsd_386.go
+++ b/unix/zsyscall_openbsd_386.go
@@ -404,6 +404,23 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Getcwd(buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func ioctl(fd int, req uint, arg uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
 	if e1 != 0 {
diff --git a/unix/zsyscall_openbsd_amd64.go b/unix/zsyscall_openbsd_amd64.go
index cdaf4ef..ba0e8f3 100644
--- a/unix/zsyscall_openbsd_amd64.go
+++ b/unix/zsyscall_openbsd_amd64.go
@@ -404,6 +404,23 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Getcwd(buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func ioctl(fd int, req uint, arg uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
 	if e1 != 0 {
diff --git a/unix/zsyscall_openbsd_arm.go b/unix/zsyscall_openbsd_arm.go
index 6c4dc8a..2ce02c7 100644
--- a/unix/zsyscall_openbsd_arm.go
+++ b/unix/zsyscall_openbsd_arm.go
@@ -404,6 +404,23 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Getcwd(buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS___GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func ioctl(fd int, req uint, arg uintptr) (err error) {
 	_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
 	if e1 != 0 {
diff --git a/unix/ztypes_dragonfly_amd64.go b/unix/ztypes_dragonfly_amd64.go
index 84c2d67..e3b8ebb 100644
--- a/unix/ztypes_dragonfly_amd64.go
+++ b/unix/ztypes_dragonfly_amd64.go
@@ -143,6 +143,10 @@
 	Val [2]int32
 }
 
+const (
+	PathMax = 0x400
+)
+
 type RawSockaddrInet4 struct {
 	Len    uint8
 	Family uint8
diff --git a/unix/ztypes_freebsd_386.go b/unix/ztypes_freebsd_386.go
index f11c787..878a21a 100644
--- a/unix/ztypes_freebsd_386.go
+++ b/unix/ztypes_freebsd_386.go
@@ -141,6 +141,10 @@
 }
 
 const (
+	PathMax = 0x400
+)
+
+const (
 	FADV_NORMAL     = 0x0
 	FADV_RANDOM     = 0x1
 	FADV_SEQUENTIAL = 0x2
diff --git a/unix/ztypes_freebsd_amd64.go b/unix/ztypes_freebsd_amd64.go
index 6580947..8408af1 100644
--- a/unix/ztypes_freebsd_amd64.go
+++ b/unix/ztypes_freebsd_amd64.go
@@ -141,6 +141,10 @@
 }
 
 const (
+	PathMax = 0x400
+)
+
+const (
 	FADV_NORMAL     = 0x0
 	FADV_RANDOM     = 0x1
 	FADV_SEQUENTIAL = 0x2
diff --git a/unix/ztypes_freebsd_arm.go b/unix/ztypes_freebsd_arm.go
index 5a73ab3..4b2d9a4 100644
--- a/unix/ztypes_freebsd_arm.go
+++ b/unix/ztypes_freebsd_arm.go
@@ -143,6 +143,10 @@
 }
 
 const (
+	PathMax = 0x400
+)
+
+const (
 	FADV_NORMAL     = 0x0
 	FADV_RANDOM     = 0x1
 	FADV_SEQUENTIAL = 0x2
diff --git a/unix/ztypes_netbsd_386.go b/unix/ztypes_netbsd_386.go
index 8dae89e..da70faa 100644
--- a/unix/ztypes_netbsd_386.go
+++ b/unix/ztypes_netbsd_386.go
@@ -99,6 +99,10 @@
 	X__fsid_val [2]int32
 }
 
+const (
+	PathMax = 0x400
+)
+
 type RawSockaddrInet4 struct {
 	Len    uint8
 	Family uint8
diff --git a/unix/ztypes_netbsd_amd64.go b/unix/ztypes_netbsd_amd64.go
index 71dab0f..0963ab8 100644
--- a/unix/ztypes_netbsd_amd64.go
+++ b/unix/ztypes_netbsd_amd64.go
@@ -103,6 +103,10 @@
 	X__fsid_val [2]int32
 }
 
+const (
+	PathMax = 0x400
+)
+
 type RawSockaddrInet4 struct {
 	Len    uint8
 	Family uint8
diff --git a/unix/ztypes_netbsd_arm.go b/unix/ztypes_netbsd_arm.go
index a222848..211f641 100644
--- a/unix/ztypes_netbsd_arm.go
+++ b/unix/ztypes_netbsd_arm.go
@@ -104,6 +104,10 @@
 	X__fsid_val [2]int32
 }
 
+const (
+	PathMax = 0x400
+)
+
 type RawSockaddrInet4 struct {
 	Len    uint8
 	Family uint8
diff --git a/unix/ztypes_openbsd_386.go b/unix/ztypes_openbsd_386.go
index 864d727..d5a2d75 100644
--- a/unix/ztypes_openbsd_386.go
+++ b/unix/ztypes_openbsd_386.go
@@ -140,6 +140,10 @@
 	Val [2]int32
 }
 
+const (
+	PathMax = 0x400
+)
+
 type RawSockaddrInet4 struct {
 	Len    uint8
 	Family uint8
diff --git a/unix/ztypes_openbsd_amd64.go b/unix/ztypes_openbsd_amd64.go
index 33f865f..d531410 100644
--- a/unix/ztypes_openbsd_amd64.go
+++ b/unix/ztypes_openbsd_amd64.go
@@ -142,6 +142,10 @@
 	Val [2]int32
 }
 
+const (
+	PathMax = 0x400
+)
+
 type RawSockaddrInet4 struct {
 	Len    uint8
 	Family uint8
diff --git a/unix/ztypes_openbsd_arm.go b/unix/ztypes_openbsd_arm.go
index 91a6626..e35b13b 100644
--- a/unix/ztypes_openbsd_arm.go
+++ b/unix/ztypes_openbsd_arm.go
@@ -140,6 +140,10 @@
 	Val [2]int32
 }
 
+const (
+	PathMax = 0x400
+)
+
 type RawSockaddrInet4 struct {
 	Len    uint8
 	Family uint8