blob: 1dadead21e6d6a1ea5b7edebdbdcdec773dec1c6 [file] [log] [blame]
Andrea Campanella764f1ed2022-03-24 11:46:38 +01001// Copyright 2021 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package unix
6
7import (
Andrea Campanella764f1ed2022-03-24 11:46:38 +01008 "unsafe"
9)
10
11// IoctlRetInt performs an ioctl operation specified by req on a device
12// associated with opened file descriptor fd, and returns a non-negative
13// integer that is returned by the ioctl syscall.
14func IoctlRetInt(fd int, req uint) (int, error) {
15 ret, _, err := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), 0)
16 if err != 0 {
17 return 0, err
18 }
19 return int(ret), nil
20}
21
22func IoctlGetUint32(fd int, req uint) (uint32, error) {
23 var value uint32
kesavandc71914f2022-03-25 11:19:03 +053024 err := ioctlPtr(fd, req, unsafe.Pointer(&value))
Andrea Campanella764f1ed2022-03-24 11:46:38 +010025 return value, err
26}
27
28func IoctlGetRTCTime(fd int) (*RTCTime, error) {
29 var value RTCTime
kesavandc71914f2022-03-25 11:19:03 +053030 err := ioctlPtr(fd, RTC_RD_TIME, unsafe.Pointer(&value))
Andrea Campanella764f1ed2022-03-24 11:46:38 +010031 return &value, err
32}
33
34func IoctlSetRTCTime(fd int, value *RTCTime) error {
kesavandc71914f2022-03-25 11:19:03 +053035 return ioctlPtr(fd, RTC_SET_TIME, unsafe.Pointer(value))
Andrea Campanella764f1ed2022-03-24 11:46:38 +010036}
37
38func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) {
39 var value RTCWkAlrm
kesavandc71914f2022-03-25 11:19:03 +053040 err := ioctlPtr(fd, RTC_WKALM_RD, unsafe.Pointer(&value))
Andrea Campanella764f1ed2022-03-24 11:46:38 +010041 return &value, err
42}
43
44func IoctlSetRTCWkAlrm(fd int, value *RTCWkAlrm) error {
kesavandc71914f2022-03-25 11:19:03 +053045 return ioctlPtr(fd, RTC_WKALM_SET, unsafe.Pointer(value))
Andrea Campanella764f1ed2022-03-24 11:46:38 +010046}
47
48// IoctlGetEthtoolDrvinfo fetches ethtool driver information for the network
49// device specified by ifname.
50func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) {
kesavandc71914f2022-03-25 11:19:03 +053051 ifr, err := NewIfreq(ifname)
52 if err != nil {
53 return nil, err
Andrea Campanella764f1ed2022-03-24 11:46:38 +010054 }
55
kesavandc71914f2022-03-25 11:19:03 +053056 value := EthtoolDrvinfo{Cmd: ETHTOOL_GDRVINFO}
57 ifrd := ifr.withData(unsafe.Pointer(&value))
58
59 err = ioctlIfreqData(fd, SIOCETHTOOL, &ifrd)
Andrea Campanella764f1ed2022-03-24 11:46:38 +010060 return &value, err
61}
62
63// IoctlGetWatchdogInfo fetches information about a watchdog device from the
64// Linux watchdog API. For more information, see:
65// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html.
66func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) {
67 var value WatchdogInfo
kesavandc71914f2022-03-25 11:19:03 +053068 err := ioctlPtr(fd, WDIOC_GETSUPPORT, unsafe.Pointer(&value))
Andrea Campanella764f1ed2022-03-24 11:46:38 +010069 return &value, err
70}
71
72// IoctlWatchdogKeepalive issues a keepalive ioctl to a watchdog device. For
73// more information, see:
74// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html.
75func IoctlWatchdogKeepalive(fd int) error {
kesavandc71914f2022-03-25 11:19:03 +053076 // arg is ignored and not a pointer, so ioctl is fine instead of ioctlPtr.
Andrea Campanella764f1ed2022-03-24 11:46:38 +010077 return ioctl(fd, WDIOC_KEEPALIVE, 0)
78}
79
80// IoctlFileCloneRange performs an FICLONERANGE ioctl operation to clone the
81// range of data conveyed in value to the file associated with the file
82// descriptor destFd. See the ioctl_ficlonerange(2) man page for details.
83func IoctlFileCloneRange(destFd int, value *FileCloneRange) error {
kesavandc71914f2022-03-25 11:19:03 +053084 return ioctlPtr(destFd, FICLONERANGE, unsafe.Pointer(value))
Andrea Campanella764f1ed2022-03-24 11:46:38 +010085}
86
87// IoctlFileClone performs an FICLONE ioctl operation to clone the entire file
88// associated with the file description srcFd to the file associated with the
89// file descriptor destFd. See the ioctl_ficlone(2) man page for details.
90func IoctlFileClone(destFd, srcFd int) error {
91 return ioctl(destFd, FICLONE, uintptr(srcFd))
92}
93
94type FileDedupeRange struct {
95 Src_offset uint64
96 Src_length uint64
97 Reserved1 uint16
98 Reserved2 uint32
99 Info []FileDedupeRangeInfo
100}
101
102type FileDedupeRangeInfo struct {
103 Dest_fd int64
104 Dest_offset uint64
105 Bytes_deduped uint64
106 Status int32
107 Reserved uint32
108}
109
110// IoctlFileDedupeRange performs an FIDEDUPERANGE ioctl operation to share the
111// range of data conveyed in value from the file associated with the file
112// descriptor srcFd to the value.Info destinations. See the
113// ioctl_fideduperange(2) man page for details.
114func IoctlFileDedupeRange(srcFd int, value *FileDedupeRange) error {
115 buf := make([]byte, SizeofRawFileDedupeRange+
116 len(value.Info)*SizeofRawFileDedupeRangeInfo)
117 rawrange := (*RawFileDedupeRange)(unsafe.Pointer(&buf[0]))
118 rawrange.Src_offset = value.Src_offset
119 rawrange.Src_length = value.Src_length
120 rawrange.Dest_count = uint16(len(value.Info))
121 rawrange.Reserved1 = value.Reserved1
122 rawrange.Reserved2 = value.Reserved2
123
124 for i := range value.Info {
125 rawinfo := (*RawFileDedupeRangeInfo)(unsafe.Pointer(
126 uintptr(unsafe.Pointer(&buf[0])) + uintptr(SizeofRawFileDedupeRange) +
127 uintptr(i*SizeofRawFileDedupeRangeInfo)))
128 rawinfo.Dest_fd = value.Info[i].Dest_fd
129 rawinfo.Dest_offset = value.Info[i].Dest_offset
130 rawinfo.Bytes_deduped = value.Info[i].Bytes_deduped
131 rawinfo.Status = value.Info[i].Status
132 rawinfo.Reserved = value.Info[i].Reserved
133 }
134
kesavandc71914f2022-03-25 11:19:03 +0530135 err := ioctlPtr(srcFd, FIDEDUPERANGE, unsafe.Pointer(&buf[0]))
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100136
137 // Output
138 for i := range value.Info {
139 rawinfo := (*RawFileDedupeRangeInfo)(unsafe.Pointer(
140 uintptr(unsafe.Pointer(&buf[0])) + uintptr(SizeofRawFileDedupeRange) +
141 uintptr(i*SizeofRawFileDedupeRangeInfo)))
142 value.Info[i].Dest_fd = rawinfo.Dest_fd
143 value.Info[i].Dest_offset = rawinfo.Dest_offset
144 value.Info[i].Bytes_deduped = rawinfo.Bytes_deduped
145 value.Info[i].Status = rawinfo.Status
146 value.Info[i].Reserved = rawinfo.Reserved
147 }
148
149 return err
150}
151
152func IoctlHIDGetDesc(fd int, value *HIDRawReportDescriptor) error {
kesavandc71914f2022-03-25 11:19:03 +0530153 return ioctlPtr(fd, HIDIOCGRDESC, unsafe.Pointer(value))
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100154}
155
156func IoctlHIDGetRawInfo(fd int) (*HIDRawDevInfo, error) {
157 var value HIDRawDevInfo
kesavandc71914f2022-03-25 11:19:03 +0530158 err := ioctlPtr(fd, HIDIOCGRAWINFO, unsafe.Pointer(&value))
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100159 return &value, err
160}
161
162func IoctlHIDGetRawName(fd int) (string, error) {
163 var value [_HIDIOCGRAWNAME_LEN]byte
kesavandc71914f2022-03-25 11:19:03 +0530164 err := ioctlPtr(fd, _HIDIOCGRAWNAME, unsafe.Pointer(&value[0]))
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100165 return ByteSliceToString(value[:]), err
166}
167
168func IoctlHIDGetRawPhys(fd int) (string, error) {
169 var value [_HIDIOCGRAWPHYS_LEN]byte
kesavandc71914f2022-03-25 11:19:03 +0530170 err := ioctlPtr(fd, _HIDIOCGRAWPHYS, unsafe.Pointer(&value[0]))
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100171 return ByteSliceToString(value[:]), err
172}
173
174func IoctlHIDGetRawUniq(fd int) (string, error) {
175 var value [_HIDIOCGRAWUNIQ_LEN]byte
kesavandc71914f2022-03-25 11:19:03 +0530176 err := ioctlPtr(fd, _HIDIOCGRAWUNIQ, unsafe.Pointer(&value[0]))
Andrea Campanella764f1ed2022-03-24 11:46:38 +0100177 return ByteSliceToString(value[:]), err
178}
kesavandc71914f2022-03-25 11:19:03 +0530179
180// IoctlIfreq performs an ioctl using an Ifreq structure for input and/or
181// output. See the netdevice(7) man page for details.
182func IoctlIfreq(fd int, req uint, value *Ifreq) error {
183 // It is possible we will add more fields to *Ifreq itself later to prevent
184 // misuse, so pass the raw *ifreq directly.
185 return ioctlPtr(fd, req, unsafe.Pointer(&value.raw))
186}
187
188// TODO(mdlayher): export if and when IfreqData is exported.
189
190// ioctlIfreqData performs an ioctl using an ifreqData structure for input
191// and/or output. See the netdevice(7) man page for details.
192func ioctlIfreqData(fd int, req uint, value *ifreqData) error {
193 // The memory layout of IfreqData (type-safe) and ifreq (not type-safe) are
194 // identical so pass *IfreqData directly.
195 return ioctlPtr(fd, req, unsafe.Pointer(value))
196}