浏览代码

unix: add IoctlGetInt and IoctlSetInt on Linux

This CL adds basic integer get/set functions which wrap a generic
ioctl call.  The API is similar the one introduced for solaris/amd64
in CL 14587, but the request parameter has been changed to a uint
instead of an int.  This makes requests with a number larger than the
maximum signed 32-bit integer work on linux/386.

For consistency, the solaris/amd64 API has also been updated to make
use of a uint instead of an int for the request number.

Fixes golang/go#20474

Change-Id: Iaae1ee2e4bb4bfcc420dcec252fe53c8d90ce81d
Reviewed-on: https://go-review.googlesource.com/44009
Run-TryBot: Matt Layher <mdlayher@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Matt Layher 8 年之前
父节点
当前提交
a55a760868

+ 3 - 0
unix/linux/types.go

@@ -59,6 +59,7 @@ package unix
 #include <linux/if_alg.h>
 #include <linux/fs.h>
 #include <linux/vm_sockets.h>
+#include <linux/random.h>
 
 // On mips64, the glibc stat and kernel stat do not agree
 #if (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI64)
@@ -530,6 +531,8 @@ const (
 
 type Sigset_t C.sigset_t
 
+const RNDGETENTCNT = C.RNDGETENTCNT
+
 // sysconf information
 
 const _SC_PAGESIZE = C._SC_PAGESIZE

+ 19 - 1
unix/syscall_linux.go

@@ -36,6 +36,25 @@ func Creat(path string, mode uint32) (fd int, err error) {
 	return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode)
 }
 
