authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-02 15:28:46-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-02 15:28:46-04:00
log7fd937fef4547a98d7c33ea67eca76e6336f9152
tree9122d4a2eab8b9deef81e089cecee0e7699a08fa
parent0d091dc92374a49c41d406b5bf9a4b508a3d450c

cleanups

* 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,7 +22,7 @@ pub const Address = extern union {
22 //pub const localhost = initIp4(parseIp4("127.0.0.1") catch unreachable, 0);22 //pub const localhost = initIp4(parseIp4("127.0.0.1") catch unreachable, 0);
2323
24 /// Parse the given IP address string into an Address value.24 /// Parse the given IP address string into an Address value.
25 /// It is recommended to use Address.resolveIp instead, to handle25 /// It is recommended to use `resolveIp` instead, to handle
26 /// IPv6 link-local unix addresses.26 /// IPv6 link-local unix addresses.
27 pub fn parseIp(name: []const u8, port: u16) !Address {27 pub fn parseIp(name: []const u8, port: u16) !Address {
28 if (parseIp4(name, port)) |ip4| return ip4 else |err| switch (err) {28 if (parseIp4(name, port)) |ip4| return ip4 else |err| switch (err) {
...@@ -78,6 +78,7 @@ pub const Address = extern union {...@@ -78,6 +78,7 @@ pub const Address = extern union {
7878
79 /// Parse a given IPv6 address string into an Address.79 /// Parse a given IPv6 address string into an Address.
80 /// Assumes the Scope ID of the address is fully numeric.80 /// Assumes the Scope ID of the address is fully numeric.
81 /// For non-numeric addresses, see `resolveIp6`.
81 pub fn parseIp6(buf: []const u8, port: u16) !Address {82 pub fn parseIp6(buf: []const u8, port: u16) !Address {
82 var result = Address{83 var result = Address{
83 .in6 = os.sockaddr_in6{84 .in6 = os.sockaddr_in6{
...@@ -185,8 +186,7 @@ pub const Address = extern union {...@@ -185,8 +186,7 @@ pub const Address = extern union {
185 }186 }
186187
187 pub fn resolveIp6(buf: []const u8, port: u16) !Address {188 pub fn resolveIp6(buf: []const u8, port: u16) !Address {
188 // FIXME: this is a very bad implementation, since it's only a copy189 // TODO: Unify the implementations of resolveIp6 and parseIp6.
189 // of parseIp6 with alphanumerical scope id support
190 var result = Address{190 var result = Address{
191 .in6 = os.sockaddr_in6{191 .in6 = os.sockaddr_in6{
192 .scope_id = 0,192 .scope_id = 0,
...@@ -543,17 +543,13 @@ fn if_nametoindex(name: []const u8) !u32 {...@@ -543,17 +543,13 @@ fn if_nametoindex(name: []const u8) !u32 {
543 var sockfd = try os.socket(os.AF_UNIX, os.SOCK_DGRAM | os.SOCK_CLOEXEC, 0);543 var sockfd = try os.socket(os.AF_UNIX, os.SOCK_DGRAM | os.SOCK_CLOEXEC, 0);
544 defer os.close(sockfd);544 defer os.close(sockfd);
545545
546 std.mem.copy(u8, &ifr.ifr_ifrn.name, name);546 std.mem.copy(u8, &ifr.ifrn.name, name);
547 ifr.ifr_ifrn.name[name.len] = 0;547 ifr.ifrn.name[name.len] = 0;
548548
549 os.ioctl(sockfd, os.system.SIOCGIFINDEX, @ptrToInt(&ifr)) catch |err| {549 // TODO investigate if this needs to be integrated with evented I/O.
550 switch (err) {550 try os.ioctl_SIOCGIFINDEX(sockfd, &ifr);
551 error.NoDevice => return error.InterfaceNotFound,
552 else => return err,
553 }
554 };
555551
556 return @bitCast(u32, ifr.ifr_ifru.ifru_ivalue);552 return @bitCast(u32, ifr.ifru.ivalue);
557}553}
558554
559pub const AddressList = struct {555pub const AddressList = struct {
lib/std/net/test.zig+3-1
...@@ -48,6 +48,7 @@ test "parse and render IPv6 addresses" {...@@ -48,6 +48,7 @@ test "parse and render IPv6 addresses" {
48 testing.expectError(error.InvalidEnd, net.Address.parseIp6("FF01:0:0:0:0:0:0:FB:", 0));48 testing.expectError(error.InvalidEnd, net.Address.parseIp6("FF01:0:0:0:0:0:0:FB:", 0));
49 testing.expectError(error.Incomplete, net.Address.parseIp6("FF01:", 0));49 testing.expectError(error.Incomplete, net.Address.parseIp6("FF01:", 0));
50 testing.expectError(error.InvalidIpv4Mapping, net.Address.parseIp6("::123.123.123.123", 0));50 testing.expectError(error.InvalidIpv4Mapping, net.Address.parseIp6("::123.123.123.123", 0));
51 // TODO Make this test pass on other operating systems.
51 if (std.builtin.os.tag == .linux) {52 if (std.builtin.os.tag == .linux) {
52 testing.expectError(error.Incomplete, net.Address.resolveIp6("ff01::fb%", 0));53 testing.expectError(error.Incomplete, net.Address.resolveIp6("ff01::fb%", 0));
53 testing.expectError(error.Overflow, net.Address.resolveIp6("ff01::fb%wlp3s0s0s0s0s0s0s0s0", 0));54 testing.expectError(error.Overflow, net.Address.resolveIp6("ff01::fb%wlp3s0s0s0s0s0s0s0s0", 0));
...@@ -56,8 +57,9 @@ test "parse and render IPv6 addresses" {...@@ -56,8 +57,9 @@ test "parse and render IPv6 addresses" {
56}57}
5758
58test "invalid but parseable IPv6 scope ids" {59test "invalid but parseable IPv6 scope ids" {
59 // Currently, resolveIp6 with alphanumerical scope IDs only works on Linux.
60 if (std.builtin.os.tag != .linux) {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 return error.SkipZigTest;63 return error.SkipZigTest;
62 }64 }
6365
lib/std/os.zig+37-19
...@@ -2390,8 +2390,15 @@ pub fn isatty(handle: fd_t) bool {...@@ -2390,8 +2390,15 @@ pub fn isatty(handle: fd_t) bool {
2390 return true;2390 return true;
2391 }2391 }
2392 if (builtin.os.tag == .linux) {2392 if (builtin.os.tag == .linux) {
2393 var wsz: linux.winsize = undefined;2393 while (true) {
2394 return linux.ioctl(handle, linux.TIOCGWINSZ, @ptrToInt(&wsz)) == 0;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 unreachable;2403 unreachable;
2397}2404}
...@@ -4880,12 +4887,15 @@ pub fn getrusage(who: i32) rusage {...@@ -4880,12 +4887,15 @@ pub fn getrusage(who: i32) rusage {
4880pub const TermiosGetError = error{NotATerminal} || UnexpectedError;4887pub const TermiosGetError = error{NotATerminal} || UnexpectedError;
48814888
4882pub fn tcgetattr(handle: fd_t) TermiosGetError!termios {4889pub fn tcgetattr(handle: fd_t) TermiosGetError!termios {
4883 var term: termios = undefined;4890 while (true) {
4884 switch (errno(system.tcgetattr(handle, &term))) {4891 var term: termios = undefined;
4885 0 => return term,4892 switch (errno(system.tcgetattr(handle, &term))) {
4886 EBADF => unreachable,4893 0 => return term,
4887 ENOTTY => return error.NotATerminal,4894 EINTR => continue,
4888 else => |err| return unexpectedErrno(err),4895 EBADF => unreachable,
4896 ENOTTY => return error.NotATerminal,
4897 else => |err| return unexpectedErrno(err),
4898 }
4889 }4899 }
4890}4900}
48914901
...@@ -4905,16 +4915,24 @@ pub fn tcsetattr(handle: fd_t, optional_action: TCSA, termios_p: termios) Termio...@@ -4905,16 +4915,24 @@ pub fn tcsetattr(handle: fd_t, optional_action: TCSA, termios_p: termios) Termio
4905 }4915 }
4906}4916}
49074917
4908pub fn ioctl(handle: fd_t, request: i32, arg: var) !void {4918const IoCtl_SIOCGIFINDEX_Error = error{
4909 switch (errno(system.ioctl(handle, request, arg))) {4919 FileSystem,
4910 0 => {},4920 InterfaceNotFound,
4911 EINVAL => unreachable,4921} || UnexpectedError;
4912 ENOTTY => unreachable,4922
4913 ENXIO => unreachable,4923pub fn ioctl_SIOCGIFINDEX(fd: fd_t, ifr: *ifreq) IoCtl_SIOCGIFINDEX_Error!void {
4914 EBADF => return error.BadFile,4924 while (true) {
4915 EINTR => return error.CaughtSignal,4925 switch (errno(system.ioctl(fd, SIOCGIFINDEX, @ptrToInt(ifr)))) {
4916 EIO => return error.FileSystem,4926 0 => return,
4917 ENODEV => return error.NoDevice,4927 EINVAL => unreachable, // Bad parameters.
4918 else => |err| return unexpectedErrno(err),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,21 +1719,21 @@ pub const ifmap = extern struct {
1719};1719};
17201720
1721pub const ifreq = extern struct {1721pub const ifreq = extern struct {
1722 ifr_ifrn: extern union {1722 ifrn: extern union {
1723 name: [IFNAMESIZE]u8,1723 name: [IFNAMESIZE]u8,
1724 },1724 },
1725 ifr_ifru: extern union {1725 ifru: extern union {
1726 ifru_addr: sockaddr,1726 addr: sockaddr,
1727 ifru_dstaddr: sockaddr,1727 dstaddr: sockaddr,
1728 ifru_broadaddr: sockaddr,1728 broadaddr: sockaddr,
1729 ifru_netmask: sockaddr,1729 netmask: sockaddr,
1730 ifru_hwaddr: sockaddr,1730 hwaddr: sockaddr,
1731 ifru_flags: i16,1731 flags: i16,
1732 ifru_ivalue: i32,1732 ivalue: i32,
1733 ifru_mtu: i32,1733 mtu: i32,
1734 ifru_map: ifmap,1734 map: ifmap,
1735 ifru_slave: [IFNAMESIZE - 1:0]u8,1735 slave: [IFNAMESIZE - 1:0]u8,
1736 ifru_newname: [IFNAMESIZE - 1:0]u8,1736 newname: [IFNAMESIZE - 1:0]u8,
1737 ifru_data: ?[*]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,15 +1186,15 @@ pub fn getrusage(who: i32, usage: *rusage) usize {
1186}1186}
11871187
1188pub fn tcgetattr(fd: fd_t, termios_p: *termios) usize {1188pub 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}
11911191
1192pub fn tcsetattr(fd: fd_t, optional_action: TCSA, termios_p: *const termios) usize {1192pub 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}
11951195
1196pub fn ioctl(fd: fd_t, request: i32, arg: var) usize {1196pub fn ioctl(fd: fd_t, request: u32, arg: usize) usize {
1197 return syscall3(.ioctl, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, request)), arg);1197 return syscall3(.ioctl, @bitCast(usize, @as(isize, fd)), request, arg);
1198}1198}
11991199
1200test "" {1200test "" {