sys/unix/ioctl_unsigned.go

70 строки
2.3 KiB
Go
Исходник Постоянная ссылка Обычный вид История

// Copyright 2018 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 darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd
package unix
import (
"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))
}
// IoctlSetPointerInt performs an ioctl operation which sets an
// integer value on fd, using the specified request number. The ioctl
// argument is called with a pointer to the integer value, rather than
// passing the integer value directly.
func IoctlSetPointerInt(fd int, req uint, value int) error {
v := int32(value)
return ioctlPtr(fd, req, unsafe.Pointer(&v))
}
// 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.
return ioctlPtr(fd, req, unsafe.Pointer(value))
}
// IoctlSetTermios performs an ioctl on fd with a *Termios.
//
// The req value will usually be TCSETA or TIOCSETA.
func IoctlSetTermios(fd int, req uint, value *Termios) error {
// TODO: if we get the chance, remove the req parameter.
return ioctlPtr(fd, req, unsafe.Pointer(value))
}
// IoctlGetInt performs an ioctl operation which gets an integer value
// from fd, using the specified request number.
unix: add IoctlRetInt for Linux Add IoctlRetInt() for ioctls that use syscall's return value as an output parameter. Add a unit test for Linux, and the NS_GET_ defines that it requires (see ioctl_ns(2)). Motivation: Currently, x/sys/unix provides a few functions to deal with ioctls. In particular, IoctlGetInt(), which "performs an ioctl operation which gets an integer value". It does that by passing a pointer to an integer to a syscall and returning that integer. The value returned from syscall is treated as success/failure flag (0 means success, -1 means failure, and in such case errno is used to figure out the underlying error). It appears that there are a few ioctls in Linux and at least one in Solaris, which do not use the above way to return an int, instead they use the syscall's return value (in case it's not negative). As Linux ioctl(2) man page says, > RETURN VALUE > Usually, on success zero is returned. A few ioctl() requests > use the return value as an output parameter and return > a nonnegative value on success. On error, -1 is returned, > and errno is set appropriately. Currently I am aware of at least 6 Linux ioctls that do that (return the value directly): * LOOP_CTL_* ioctls on /dev/loop-control (all 3 of them). Source: loop(4) * NS_* ioctls (3 out of 4) on /proc/PID/ns/*. Source: ioctl_ns(2) And one in Solaris: * I_FIND ioctl, source: streamio(7i). There might be some more ioctls like the ones above, but since ioctls are scarcely documented, it is hard to say how many more. Obviously, using IoctlGetInt() for such ioctls would be a big mistake, as 0 will always be returned. For example, there was a bug in Docker's pkg/loopback (moby/moby#39801). [v6: make it linux-specific for now] Fixes golang/go#33966 Change-Id: Ie64f72fd84101b955ba14519a357e06a66d685d0 Reviewed-on: https://go-review.googlesource.com/c/sys/+/192780 Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
2019-09-02 03:21:42 +03:00
//
// 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 := ioctlPtr(fd, req, unsafe.Pointer(&value))
return value, err
}
func IoctlGetWinsize(fd int, req uint) (*Winsize, error) {
var value Winsize
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
return &value, err
}
func IoctlGetTermios(fd int, req uint) (*Termios, error) {
var value Termios
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
return &value, err
}