Add std.os.ioctl

This commit is contained in:
Luna 2020-04-20 16:34:37 -03:00 committed by Andrew Kelley
parent c7b790ded6
commit c8468bed42
3 changed files with 28 additions and 24 deletions

View File

@ -545,24 +545,12 @@ fn if_nametoindex(name: []const u8) !u32 {
std.mem.copy(u8, &ifr.ifr_ifrn.name, name);
ifr.ifr_ifrn.name[name.len] = 0;
const rc = os.system.syscall3(
os.linux.SYS_ioctl,
@bitCast(usize, @as(isize, sockfd)),
os.linux.SIOCGIFINDEX,
@ptrToInt(&ifr),
);
switch (os.errno(rc)) {
os.EBADF => return error.BadFile,
os.EINTR => return error.CaughtSignal,
os.EIO => return error.FileSystem,
os.EINVAL => unreachable,
os.ENOTTY => unreachable,
os.ENXIO => unreachable,
// ioctl() sends ENODEV for an unknown scope id.
os.ENODEV => return error.InterfaceNotFound,
else => {},
}
std.os.ioctl(sockfd, os.linux.SIOCGIFINDEX, @ptrToInt(&ifr)) catch |err| {
switch (err) {
error.NoDevice => return error.InterfaceNotFound,
else => return err,
}
};
return @bitCast(u32, ifr.ifr_ifru.ifru_ivalue);
}

View File

@ -405,7 +405,6 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize {
else => |err| return unexpectedErrno(err),
}
}
const iov_count = math.cast(u31, iov.len) catch math.maxInt(u31);
while (true) {
// TODO handle the case when iov_len is too large and get rid of this @intCast
@ -2451,9 +2450,8 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t
if (builtin.os.tag == .windows) {
// NOTE: windows translates the SOCK_NONBLOCK/SOCK_CLOEXEC flags into windows-analagous operations
const filtered_sock_type = socket_type & ~@as(u32, SOCK_NONBLOCK | SOCK_CLOEXEC);
const flags : u32 = if ((socket_type & SOCK_CLOEXEC) != 0) windows.ws2_32.WSA_FLAG_NO_HANDLE_INHERIT else 0;
const rc = windows.ws2_32.WSASocketW(@intCast(c_int, domain), @intCast(c_int, filtered_sock_type),
@intCast(c_int, protocol), null, 0, flags);
const flags: u32 = if ((socket_type & SOCK_CLOEXEC) != 0) windows.ws2_32.WSA_FLAG_NO_HANDLE_INHERIT else 0;
const rc = windows.ws2_32.WSASocketW(@intCast(c_int, domain), @intCast(c_int, filtered_sock_type), @intCast(c_int, protocol), null, 0, flags);
if (rc == windows.ws2_32.INVALID_SOCKET) switch (windows.ws2_32.WSAGetLastError()) {
.WSAEMFILE => return error.ProcessFdQuotaExceeded,
.WSAENOBUFS => return error.SystemResources,
@ -2463,7 +2461,7 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t
};
errdefer windows.closesocket(rc) catch unreachable;
if ((socket_type & SOCK_NONBLOCK) != 0) {
var mode : c_ulong = 1; // nonblocking
var mode: c_ulong = 1; // nonblocking
if (windows.ws2_32.SOCKET_ERROR == windows.ws2_32.ioctlsocket(rc, windows.ws2_32.FIONBIO, &mode)) {
switch (windows.ws2_32.WSAGetLastError()) {
// have not identified any error codes that should be handled yet
@ -2858,7 +2856,7 @@ pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) Con
.WSAECONNREFUSED => return error.ConnectionRefused,
.WSAETIMEDOUT => return error.ConnectionTimedOut,
.WSAEHOSTUNREACH // TODO: should we return NetworkUnreachable in this case as well?
,.WSAENETUNREACH => return error.NetworkUnreachable,
, .WSAENETUNREACH => return error.NetworkUnreachable,
.WSAEFAULT => unreachable,
.WSAEINVAL => unreachable,
.WSAEISCONN => unreachable,
@ -4906,3 +4904,17 @@ pub fn tcsetattr(handle: fd_t, optional_action: TCSA, termios_p: termios) Termio
}
}
}
pub fn ioctl(handle: fd_t, request: u32, arg: var) !void {
switch (errno(system.ioctl(handle, request, arg))) {
0 => {},
EINVAL => unreachable,
ENOTTY => unreachable,
ENXIO => unreachable,
EBADF => return error.BadFile,
EINTR => return error.CaughtSignal,
EIO => return error.FileSystem,
ENODEV => return error.NoDevice,
else => |err| return unexpectedErrno(err),
}
}

View File

@ -1193,6 +1193,10 @@ pub fn tcsetattr(fd: fd_t, optional_action: TCSA, termios_p: *const termios) usi
return syscall3(.ioctl, @bitCast(usize, @as(isize, fd)), TCSETS + @enumToInt(optional_action), @ptrToInt(termios_p));
}
pub fn ioctl(fd: fd_t, request: u32, arg: var) usize {
return syscall3(.ioctl, @bitCast(usize, @as(isize, fd)), request, arg);
}
test "" {
if (builtin.os.tag == .linux) {
_ = @import("linux/test.zig");