| ... | ... | @@ -1,27 +1,18 @@ |
| 1 | 1 | //! POSIX API layer. |
| 2 | 2 | //! |
| 3 | 3 | //! This is more cross platform than using OS-specific APIs, however, it is |
| 4 | | //! lower-level and less portable than other namespaces such as `std.fs` and |
| 4 | //! lower-level and less portable than other namespaces such as `std.Io` and |
| 5 | 5 | //! `std.process`. |
| 6 | 6 | //! |
| 7 | 7 | //! These APIs are generally lowered to libc function calls if and only if libc |
| 8 | 8 | //! is linked. Most operating systems other than Windows, Linux, and WASI |
| 9 | 9 | //! require always linking libc because they use it as the stable syscall ABI. |
| 10 | | //! |
| 11 | | //! Operating systems that are not POSIX-compliant are sometimes supported by |
| 12 | | //! this API layer; sometimes not. Generally, an implementation will be |
| 13 | | //! provided only if such implementation is straightforward on that operating |
| 14 | | //! system. Otherwise, programmers are expected to use OS-specific logic to |
| 15 | | //! deal with the exception. |
| 16 | | |
| 17 | 10 | const builtin = @import("builtin"); |
| 18 | 11 | const native_os = builtin.os.tag; |
| 19 | 12 | |
| 20 | 13 | const std = @import("std.zig"); |
| 21 | 14 | const Io = std.Io; |
| 22 | 15 | const mem = std.mem; |
| 23 | | const fs = std.fs; |
| 24 | | const max_path_bytes = std.fs.max_path_bytes; |
| 25 | 16 | const maxInt = std.math.maxInt; |
| 26 | 17 | const cast = std.math.cast; |
| 27 | 18 | const assert = std.debug.assert; |
| ... | ... | @@ -122,15 +113,14 @@ pub const STDIN_FILENO = system.STDIN_FILENO; |
| 122 | 113 | pub const STDOUT_FILENO = system.STDOUT_FILENO; |
| 123 | 114 | pub const SYS = system.SYS; |
| 124 | 115 | pub const Sigaction = system.Sigaction; |
| 116 | /// Windows has no concept of `stat`. |
| 117 | /// |
| 118 | /// On Linux, the `stat` bits/wrappers are removed due to having to maintain |
| 119 | /// the different varying stat structs per target and libc, leading to runtime |
| 120 | /// errors. Users targeting Linux should add a comptime check and use statx, |
| 121 | /// similar to how `Io.File.stat` does. |
| 125 | 122 | pub const Stat = switch (native_os) { |
| 126 | | // Has no concept of `stat`. |
| 127 | 123 | .windows => void, |
| 128 | | // The `stat` bits/wrappers are removed due to having to maintain the |
| 129 | | // different varying `struct stat`s per target and libc, leading to runtime |
| 130 | | // errors. |
| 131 | | // |
| 132 | | // Users targeting linux should add a comptime check and use `statx`, |
| 133 | | // similar to how `std.fs.File.stat` does. |
| 134 | 124 | .linux => void, |
| 135 | 125 | else => system.Stat, |
| 136 | 126 | }; |
| ... | ... | @@ -645,26 +635,6 @@ fn setSockFlags(sock: socket_t, flags: u32) !void { |
| 645 | 635 | } |
| 646 | 636 | } |
| 647 | 637 | |
| 648 | | pub const EventFdError = error{ |
| 649 | | SystemResources, |
| 650 | | ProcessFdQuotaExceeded, |
| 651 | | SystemFdQuotaExceeded, |
| 652 | | } || UnexpectedError; |
| 653 | | |
| 654 | | pub fn eventfd(initval: u32, flags: u32) EventFdError!i32 { |
| 655 | | const rc = system.eventfd(initval, flags); |
| 656 | | switch (errno(rc)) { |
| 657 | | .SUCCESS => return @intCast(rc), |
| 658 | | else => |err| return unexpectedErrno(err), |
| 659 | | |
| 660 | | .INVAL => unreachable, // invalid parameters |
| 661 | | .MFILE => return error.ProcessFdQuotaExceeded, |
| 662 | | .NFILE => return error.SystemFdQuotaExceeded, |
| 663 | | .NODEV => return error.SystemResources, |
| 664 | | .NOMEM => return error.SystemResources, |
| 665 | | } |
| 666 | | } |
| 667 | | |
| 668 | 638 | pub const GetSockNameError = error{ |
| 669 | 639 | /// Insufficient resources were available in the system to perform the operation. |
| 670 | 640 | SystemResources, |
| ... | ... | @@ -707,40 +677,6 @@ pub fn getpeername(sock: socket_t, addr: *sockaddr, addrlen: *socklen_t) GetSock |
| 707 | 677 | } |
| 708 | 678 | } |
| 709 | 679 | |
| 710 | | pub const ConnectError = std.Io.net.IpAddress.ConnectError || std.Io.net.UnixAddress.ConnectError; |
| 711 | | |
| 712 | | pub fn connect(sock: socket_t, sock_addr: *const sockaddr, len: socklen_t) ConnectError!void { |
| 713 | | if (native_os == .windows) { |
| 714 | | @compileError("use std.Io instead"); |
| 715 | | } |
| 716 | | |
| 717 | | while (true) { |
| 718 | | switch (errno(system.connect(sock, sock_addr, len))) { |
| 719 | | .SUCCESS => return, |
| 720 | | .ACCES => return error.AccessDenied, |
| 721 | | .PERM => return error.PermissionDenied, |
| 722 | | .ADDRNOTAVAIL => return error.AddressUnavailable, |
| 723 | | .AFNOSUPPORT => return error.AddressFamilyUnsupported, |
| 724 | | .AGAIN, .INPROGRESS => return error.WouldBlock, |
| 725 | | .ALREADY => return error.ConnectionPending, |
| 726 | | .BADF => unreachable, // sockfd is not a valid open file descriptor. |
| 727 | | .CONNREFUSED => return error.ConnectionRefused, |
| 728 | | .CONNRESET => return error.ConnectionResetByPeer, |
| 729 | | .FAULT => unreachable, // The socket structure address is outside the user's address space. |
| 730 | | .INTR => continue, |
| 731 | | .ISCONN => @panic("AlreadyConnected"), // The socket is already connected. |
| 732 | | .HOSTUNREACH => return error.NetworkUnreachable, |
| 733 | | .NETUNREACH => return error.NetworkUnreachable, |
| 734 | | .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. |
| 735 | | .PROTOTYPE => unreachable, // The socket type does not support the requested communications protocol. |
| 736 | | .TIMEDOUT => return error.Timeout, |
| 737 | | .NOENT => return error.FileNotFound, // Returned when socket is AF.UNIX and the given path does not exist. |
| 738 | | .CONNABORTED => unreachable, // Tried to reuse socket that previously received error.ConnectionRefused. |
| 739 | | else => |err| return unexpectedErrno(err), |
| 740 | | } |
| 741 | | } |
| 742 | | } |
| 743 | | |
| 744 | 680 | pub const FStatError = std.Io.File.StatError; |
| 745 | 681 | |
| 746 | 682 | /// Return information about a file descriptor. |