x/sys/unix: add support for O_TMPFILE in Linux

Since Linux 3.11, O_TMPFILE flag can be used in open syscall to create
an unnamed file in a directory. The file occupies space in the
filesystem, and can be given a name using linkat syscall. If the file is
closed without being given a name, its contents are deleted.

See the manpage open(2) in Linux for details.

Exports O_TMPFILE for Linux in 386 and amd64 (other architectures
already had it). Exports Linkat syscall and AT_SYMLINK_FOLLOW (used for
giving a name to the file) for all Linux in all architectures.

Fixes golang/go#7830.

Change-Id: Ib82e44f405b227e227b9cbf317c2657b32e046f5
Reviewed-on: https://go-review.googlesource.com/21003
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go
index 88c8e04..464344e 100644
--- a/unix/syscall_linux.go
+++ b/unix/syscall_linux.go
@@ -36,10 +36,10 @@
 	return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode)
 }
 
-//sys	linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error)
+//sys	Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error)
 
 func Link(oldpath string, newpath string) (err error) {
-	return linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0)
+	return Linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0)
 }
 
 func Mkdir(path string, mode uint32) (err error) {
diff --git a/unix/types_linux.go b/unix/types_linux.go
index 16378fa..7b53590 100644
--- a/unix/types_linux.go
+++ b/unix/types_linux.go
@@ -400,6 +400,7 @@
 const (
 	AT_FDCWD            = C.AT_FDCWD
 	AT_REMOVEDIR        = C.AT_REMOVEDIR
+	AT_SYMLINK_FOLLOW   = C.AT_SYMLINK_FOLLOW
 	AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
 )
 
diff --git a/unix/zerrors_linux_386.go b/unix/zerrors_linux_386.go
index d370be0..80b7381 100644
--- a/unix/zerrors_linux_386.go
+++ b/unix/zerrors_linux_386.go
@@ -826,6 +826,7 @@
 	O_RDWR                           = 0x2
 	O_RSYNC                          = 0x101000
 	O_SYNC                           = 0x101000
+	O_TMPFILE                        = 0x410000
 	O_TRUNC                          = 0x200
 	O_WRONLY                         = 0x1
 	PACKET_ADD_MEMBERSHIP            = 0x1
diff --git a/unix/zerrors_linux_amd64.go b/unix/zerrors_linux_amd64.go
index b83fb40..64cc0b7 100644
--- a/unix/zerrors_linux_amd64.go
+++ b/unix/zerrors_linux_amd64.go
@@ -826,6 +826,7 @@
 	O_RDWR                           = 0x2
 	O_RSYNC                          = 0x101000
 	O_SYNC                           = 0x101000
+	O_TMPFILE                        = 0x410000
 	O_TRUNC                          = 0x200
 	O_WRONLY                         = 0x1
 	PACKET_ADD_MEMBERSHIP            = 0x1
diff --git a/unix/zsyscall_linux_386.go b/unix/zsyscall_linux_386.go
index 106cd59..fe1f1dd 100644
--- a/unix/zsyscall_linux_386.go
+++ b/unix/zsyscall_linux_386.go
@@ -14,7 +14,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
+func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)
 	if err != nil {
diff --git a/unix/zsyscall_linux_amd64.go b/unix/zsyscall_linux_amd64.go
index c1bae65..510cb1b 100644
--- a/unix/zsyscall_linux_amd64.go
+++ b/unix/zsyscall_linux_amd64.go
@@ -14,7 +14,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
+func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)
 	if err != nil {
diff --git a/unix/zsyscall_linux_arm.go b/unix/zsyscall_linux_arm.go
index 3383f97..28c720f 100644
--- a/unix/zsyscall_linux_arm.go
+++ b/unix/zsyscall_linux_arm.go
@@ -14,7 +14,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
+func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)
 	if err != nil {
diff --git a/unix/zsyscall_linux_arm64.go b/unix/zsyscall_linux_arm64.go
index fb2ff3a..1ac5421 100644
--- a/unix/zsyscall_linux_arm64.go
+++ b/unix/zsyscall_linux_arm64.go
@@ -14,7 +14,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
+func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)
 	if err != nil {
diff --git a/unix/zsyscall_linux_mips64.go b/unix/zsyscall_linux_mips64.go
index 7eac55b..7247005 100644
--- a/unix/zsyscall_linux_mips64.go
+++ b/unix/zsyscall_linux_mips64.go
@@ -14,7 +14,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
+func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)
 	if err != nil {
diff --git a/unix/zsyscall_linux_mips64le.go b/unix/zsyscall_linux_mips64le.go
index e8b61a6..1b7fb64 100644
--- a/unix/zsyscall_linux_mips64le.go
+++ b/unix/zsyscall_linux_mips64le.go
@@ -14,7 +14,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
+func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)
 	if err != nil {
diff --git a/unix/zsyscall_linux_ppc64.go b/unix/zsyscall_linux_ppc64.go
index 9c9fcb2..2b4cd7d 100644
--- a/unix/zsyscall_linux_ppc64.go
+++ b/unix/zsyscall_linux_ppc64.go
@@ -14,7 +14,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
+func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)
 	if err != nil {
diff --git a/unix/zsyscall_linux_ppc64le.go b/unix/zsyscall_linux_ppc64le.go
index 692a1e1..7e1708d 100644
--- a/unix/zsyscall_linux_ppc64le.go
+++ b/unix/zsyscall_linux_ppc64le.go
@@ -14,7 +14,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
+func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)
 	if err != nil {
diff --git a/unix/ztypes_linux_386.go b/unix/ztypes_linux_386.go
index cf5db0e..650bf22 100644
--- a/unix/ztypes_linux_386.go
+++ b/unix/ztypes_linux_386.go
@@ -574,8 +574,9 @@
 
 const (
 	AT_FDCWD            = -0x64
-	AT_SYMLINK_NOFOLLOW = 0x100
 	AT_REMOVEDIR        = 0x200
+	AT_SYMLINK_FOLLOW   = 0x400
+	AT_SYMLINK_NOFOLLOW = 0x100
 )
 
 type Termios struct {
diff --git a/unix/ztypes_linux_amd64.go b/unix/ztypes_linux_amd64.go
index ac27784..539ec3c 100644
--- a/unix/ztypes_linux_amd64.go
+++ b/unix/ztypes_linux_amd64.go
@@ -592,8 +592,9 @@
 
 const (
 	AT_FDCWD            = -0x64
-	AT_SYMLINK_NOFOLLOW = 0x100
 	AT_REMOVEDIR        = 0x200
+	AT_SYMLINK_FOLLOW   = 0x400
+	AT_SYMLINK_NOFOLLOW = 0x100
 )
 
 type Termios struct {
diff --git a/unix/ztypes_linux_arm.go b/unix/ztypes_linux_arm.go
index b318bb8..f437a49 100644
--- a/unix/ztypes_linux_arm.go
+++ b/unix/ztypes_linux_arm.go
@@ -563,8 +563,9 @@
 
 const (
 	AT_FDCWD            = -0x64
-	AT_SYMLINK_NOFOLLOW = 0x100
 	AT_REMOVEDIR        = 0x200
+	AT_SYMLINK_FOLLOW   = 0x400
+	AT_SYMLINK_NOFOLLOW = 0x100
 )
 
 type Termios struct {
diff --git a/unix/ztypes_linux_arm64.go b/unix/ztypes_linux_arm64.go
index a159aad..1028fcd 100644
--- a/unix/ztypes_linux_arm64.go
+++ b/unix/ztypes_linux_arm64.go
@@ -580,6 +580,7 @@
 const (
 	AT_FDCWD            = -0x64
 	AT_REMOVEDIR        = 0x200
+	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 )
 
diff --git a/unix/ztypes_linux_mips64.go b/unix/ztypes_linux_mips64.go
index 0c5c918..f08b531 100644
--- a/unix/ztypes_linux_mips64.go
+++ b/unix/ztypes_linux_mips64.go
@@ -585,6 +585,7 @@
 const (
 	AT_FDCWD            = -0x64
 	AT_REMOVEDIR        = 0x200
+	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 )
 
diff --git a/unix/ztypes_linux_mips64le.go b/unix/ztypes_linux_mips64le.go
index 7c0c803..45e0df6 100644
--- a/unix/ztypes_linux_mips64le.go
+++ b/unix/ztypes_linux_mips64le.go
@@ -585,6 +585,7 @@
 const (
 	AT_FDCWD            = -0x64
 	AT_REMOVEDIR        = 0x200
+	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 )
 
diff --git a/unix/ztypes_linux_ppc64.go b/unix/ztypes_linux_ppc64.go
index b14cbfe..2bc296e 100644
--- a/unix/ztypes_linux_ppc64.go
+++ b/unix/ztypes_linux_ppc64.go
@@ -590,6 +590,7 @@
 const (
 	AT_FDCWD            = -0x64
 	AT_REMOVEDIR        = 0x200
+	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 )
 
diff --git a/unix/ztypes_linux_ppc64le.go b/unix/ztypes_linux_ppc64le.go
index 22c96a2..0a66893 100644
--- a/unix/ztypes_linux_ppc64le.go
+++ b/unix/ztypes_linux_ppc64le.go
@@ -590,6 +590,7 @@
 const (
 	AT_FDCWD            = -0x64
 	AT_REMOVEDIR        = 0x200
+	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 )