| author | |
| committer | |
| log | 7fd937fef4547a98d7c33ea67eca76e6336f9152 |
| tree | 9122d4a2eab8b9deef81e089cecee0e7699a08fa |
| parent | 0d091dc92374a49c41d406b5bf9a4b508a3d450c |
* improve docs
* add TODO comments for things that don't have open issues
* remove redundant namespacing of struct fields
* guard against ioctl returning EINTR
* remove the general std.os.ioctl function in favor of the specific
ioctl_SIOCGIFINDEX function. This allows us to have a more precise
error set, and more type-safe API.5 files changed, 66 insertions(+), 50 deletions(-)
lib/std/net.zig+8-12| ... | ... | @@ -22,7 +22,7 @@ pub const Address = extern union { |
| 22 | 22 | //pub const localhost = initIp4(parseIp4("127.0.0.1") catch unreachable, 0); |
| 23 | 23 | |
| 24 | 24 | /// Parse the given IP address string into an Address value. |
| 25 | /// It is recommended to use Address.resolveIp instead, to handle | |
| 25 | /// It is recommended to use `resolveIp` instead, to handle | |
| 26 | 26 | /// IPv6 link-local unix addresses. |
| 27 | 27 | pub fn parseIp(name: []const u8, port: u16) !Address { |
| 28 | 28 | if (parseIp4(name, port)) |ip4| return ip4 else |err| switch (err) { |
| ... | ... | @@ -78,6 +78,7 @@ pub const Address = extern union { |
| 78 | 78 | |
| 79 | 79 | /// Parse a given IPv6 address string into an Address. |
| 80 | 80 | /// Assumes the Scope ID of the address is fully numeric. |
| 81 | /// For non-numeric addresses, see `resolveIp6`. | |
| 81 | 82 | pub fn parseIp6(buf: []const u8, port: u16) !Address { |
| 82 | 83 | var result = Address{ |
| 83 | 84 | .in6 = os.sockaddr_in6{ |
| ... | ... | @@ -185,8 +186,7 @@ pub const Address = extern union { |
| 185 | 186 | } |
| 186 | 187 | |
| 187 | 188 | pub fn resolveIp6(buf: []const u8, port: u16) !Address { |
| 188 | // FIXME: this is a very bad implementation, since it's only a copy | |
| 189 | // of parseIp6 with alphanumerical scope id support | |
| 189 | // TODO: Unify the implementations of resolveIp6 and parseIp6. | |
| 190 | 190 | var result = Address{ |
| 191 | 191 | .in6 = os.sockaddr_in6{ |
| 192 | 192 | .scope_id = 0, |
| ... | ... | @@ -543,17 +543,13 @@ fn if_nametoindex(name: []const u8) !u32 { |
| 543 | 543 | var sockfd = try os.socket(os.AF_UNIX, os.SOCK_DGRAM | os.SOCK_CLOEXEC, 0); |
| 544 | 544 | defer os.close(sockfd); |
| 545 | 545 | |
| 546 | std.mem.copy(u8, &ifr.ifr_ifrn.name, name); | |
| 547 | ifr.ifr_ifrn.name[name.len] = 0; | |
| 546 | std.mem.copy(u8, &ifr.ifrn.name, name); | |
| 547 | ifr.ifrn.name[name.len] = 0; | |
| 548 | 548 | |
| 549 | os.ioctl(sockfd, os.system.SIOCGIFINDEX, @ptrToInt(&ifr)) catch |err| { | |
| 550 | switch (err) { | |
| 551 | error.NoDevice => return error.InterfaceNotFound, | |
| 552 | else => return err, | |
| 553 | } | |
| 554 | }; | |
| 549 | // TODO investigate if this needs to be integrated with evented I/O. | |
| 550 | try os.ioctl_SIOCGIFINDEX(sockfd, &ifr); | |
| 555 | 551 | |
| 556 | return @bitCast(u32, ifr.ifr_ifru.ifru_ivalue); | |
| 552 | return @bitCast(u32, ifr.ifru.ivalue); | |
| 557 | 553 | } |
| 558 | 554 | |
| 559 | 555 | pub const AddressList = struct { |
lib/std/net/test.zig+3-1| ... | ... | @@ -48,6 +48,7 @@ test "parse and render IPv6 addresses" { |
| 48 | 48 | testing.expectError(error.InvalidEnd, net.Address.parseIp6("FF01:0:0:0:0:0:0:FB:", 0)); |
| 49 | 49 | testing.expectError(error.Incomplete, net.Address.parseIp6("FF01:", 0)); |
| 50 | 50 | testing.expectError(error.InvalidIpv4Mapping, net.Address.parseIp6("::123.123.123.123", 0)); |
| 51 | // TODO Make this test pass on other operating systems. | |
| 51 | 52 | if (std.builtin.os.tag == .linux) { |
| 52 | 53 | testing.expectError(error.Incomplete, net.Address.resolveIp6("ff01::fb%", 0)); |
| 53 | 54 | testing.expectError(error.Overflow, net.Address.resolveIp6("ff01::fb%wlp3s0s0s0s0s0s0s0s0", 0)); |
| ... | ... | @@ -56,8 +57,9 @@ test "parse and render IPv6 addresses" { |
| 56 | 57 | } |
| 57 | 58 | |
| 58 | 59 | test "invalid but parseable IPv6 scope ids" { |
| 59 | // Currently, resolveIp6 with alphanumerical scope IDs only works on Linux. | |
| 60 | 60 | if (std.builtin.os.tag != .linux) { |
| 61 | // Currently, resolveIp6 with alphanumerical scope IDs only works on Linux. | |
| 62 | // TODO Make this test pass on other operating systems. | |
| 61 | 63 | return error.SkipZigTest; |
| 62 | 64 | } |
| 63 | 65 |
lib/std/os.zig+37-19| ... | ... | @@ -2390,8 +2390,15 @@ pub fn isatty(handle: fd_t) bool { |
| 2390 | 2390 | return true; |
| 2391 | 2391 | } |
| 2392 | 2392 | if (builtin.os.tag == .linux) { |
| 2393 | var wsz: linux.winsize = undefined; | |
| 2394 | return linux.ioctl(handle, linux.TIOCGWINSZ, @ptrToInt(&wsz)) == 0; | |
| 2393 | while (true) { | |
| 2394 | var wsz: linux.winsize = undefined; | |
| 2395 | const fd = @bitCast(usize, @as(isize, handle)); | |
| 2396 | switch (linux.syscall3(.ioctl, fd, linux.TIOCGWINSZ, @ptrToInt(&wsz))) { | |
| 2397 | 0 => return true, | |
| 2398 | EINTR => continue, | |
| 2399 | else => return false, | |
| 2400 | } | |
| 2401 | } | |
| 2395 | 2402 | } |
| 2396 | 2403 | unreachable; |
| 2397 | 2404 | } |
| ... | ... | @@ -4880,12 +4887,15 @@ pub fn getrusage(who: i32) rusage { |
| 4880 | 4887 | pub const TermiosGetError = error{NotATerminal} || UnexpectedError; |
| 4881 | 4888 | |
| 4882 | 4889 | pub fn tcgetattr(handle: fd_t) TermiosGetError!termios { |
| 4883 | var term: termios = undefined; | |
| 4884 | switch (errno(system.tcgetattr(handle, &term))) { | |
| 4885 | 0 => return term, | |
| 4886 | EBADF => unreachable, | |
| 4887 | ENOTTY => return error.NotATerminal, | |
| 4888 | else => |err| return unexpectedErrno(err), | |
| 4890 | while (true) { | |
| 4891 | var term: termios = undefined; | |
| 4892 | switch (errno(system.tcgetattr(handle, &term))) { | |
| 4893 | 0 => return term, | |
| 4894 | EINTR => continue, | |
| 4895 | EBADF => unreachable, | |
| 4896 | ENOTTY => return error.NotATerminal, | |
| 4897 | else => |err| return unexpectedErrno(err), | |
| 4898 | } | |
| 4889 | 4899 | } |
| 4890 | 4900 | } |
| 4891 | 4901 | |
| ... | ... | @@ -4905,16 +4915,24 @@ pub fn tcsetattr(handle: fd_t, optional_action: TCSA, termios_p: termios) Termio |
| 4905 | 4915 | } |
| 4906 | 4916 | } |
| 4907 | 4917 | |
| 4908 | pub fn ioctl(handle: fd_t, request: i32, arg: var) !void { | |
| 4909 | switch (errno(system.ioctl(handle, request, arg))) { | |
| 4910 | 0 => {}, | |
| 4911 | EINVAL => unreachable, | |
| 4912 | ENOTTY => unreachable, | |
| 4913 | ENXIO => unreachable, | |
| 4914 | EBADF => return error.BadFile, | |
| 4915 | EINTR => return error.CaughtSignal, | |
| 4916 | EIO => return error.FileSystem, | |
| 4917 | ENODEV => return error.NoDevice, | |
| 4918 | else => |err| return unexpectedErrno(err), | |
| 4918 | const IoCtl_SIOCGIFINDEX_Error = error{ | |
| 4919 | FileSystem, | |
| 4920 | InterfaceNotFound, | |
| 4921 | } || UnexpectedError; | |
| 4922 | ||
| 4923 | pub fn ioctl_SIOCGIFINDEX(fd: fd_t, ifr: *ifreq) IoCtl_SIOCGIFINDEX_Error!void { | |
| 4924 | while (true) { | |
| 4925 | switch (errno(system.ioctl(fd, SIOCGIFINDEX, @ptrToInt(ifr)))) { | |
| 4926 | 0 => return, | |
| 4927 | EINVAL => unreachable, // Bad parameters. | |
| 4928 | ENOTTY => unreachable, | |
| 4929 | ENXIO => unreachable, | |
| 4930 | EBADF => unreachable, // Always a race condition. | |
| 4931 | EFAULT => unreachable, // Bad pointer parameter. | |
| 4932 | EINTR => continue, | |
| 4933 | EIO => return error.FileSystem, | |
| 4934 | ENODEV => return error.InterfaceNotFound, | |
| 4935 | else => |err| return unexpectedErrno(err), | |
| 4936 | } | |
| 4919 | 4937 | } |
| 4920 | 4938 | } |
lib/std/os/bits/linux.zig+14-14| ... | ... | @@ -1719,21 +1719,21 @@ pub const ifmap = extern struct { |
| 1719 | 1719 | }; |
| 1720 | 1720 | |
| 1721 | 1721 | pub const ifreq = extern struct { |
| 1722 | ifr_ifrn: extern union { | |
| 1722 | ifrn: extern union { | |
| 1723 | 1723 | name: [IFNAMESIZE]u8, |
| 1724 | 1724 | }, |
| 1725 | ifr_ifru: extern union { | |
| 1726 | ifru_addr: sockaddr, | |
| 1727 | ifru_dstaddr: sockaddr, | |
| 1728 | ifru_broadaddr: sockaddr, | |
| 1729 | ifru_netmask: sockaddr, | |
| 1730 | ifru_hwaddr: sockaddr, | |
| 1731 | ifru_flags: i16, | |
| 1732 | ifru_ivalue: i32, | |
| 1733 | ifru_mtu: i32, | |
| 1734 | ifru_map: ifmap, | |
| 1735 | ifru_slave: [IFNAMESIZE - 1:0]u8, | |
| 1736 | ifru_newname: [IFNAMESIZE - 1:0]u8, | |
| 1737 | ifru_data: ?[*]u8, | |
| 1725 | ifru: extern union { | |
| 1726 | addr: sockaddr, | |
| 1727 | dstaddr: sockaddr, | |
| 1728 | broadaddr: sockaddr, | |
| 1729 | netmask: sockaddr, | |
| 1730 | hwaddr: sockaddr, | |
| 1731 | flags: i16, | |
| 1732 | ivalue: i32, | |
| 1733 | mtu: i32, | |
| 1734 | map: ifmap, | |
| 1735 | slave: [IFNAMESIZE - 1:0]u8, | |
| 1736 | newname: [IFNAMESIZE - 1:0]u8, | |
| 1737 | data: ?[*]u8, | |
| 1738 | 1738 | }, |
| 1739 | 1739 | }; |
lib/std/os/linux.zig+4-4| ... | ... | @@ -1186,15 +1186,15 @@ pub fn getrusage(who: i32, usage: *rusage) usize { |
| 1186 | 1186 | } |
| 1187 | 1187 | |
| 1188 | 1188 | pub fn tcgetattr(fd: fd_t, termios_p: *termios) usize { |
| 1189 | return ioctl(fd, TCGETS, @ptrToInt(termios_p)); | |
| 1189 | return syscall3(.ioctl, @bitCast(usize, @as(isize, fd)), TCGETS, @ptrToInt(termios_p)); | |
| 1190 | 1190 | } |
| 1191 | 1191 | |
| 1192 | 1192 | pub fn tcsetattr(fd: fd_t, optional_action: TCSA, termios_p: *const termios) usize { |
| 1193 | return ioctl(fd, TCSETS + @enumToInt(optional_action), @ptrToInt(termios_p)); | |
| 1193 | return syscall3(.ioctl, @bitCast(usize, @as(isize, fd)), TCSETS + @enumToInt(optional_action), @ptrToInt(termios_p)); | |
| 1194 | 1194 | } |
| 1195 | 1195 | |
| 1196 | pub fn ioctl(fd: fd_t, request: i32, arg: var) usize { | |
| 1197 | return syscall3(.ioctl, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, request)), arg); | |
| 1196 | pub fn ioctl(fd: fd_t, request: u32, arg: usize) usize { | |
| 1197 | return syscall3(.ioctl, @bitCast(usize, @as(isize, fd)), request, arg); | |
| 1198 | 1198 | } |
| 1199 | 1199 | |
| 1200 | 1200 | test "" { |