+//sys	ioctl(fd int, req uint, arg uintptr) (err error)
+
+// 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) (err error) {
+	return ioctl(fd, req, uintptr(value))
+}
+
+// IoctlGetInt performs an ioctl operation which gets an integer value
+// from fd, using the specified request number.
+func IoctlGetInt(fd int, req uint) (int, error) {
+	var value int
+	err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
+	return value, err
+}
+
 //sys	Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error)
 
 func Link(oldpath string, newpath string) (err error) {
@@ -1312,7 +1331,6 @@ func Vmsplice(fd int, iovs []Iovec, flags int) (int, error) {
 // IoGetevents
 // IoSetup
 // IoSubmit
-// Ioctl
 // IoprioGet
 // IoprioSet
 // KexecLoad

+ 15 - 0
unix/syscall_linux_test.go

@@ -15,6 +15,21 @@ import (
 	"golang.org/x/sys/unix"
 )
 
+func TestIoctlGetInt(t *testing.T) {
+	f, err := os.Open("/dev/random")
+	if err != nil {
+		t.Fatalf("failed to open device: %v", err)
+	}
+	defer f.Close()
+
+	v, err := unix.IoctlGetInt(int(f.Fd()), unix.RNDGETENTCNT)
+	if err != nil {
+		t.Fatalf("failed to perform ioctl: %v", err)
+	}
+
+	t.Logf("%d bits of entropy available", v)
+}
+
 func TestPoll(t *testing.T) {
 	f, cleanup := mktmpfifo(t)
 	defer cleanup()

+ 9 - 9
unix/syscall_solaris.go

@@ -519,43 +519,43 @@ func Acct(path string) (err error) {
  * Expose the ioctl function
  */
 
-//sys	ioctl(fd int, req int, arg uintptr) (err error)
+//sys	ioctl(fd int, req uint, arg uintptr) (err error)
 
-func IoctlSetInt(fd int, req int, value int) (err error) {
+func IoctlSetInt(fd int, req uint, value int) (err error) {
 	return ioctl(fd, req, uintptr(value))
 }
 
-func IoctlSetWinsize(fd int, req int, value *Winsize) (err error) {
+func IoctlSetWinsize(fd int, req uint, value *Winsize) (err error) {
 	return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
 }
 
-func IoctlSetTermios(fd int, req int, value *Termios) (err error) {
+func IoctlSetTermios(fd int, req uint, value *Termios) (err error) {
 	return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
 }
 
-func IoctlSetTermio(fd int, req int, value *Termio) (err error) {
+func IoctlSetTermio(fd int, req uint, value *Termio) (err error) {
 	return ioctl(fd, req, uintptr(unsafe.Pointer(value)))
 }
 
-func IoctlGetInt(fd int, req int) (int, error) {
+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 int) (*Winsize, error) {
+func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
 	var value Winsize
 	err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
 	return &value, err
 }
 
-func IoctlGetTermios(fd int, req int) (*Termios, error) {
+func IoctlGetTermios(fd int, req uint) (*Termios, error) {
 	var value Termios
 	err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
 	return &value, err
 }
 
-func IoctlGetTermio(fd int, req int) (*Termio, error) {
+func IoctlGetTermio(fd int, req uint) (*Termio, error) {
 	var value Termio
 	err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
 	return &value, err

+ 10 - 0
unix/zsyscall_linux_386.go

@@ -14,6 +14,16 @@ var _ syscall.Errno
 
 // 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 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// 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) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)

+ 10 - 0
unix/zsyscall_linux_amd64.go

@@ -14,6 +14,16 @@ var _ syscall.Errno
 
 // 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 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// 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) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)

+ 10 - 0
unix/zsyscall_linux_arm.go

@@ -14,6 +14,16 @@ var _ syscall.Errno
 
 // 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 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// 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) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)

+ 10 - 0
unix/zsyscall_linux_arm64.go

@@ -14,6 +14,16 @@ var _ syscall.Errno
 
 // 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 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// 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) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)

+ 10 - 0
unix/zsyscall_linux_mips.go

@@ -14,6 +14,16 @@ var _ syscall.Errno
 
 // 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 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// 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) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)

+ 10 - 0
unix/zsyscall_linux_mips64.go

@@ -14,6 +14,16 @@ var _ syscall.Errno
 
 // 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 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// 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) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)

+ 10 - 0
unix/zsyscall_linux_mips64le.go

@@ -14,6 +14,16 @@ var _ syscall.Errno
 
 // 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 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// 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) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)

+ 10 - 0
unix/zsyscall_linux_mipsle.go

@@ -14,6 +14,16 @@ var _ syscall.Errno
 
 // 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 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// 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) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)

+ 10 - 0
unix/zsyscall_linux_ppc64.go

@@ -14,6 +14,16 @@ var _ syscall.Errno
 
 // 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 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// 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) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)

+ 10 - 0
unix/zsyscall_linux_ppc64le.go

@@ -14,6 +14,16 @@ var _ syscall.Errno
 
 // 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 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// 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) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)

+ 10 - 0
unix/zsyscall_linux_s390x.go

@@ -14,6 +14,16 @@ var _ syscall.Errno
 
 // 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 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// 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) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(oldpath)

+ 1 - 1
unix/zsyscall_solaris_amd64.go

@@ -519,7 +519,7 @@ func acct(path *byte) (err error) {
 	return
 }
 
-func ioctl(fd int, req int, arg uintptr) (err error) {
+func ioctl(fd int, req uint, arg uintptr) (err error) {
 	_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procioctl)), 3, uintptr(fd), uintptr(req), uintptr(arg), 0, 0, 0)
 	if e1 != 0 {
 		err = e1

+ 2 - 0
unix/ztypes_linux_386.go

@@ -660,6 +660,8 @@ type Sigset_t struct {
 	X__val [32]uint32
 }
 
+const RNDGETENTCNT = 0x80045200
+
 const _SC_PAGESIZE = 0x1e
 
 type Termios struct {

+ 2 - 0
unix/ztypes_linux_amd64.go

@@ -678,6 +678,8 @@ type Sigset_t struct {
 	X__val [16]uint64
 }
 
+const RNDGETENTCNT = 0x80045200
+
 const _SC_PAGESIZE = 0x1e
 
 type Termios struct {

+ 2 - 0
unix/ztypes_linux_arm.go

@@ -649,6 +649,8 @@ type Sigset_t struct {
 	X__val [32]uint32
 }
 
+const RNDGETENTCNT = 0x80045200
+
 const _SC_PAGESIZE = 0x1e
 
 type Termios struct {

+ 2 - 0
unix/ztypes_linux_arm64.go

@@ -657,6 +657,8 @@ type Sigset_t struct {
 	X__val [16]uint64
 }
 
+const RNDGETENTCNT = 0x80045200
+
 const _SC_PAGESIZE = 0x1e
 
 type Termios struct {

+ 2 - 0
unix/ztypes_linux_mips.go

@@ -654,6 +654,8 @@ type Sigset_t struct {
 	X__val [32]uint32
 }
 
+const RNDGETENTCNT = 0x40045200
+
 const _SC_PAGESIZE = 0x1e
 
 type Termios struct {

+ 2 - 0
unix/ztypes_linux_mips64.go

@@ -659,6 +659,8 @@ type Sigset_t struct {
 	X__val [16]uint64
 }
 
+const RNDGETENTCNT = 0x40045200
+
 const _SC_PAGESIZE = 0x1e
 
 type Termios struct {

+ 2 - 0
unix/ztypes_linux_mips64le.go

@@ -659,6 +659,8 @@ type Sigset_t struct {
 	X__val [16]uint64
 }
 
+const RNDGETENTCNT = 0x40045200
+
 const _SC_PAGESIZE = 0x1e
 
 type Termios struct {

+ 2 - 0
unix/ztypes_linux_mipsle.go

@@ -654,6 +654,8 @@ type Sigset_t struct {
 	X__val [32]uint32
 }
 
+const RNDGETENTCNT = 0x40045200
+
 const _SC_PAGESIZE = 0x1e
 
 type Termios struct {

+ 2 - 0
unix/ztypes_linux_ppc64.go

@@ -667,6 +667,8 @@ type Sigset_t struct {
 	X__val [16]uint64
 }
 
+const RNDGETENTCNT = 0x40045200
+
 const _SC_PAGESIZE = 0x1e
 
 type Termios struct {

+ 2 - 0
unix/ztypes_linux_ppc64le.go

@@ -667,6 +667,8 @@ type Sigset_t struct {
 	X__val [16]uint64
 }
 
+const RNDGETENTCNT = 0x40045200
+
 const _SC_PAGESIZE = 0x1e
 
 type Termios struct {

+ 2 - 0
unix/ztypes_linux_s390x.go

@@ -684,6 +684,8 @@ type Sigset_t struct {
 	_ [16]uint64
 }
 
+const RNDGETENTCNT = 0x80045200
+
 const _SC_PAGESIZE = 0x1e
 
 type Termios struct {