From a0b8f38ab54ac451646aa00cd5e91b6c76f22a84 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 05:57:19 +0200 Subject: Merging upstream version 1.72.1+dfsg1. Signed-off-by: Daniel Baumann --- vendor/rustix/src/backend/libc/c.rs | 499 ++++- vendor/rustix/src/backend/libc/conv.rs | 113 +- vendor/rustix/src/backend/libc/event/epoll.rs | 486 +++++ vendor/rustix/src/backend/libc/event/mod.rs | 9 + vendor/rustix/src/backend/libc/event/poll_fd.rs | 137 ++ vendor/rustix/src/backend/libc/event/syscalls.rs | 161 ++ vendor/rustix/src/backend/libc/event/types.rs | 19 + .../src/backend/libc/event/windows_syscalls.rs | 16 + vendor/rustix/src/backend/libc/fs/dir.rs | 13 +- vendor/rustix/src/backend/libc/fs/inotify.rs | 20 +- vendor/rustix/src/backend/libc/fs/makedev.rs | 32 +- vendor/rustix/src/backend/libc/fs/mod.rs | 4 +- vendor/rustix/src/backend/libc/fs/syscalls.rs | 874 ++++++--- vendor/rustix/src/backend/libc/fs/types.rs | 256 +-- vendor/rustix/src/backend/libc/io/epoll.rs | 366 ---- vendor/rustix/src/backend/libc/io/errno.rs | 2 +- vendor/rustix/src/backend/libc/io/io_slice.rs | 87 - vendor/rustix/src/backend/libc/io/mod.rs | 7 - vendor/rustix/src/backend/libc/io/poll_fd.rs | 136 -- vendor/rustix/src/backend/libc/io/syscalls.rs | 433 +--- vendor/rustix/src/backend/libc/io/types.rs | 138 +- .../rustix/src/backend/libc/io/windows_syscalls.rs | 18 +- vendor/rustix/src/backend/libc/io_lifetimes.rs | 82 - .../rustix/src/backend/libc/io_uring/syscalls.rs | 55 +- vendor/rustix/src/backend/libc/mm/syscalls.rs | 46 +- vendor/rustix/src/backend/libc/mm/types.rs | 218 ++- vendor/rustix/src/backend/libc/mod.rs | 146 +- vendor/rustix/src/backend/libc/net/addr.rs | 49 +- vendor/rustix/src/backend/libc/net/ext.rs | 83 +- vendor/rustix/src/backend/libc/net/mod.rs | 3 +- vendor/rustix/src/backend/libc/net/msghdr.rs | 125 ++ .../rustix/src/backend/libc/net/read_sockaddr.rs | 81 +- vendor/rustix/src/backend/libc/net/send_recv.rs | 38 +- vendor/rustix/src/backend/libc/net/syscalls.rs | 199 +- vendor/rustix/src/backend/libc/net/types.rs | 500 ----- .../rustix/src/backend/libc/net/write_sockaddr.rs | 2 +- vendor/rustix/src/backend/libc/offset.rs | 410 ---- vendor/rustix/src/backend/libc/param/auxv.rs | 2 +- vendor/rustix/src/backend/libc/pid/mod.rs | 1 + vendor/rustix/src/backend/libc/pid/syscalls.rs | 14 + vendor/rustix/src/backend/libc/pipe/mod.rs | 2 + vendor/rustix/src/backend/libc/pipe/syscalls.rs | 111 ++ vendor/rustix/src/backend/libc/pipe/types.rs | 93 + vendor/rustix/src/backend/libc/prctl/mod.rs | 1 + vendor/rustix/src/backend/libc/prctl/syscalls.rs | 14 + vendor/rustix/src/backend/libc/process/cpu_set.rs | 5 +- vendor/rustix/src/backend/libc/process/mod.rs | 7 +- vendor/rustix/src/backend/libc/process/syscalls.rs | 322 ++- vendor/rustix/src/backend/libc/process/types.rs | 255 +-- vendor/rustix/src/backend/libc/process/wait.rs | 2 +- vendor/rustix/src/backend/libc/pty/mod.rs | 1 + vendor/rustix/src/backend/libc/pty/syscalls.rs | 86 + vendor/rustix/src/backend/libc/rand/syscalls.rs | 6 +- vendor/rustix/src/backend/libc/rand/types.rs | 10 +- vendor/rustix/src/backend/libc/system/mod.rs | 3 + vendor/rustix/src/backend/libc/system/syscalls.rs | 40 + vendor/rustix/src/backend/libc/system/types.rs | 8 + vendor/rustix/src/backend/libc/termios/mod.rs | 2 - vendor/rustix/src/backend/libc/termios/syscalls.rs | 297 ++- vendor/rustix/src/backend/libc/termios/types.rs | 736 ------- vendor/rustix/src/backend/libc/thread/syscalls.rs | 135 +- vendor/rustix/src/backend/libc/time/syscalls.rs | 73 +- vendor/rustix/src/backend/libc/time/types.rs | 265 +-- vendor/rustix/src/backend/libc/ugid/mod.rs | 1 + vendor/rustix/src/backend/libc/ugid/syscalls.rs | 42 + vendor/rustix/src/backend/libc/winsock_c.rs | 17 +- .../src/backend/linux_raw/arch/inline/mod.rs | 2 +- .../src/backend/linux_raw/arch/inline/x86.rs | 2 +- vendor/rustix/src/backend/linux_raw/arch/mod.rs | 86 +- .../src/backend/linux_raw/arch/outline/aarch64.s | 119 -- .../src/backend/linux_raw/arch/outline/arm.s | 135 -- .../src/backend/linux_raw/arch/outline/mips.s | 2 - .../src/backend/linux_raw/arch/outline/mips64.s | 2 +- .../src/backend/linux_raw/arch/outline/mod.rs | 13 +- .../src/backend/linux_raw/arch/outline/riscv64.s | 116 -- .../src/backend/linux_raw/arch/outline/x86_64.s | 122 -- vendor/rustix/src/backend/linux_raw/c.rs | 194 +- vendor/rustix/src/backend/linux_raw/conv.rs | 379 ++-- vendor/rustix/src/backend/linux_raw/elf.rs | 2 +- vendor/rustix/src/backend/linux_raw/event/epoll.rs | 462 +++++ vendor/rustix/src/backend/linux_raw/event/mod.rs | 4 + .../rustix/src/backend/linux_raw/event/poll_fd.rs | 95 + .../rustix/src/backend/linux_raw/event/syscalls.rs | 131 ++ vendor/rustix/src/backend/linux_raw/event/types.rs | 18 + vendor/rustix/src/backend/linux_raw/fs/dir.rs | 6 +- vendor/rustix/src/backend/linux_raw/fs/inotify.rs | 10 +- vendor/rustix/src/backend/linux_raw/fs/syscalls.rs | 485 +++-- vendor/rustix/src/backend/linux_raw/fs/types.rs | 57 +- vendor/rustix/src/backend/linux_raw/io/epoll.rs | 346 ---- vendor/rustix/src/backend/linux_raw/io/errno.rs | 15 +- vendor/rustix/src/backend/linux_raw/io/io_slice.rs | 98 - vendor/rustix/src/backend/linux_raw/io/mod.rs | 4 - vendor/rustix/src/backend/linux_raw/io/poll_fd.rs | 93 - vendor/rustix/src/backend/linux_raw/io/syscalls.rs | 288 +-- vendor/rustix/src/backend/linux_raw/io/types.rs | 95 +- .../src/backend/linux_raw/io_uring/syscalls.rs | 2 +- vendor/rustix/src/backend/linux_raw/mm/syscalls.rs | 10 +- vendor/rustix/src/backend/linux_raw/mm/types.rs | 18 +- vendor/rustix/src/backend/linux_raw/mod.rs | 67 +- vendor/rustix/src/backend/linux_raw/net/addr.rs | 60 +- vendor/rustix/src/backend/linux_raw/net/mod.rs | 2 +- vendor/rustix/src/backend/linux_raw/net/msghdr.rs | 143 ++ .../src/backend/linux_raw/net/read_sockaddr.rs | 68 +- .../rustix/src/backend/linux_raw/net/send_recv.rs | 6 +- .../rustix/src/backend/linux_raw/net/syscalls.rs | 219 ++- vendor/rustix/src/backend/linux_raw/net/types.rs | 275 --- .../src/backend/linux_raw/net/write_sockaddr.rs | 4 +- vendor/rustix/src/backend/linux_raw/param/auxv.rs | 81 +- .../src/backend/linux_raw/param/libc_auxv.rs | 121 +- .../src/backend/linux_raw/param/mustang_auxv.rs | 4 +- vendor/rustix/src/backend/linux_raw/pid/mod.rs | 1 + .../rustix/src/backend/linux_raw/pid/syscalls.rs | 18 + vendor/rustix/src/backend/linux_raw/pipe/mod.rs | 2 + .../rustix/src/backend/linux_raw/pipe/syscalls.rs | 132 ++ vendor/rustix/src/backend/linux_raw/pipe/types.rs | 72 + vendor/rustix/src/backend/linux_raw/prctl/mod.rs | 1 + .../rustix/src/backend/linux_raw/prctl/syscalls.rs | 22 + .../src/backend/linux_raw/process/cpu_set.rs | 5 +- .../src/backend/linux_raw/process/syscalls.rs | 257 +-- .../rustix/src/backend/linux_raw/process/types.rs | 143 +- vendor/rustix/src/backend/linux_raw/pty/mod.rs | 1 + .../rustix/src/backend/linux_raw/pty/syscalls.rs | 59 + .../rustix/src/backend/linux_raw/rand/syscalls.rs | 2 +- vendor/rustix/src/backend/linux_raw/rand/types.rs | 2 + vendor/rustix/src/backend/linux_raw/reg.rs | 3 +- .../src/backend/linux_raw/runtime/syscalls.rs | 49 +- vendor/rustix/src/backend/linux_raw/runtime/tls.rs | 8 +- vendor/rustix/src/backend/linux_raw/system/mod.rs | 2 + .../src/backend/linux_raw/system/syscalls.rs | 37 + .../rustix/src/backend/linux_raw/system/types.rs | 4 + vendor/rustix/src/backend/linux_raw/termios/mod.rs | 1 - .../src/backend/linux_raw/termios/syscalls.rs | 234 +-- .../rustix/src/backend/linux_raw/termios/types.rs | 495 ----- .../rustix/src/backend/linux_raw/thread/futex.rs | 6 +- .../src/backend/linux_raw/thread/syscalls.rs | 78 +- .../rustix/src/backend/linux_raw/time/syscalls.rs | 100 +- vendor/rustix/src/backend/linux_raw/time/types.rs | 79 +- vendor/rustix/src/backend/linux_raw/ugid/mod.rs | 1 + .../rustix/src/backend/linux_raw/ugid/syscalls.rs | 67 + .../rustix/src/backend/linux_raw/vdso_wrappers.rs | 134 +- vendor/rustix/src/bitcast.rs | 32 + vendor/rustix/src/check_types.rs | 101 + vendor/rustix/src/clockid.rs | 105 + vendor/rustix/src/const_assert.rs | 23 - vendor/rustix/src/cstr.rs | 10 +- vendor/rustix/src/event/eventfd.rs | 20 + vendor/rustix/src/event/kqueue.rs | 431 ++++ vendor/rustix/src/event/mod.rs | 15 + vendor/rustix/src/event/poll.rs | 32 + vendor/rustix/src/event/port.rs | 150 ++ vendor/rustix/src/ffi.rs | 16 + vendor/rustix/src/ffi/mod.rs | 16 - vendor/rustix/src/fs/abs.rs | 214 +- vendor/rustix/src/fs/at.rs | 88 +- vendor/rustix/src/fs/constants.rs | 4 +- vendor/rustix/src/fs/cwd.rs | 21 +- vendor/rustix/src/fs/fcntl.rs | 21 +- vendor/rustix/src/fs/fd.rs | 35 +- vendor/rustix/src/fs/id.rs | 1 + vendor/rustix/src/fs/ioctl.rs | 50 + vendor/rustix/src/fs/makedev.rs | 2 - vendor/rustix/src/fs/mod.rs | 48 +- vendor/rustix/src/fs/raw_dir.rs | 38 +- vendor/rustix/src/fs/seek_from.rs | 48 + vendor/rustix/src/fs/sendfile.rs | 2 +- vendor/rustix/src/fs/statx.rs | 10 +- vendor/rustix/src/fs/xattr.rs | 2 + vendor/rustix/src/io/dup.rs | 7 +- vendor/rustix/src/io/eventfd.rs | 20 - vendor/rustix/src/io/fd/mod.rs | 17 - vendor/rustix/src/io/fd/owned.rs | 252 --- vendor/rustix/src/io/fd/raw.rs | 159 -- vendor/rustix/src/io/ioctl.rs | 83 +- vendor/rustix/src/io/is_read_write.rs | 3 - vendor/rustix/src/io/kqueue.rs | 431 ---- vendor/rustix/src/io/mod.rs | 46 +- vendor/rustix/src/io/pipe.rs | 156 -- vendor/rustix/src/io/poll.rs | 32 - vendor/rustix/src/io/port.rs | 151 -- vendor/rustix/src/io/procfs.rs | 464 ----- vendor/rustix/src/io/read_write.rs | 12 +- vendor/rustix/src/io/seek_from.rs | 48 - vendor/rustix/src/io/stdio.rs | 509 ----- vendor/rustix/src/io_uring.rs | 181 +- vendor/rustix/src/lib.rs | 159 +- vendor/rustix/src/maybe_polyfill/no_std/io/mod.rs | 107 + vendor/rustix/src/maybe_polyfill/no_std/mod.rs | 15 + .../src/maybe_polyfill/no_std/net/ip_addr.rs | 2068 ++++++++++++++++++++ vendor/rustix/src/maybe_polyfill/no_std/net/mod.rs | 5 + .../src/maybe_polyfill/no_std/net/socket_addr.rs | 641 ++++++ .../rustix/src/maybe_polyfill/no_std/os/fd/mod.rs | 19 + .../src/maybe_polyfill/no_std/os/fd/owned.rs | 254 +++ .../rustix/src/maybe_polyfill/no_std/os/fd/raw.rs | 161 ++ vendor/rustix/src/maybe_polyfill/no_std/os/mod.rs | 4 + .../src/maybe_polyfill/no_std/os/windows/io/mod.rs | 5 + .../src/maybe_polyfill/no_std/os/windows/io/raw.rs | 71 + .../maybe_polyfill/no_std/os/windows/io/socket.rs | 199 ++ .../src/maybe_polyfill/no_std/os/windows/mod.rs | 19 + vendor/rustix/src/maybe_polyfill/std/mod.rs | 41 + vendor/rustix/src/mm/mmap.rs | 4 +- vendor/rustix/src/mm/mod.rs | 4 +- vendor/rustix/src/net/addr.rs | 641 ------ vendor/rustix/src/net/ip.rs | 2068 -------------------- vendor/rustix/src/net/mod.rs | 21 +- vendor/rustix/src/net/send_recv.rs | 322 --- vendor/rustix/src/net/send_recv/mod.rs | 326 +++ vendor/rustix/src/net/send_recv/msg.rs | 751 +++++++ vendor/rustix/src/net/socket.rs | 20 +- vendor/rustix/src/net/socket_addr_any.rs | 2 +- vendor/rustix/src/net/socketpair.rs | 5 +- vendor/rustix/src/net/sockopt.rs | 38 +- vendor/rustix/src/net/types.rs | 1299 ++++++++++++ vendor/rustix/src/param/mod.rs | 2 - vendor/rustix/src/path/arg.rs | 18 +- vendor/rustix/src/path/dec_int.rs | 16 +- vendor/rustix/src/path/mod.rs | 1 + vendor/rustix/src/pid.rs | 93 + vendor/rustix/src/pipe.rs | 209 ++ vendor/rustix/src/prctl.rs | 68 + vendor/rustix/src/process/chdir.rs | 52 +- vendor/rustix/src/process/chroot.rs | 4 + vendor/rustix/src/process/id.rs | 178 +- vendor/rustix/src/process/ioctl.rs | 21 + vendor/rustix/src/process/kill.rs | 2 +- vendor/rustix/src/process/membarrier.rs | 20 +- vendor/rustix/src/process/mod.rs | 40 +- vendor/rustix/src/process/pidfd.rs | 2 + vendor/rustix/src/process/pidfd_getfd.rs | 51 + vendor/rustix/src/process/prctl.rs | 185 +- vendor/rustix/src/process/priority.rs | 6 - vendor/rustix/src/process/procctl.rs | 59 +- vendor/rustix/src/process/rlimit.rs | 4 +- vendor/rustix/src/process/sched.rs | 2 +- vendor/rustix/src/process/system.rs | 137 -- vendor/rustix/src/process/umask.rs | 4 +- vendor/rustix/src/process/wait.rs | 26 +- vendor/rustix/src/procfs.rs | 468 +++++ vendor/rustix/src/pty.rs | 170 ++ vendor/rustix/src/rand/getrandom.rs | 2 +- vendor/rustix/src/rand/mod.rs | 4 +- vendor/rustix/src/runtime.rs | 78 +- vendor/rustix/src/signal.rs | 212 ++ vendor/rustix/src/stdio.rs | 511 +++++ vendor/rustix/src/system.rs | 137 ++ vendor/rustix/src/termios/cf.rs | 40 - vendor/rustix/src/termios/constants.rs | 101 - vendor/rustix/src/termios/ioctl.rs | 42 + vendor/rustix/src/termios/mod.rs | 20 +- vendor/rustix/src/termios/tc.rs | 95 +- vendor/rustix/src/termios/tty.rs | 45 +- vendor/rustix/src/termios/types.rs | 1273 ++++++++++++ vendor/rustix/src/thread/clock.rs | 4 +- vendor/rustix/src/thread/id.rs | 3 +- vendor/rustix/src/thread/libcap.rs | 39 +- vendor/rustix/src/thread/mod.rs | 16 +- vendor/rustix/src/thread/prctl.rs | 22 +- vendor/rustix/src/thread/setns.rs | 4 + vendor/rustix/src/time/clock.rs | 4 +- vendor/rustix/src/time/mod.rs | 6 +- vendor/rustix/src/timespec.rs | 108 + vendor/rustix/src/ugid.rs | 101 + vendor/rustix/src/utils.rs | 25 +- vendor/rustix/src/weak.rs | 76 +- 263 files changed, 18392 insertions(+), 14679 deletions(-) create mode 100644 vendor/rustix/src/backend/libc/event/epoll.rs create mode 100644 vendor/rustix/src/backend/libc/event/mod.rs create mode 100644 vendor/rustix/src/backend/libc/event/poll_fd.rs create mode 100644 vendor/rustix/src/backend/libc/event/syscalls.rs create mode 100644 vendor/rustix/src/backend/libc/event/types.rs create mode 100644 vendor/rustix/src/backend/libc/event/windows_syscalls.rs delete mode 100644 vendor/rustix/src/backend/libc/io/epoll.rs delete mode 100644 vendor/rustix/src/backend/libc/io/io_slice.rs delete mode 100644 vendor/rustix/src/backend/libc/io/poll_fd.rs delete mode 100644 vendor/rustix/src/backend/libc/io_lifetimes.rs create mode 100644 vendor/rustix/src/backend/libc/net/msghdr.rs delete mode 100644 vendor/rustix/src/backend/libc/net/types.rs delete mode 100644 vendor/rustix/src/backend/libc/offset.rs create mode 100644 vendor/rustix/src/backend/libc/pid/mod.rs create mode 100644 vendor/rustix/src/backend/libc/pid/syscalls.rs create mode 100644 vendor/rustix/src/backend/libc/pipe/mod.rs create mode 100644 vendor/rustix/src/backend/libc/pipe/syscalls.rs create mode 100644 vendor/rustix/src/backend/libc/pipe/types.rs create mode 100644 vendor/rustix/src/backend/libc/prctl/mod.rs create mode 100644 vendor/rustix/src/backend/libc/prctl/syscalls.rs create mode 100644 vendor/rustix/src/backend/libc/pty/mod.rs create mode 100644 vendor/rustix/src/backend/libc/pty/syscalls.rs create mode 100644 vendor/rustix/src/backend/libc/system/mod.rs create mode 100644 vendor/rustix/src/backend/libc/system/syscalls.rs create mode 100644 vendor/rustix/src/backend/libc/system/types.rs delete mode 100644 vendor/rustix/src/backend/libc/termios/types.rs create mode 100644 vendor/rustix/src/backend/libc/ugid/mod.rs create mode 100644 vendor/rustix/src/backend/libc/ugid/syscalls.rs delete mode 100644 vendor/rustix/src/backend/linux_raw/arch/outline/aarch64.s delete mode 100644 vendor/rustix/src/backend/linux_raw/arch/outline/arm.s delete mode 100644 vendor/rustix/src/backend/linux_raw/arch/outline/riscv64.s delete mode 100644 vendor/rustix/src/backend/linux_raw/arch/outline/x86_64.s create mode 100644 vendor/rustix/src/backend/linux_raw/event/epoll.rs create mode 100644 vendor/rustix/src/backend/linux_raw/event/mod.rs create mode 100644 vendor/rustix/src/backend/linux_raw/event/poll_fd.rs create mode 100644 vendor/rustix/src/backend/linux_raw/event/syscalls.rs create mode 100644 vendor/rustix/src/backend/linux_raw/event/types.rs delete mode 100644 vendor/rustix/src/backend/linux_raw/io/epoll.rs delete mode 100644 vendor/rustix/src/backend/linux_raw/io/io_slice.rs delete mode 100644 vendor/rustix/src/backend/linux_raw/io/poll_fd.rs create mode 100644 vendor/rustix/src/backend/linux_raw/net/msghdr.rs delete mode 100644 vendor/rustix/src/backend/linux_raw/net/types.rs create mode 100644 vendor/rustix/src/backend/linux_raw/pid/mod.rs create mode 100644 vendor/rustix/src/backend/linux_raw/pid/syscalls.rs create mode 100644 vendor/rustix/src/backend/linux_raw/pipe/mod.rs create mode 100644 vendor/rustix/src/backend/linux_raw/pipe/syscalls.rs create mode 100644 vendor/rustix/src/backend/linux_raw/pipe/types.rs create mode 100644 vendor/rustix/src/backend/linux_raw/prctl/mod.rs create mode 100644 vendor/rustix/src/backend/linux_raw/prctl/syscalls.rs create mode 100644 vendor/rustix/src/backend/linux_raw/pty/mod.rs create mode 100644 vendor/rustix/src/backend/linux_raw/pty/syscalls.rs create mode 100644 vendor/rustix/src/backend/linux_raw/system/mod.rs create mode 100644 vendor/rustix/src/backend/linux_raw/system/syscalls.rs create mode 100644 vendor/rustix/src/backend/linux_raw/system/types.rs delete mode 100644 vendor/rustix/src/backend/linux_raw/termios/types.rs create mode 100644 vendor/rustix/src/backend/linux_raw/ugid/mod.rs create mode 100644 vendor/rustix/src/backend/linux_raw/ugid/syscalls.rs create mode 100644 vendor/rustix/src/bitcast.rs create mode 100644 vendor/rustix/src/check_types.rs create mode 100644 vendor/rustix/src/clockid.rs delete mode 100644 vendor/rustix/src/const_assert.rs create mode 100644 vendor/rustix/src/event/eventfd.rs create mode 100644 vendor/rustix/src/event/kqueue.rs create mode 100644 vendor/rustix/src/event/mod.rs create mode 100644 vendor/rustix/src/event/poll.rs create mode 100644 vendor/rustix/src/event/port.rs create mode 100644 vendor/rustix/src/ffi.rs delete mode 100644 vendor/rustix/src/ffi/mod.rs create mode 100644 vendor/rustix/src/fs/id.rs create mode 100644 vendor/rustix/src/fs/ioctl.rs create mode 100644 vendor/rustix/src/fs/seek_from.rs delete mode 100644 vendor/rustix/src/io/eventfd.rs delete mode 100644 vendor/rustix/src/io/fd/mod.rs delete mode 100644 vendor/rustix/src/io/fd/owned.rs delete mode 100644 vendor/rustix/src/io/fd/raw.rs delete mode 100644 vendor/rustix/src/io/kqueue.rs delete mode 100644 vendor/rustix/src/io/pipe.rs delete mode 100644 vendor/rustix/src/io/poll.rs delete mode 100644 vendor/rustix/src/io/port.rs delete mode 100644 vendor/rustix/src/io/procfs.rs delete mode 100644 vendor/rustix/src/io/seek_from.rs delete mode 100644 vendor/rustix/src/io/stdio.rs create mode 100644 vendor/rustix/src/maybe_polyfill/no_std/io/mod.rs create mode 100644 vendor/rustix/src/maybe_polyfill/no_std/mod.rs create mode 100644 vendor/rustix/src/maybe_polyfill/no_std/net/ip_addr.rs create mode 100644 vendor/rustix/src/maybe_polyfill/no_std/net/mod.rs create mode 100644 vendor/rustix/src/maybe_polyfill/no_std/net/socket_addr.rs create mode 100644 vendor/rustix/src/maybe_polyfill/no_std/os/fd/mod.rs create mode 100644 vendor/rustix/src/maybe_polyfill/no_std/os/fd/owned.rs create mode 100644 vendor/rustix/src/maybe_polyfill/no_std/os/fd/raw.rs create mode 100644 vendor/rustix/src/maybe_polyfill/no_std/os/mod.rs create mode 100644 vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/mod.rs create mode 100644 vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/raw.rs create mode 100644 vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/socket.rs create mode 100644 vendor/rustix/src/maybe_polyfill/no_std/os/windows/mod.rs create mode 100644 vendor/rustix/src/maybe_polyfill/std/mod.rs delete mode 100644 vendor/rustix/src/net/addr.rs delete mode 100644 vendor/rustix/src/net/ip.rs delete mode 100644 vendor/rustix/src/net/send_recv.rs create mode 100644 vendor/rustix/src/net/send_recv/mod.rs create mode 100644 vendor/rustix/src/net/send_recv/msg.rs create mode 100644 vendor/rustix/src/net/types.rs create mode 100644 vendor/rustix/src/pid.rs create mode 100644 vendor/rustix/src/pipe.rs create mode 100644 vendor/rustix/src/prctl.rs create mode 100644 vendor/rustix/src/process/ioctl.rs create mode 100644 vendor/rustix/src/process/pidfd_getfd.rs delete mode 100644 vendor/rustix/src/process/system.rs create mode 100644 vendor/rustix/src/procfs.rs create mode 100644 vendor/rustix/src/pty.rs create mode 100644 vendor/rustix/src/signal.rs create mode 100644 vendor/rustix/src/stdio.rs create mode 100644 vendor/rustix/src/system.rs delete mode 100644 vendor/rustix/src/termios/cf.rs delete mode 100644 vendor/rustix/src/termios/constants.rs create mode 100644 vendor/rustix/src/termios/ioctl.rs create mode 100644 vendor/rustix/src/termios/types.rs create mode 100644 vendor/rustix/src/timespec.rs create mode 100644 vendor/rustix/src/ugid.rs (limited to 'vendor/rustix/src') diff --git a/vendor/rustix/src/backend/libc/c.rs b/vendor/rustix/src/backend/libc/c.rs index 35d24d893..90d3c26f3 100644 --- a/vendor/rustix/src/backend/libc/c.rs +++ b/vendor/rustix/src/backend/libc/c.rs @@ -1,9 +1,504 @@ +#![allow(unused_imports)] + +// Import everything from libc, but we'll add some stuff and override some +// things below. pub(crate) use libc::*; /// `PROC_SUPER_MAGIC`—The magic number for the procfs filesystem. -#[cfg(all(any(target_os = "android", target_os = "linux"), target_env = "musl"))] +#[cfg(all(linux_kernel, target_env = "musl"))] pub(crate) const PROC_SUPER_MAGIC: u32 = 0x0000_9fa0; /// `NFS_SUPER_MAGIC`—The magic number for the NFS filesystem. -#[cfg(all(any(target_os = "android", target_os = "linux"), target_env = "musl"))] +#[cfg(all(linux_kernel, target_env = "musl"))] pub(crate) const NFS_SUPER_MAGIC: u32 = 0x0000_6969; + +// Submitted upstream in . +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const IPPROTO_ETHERNET: c_int = linux_raw_sys::net::IPPROTO_ETHERNET as _; + +// TODO: Upstream these. +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_TSN: c_int = linux_raw_sys::if_ether::ETH_P_TSN as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_ERSPAN2: c_int = linux_raw_sys::if_ether::ETH_P_ERSPAN2 as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_ERSPAN: c_int = linux_raw_sys::if_ether::ETH_P_ERSPAN as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_PROFINET: c_int = linux_raw_sys::if_ether::ETH_P_PROFINET as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_REALTEK: c_int = linux_raw_sys::if_ether::ETH_P_REALTEK as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_ETHERCAT: c_int = linux_raw_sys::if_ether::ETH_P_ETHERCAT as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_PREAUTH: c_int = linux_raw_sys::if_ether::ETH_P_PREAUTH as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_LLDP: c_int = linux_raw_sys::if_ether::ETH_P_LLDP as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_MRP: c_int = linux_raw_sys::if_ether::ETH_P_MRP as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_NCSI: c_int = linux_raw_sys::if_ether::ETH_P_NCSI as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_CFM: c_int = linux_raw_sys::if_ether::ETH_P_CFM as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_IBOE: c_int = linux_raw_sys::if_ether::ETH_P_IBOE as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_HSR: c_int = linux_raw_sys::if_ether::ETH_P_HSR as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_NSH: c_int = linux_raw_sys::if_ether::ETH_P_NSH as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_DSA_8021Q: c_int = linux_raw_sys::if_ether::ETH_P_DSA_8021Q as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_DSA_A5PSW: c_int = linux_raw_sys::if_ether::ETH_P_DSA_A5PSW as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_IFE: c_int = linux_raw_sys::if_ether::ETH_P_IFE as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_CAN: c_int = linux_raw_sys::if_ether::ETH_P_CAN as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_CANXL: c_int = linux_raw_sys::if_ether::ETH_P_CANXL as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_XDSA: c_int = linux_raw_sys::if_ether::ETH_P_XDSA as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_MAP: c_int = linux_raw_sys::if_ether::ETH_P_MAP as _; +#[cfg(all(linux_kernel, feature = "net"))] +pub(crate) const ETH_P_MCTP: c_int = linux_raw_sys::if_ether::ETH_P_MCTP as _; + +#[cfg(all( + linux_kernel, + any( + target_arch = "mips", + target_arch = "mips64", + target_arch = "sparc", + target_arch = "sparc64" + ) +))] +pub(crate) const SIGEMT: c_int = linux_raw_sys::general::SIGEMT as _; + +// TODO: Upstream these. +#[cfg(all(linux_kernel, feature = "termios"))] +pub(crate) const IUCLC: tcflag_t = linux_raw_sys::general::IUCLC as _; +#[cfg(all(linux_kernel, feature = "termios"))] +pub(crate) const XCASE: tcflag_t = linux_raw_sys::general::XCASE as _; + +// On PowerPC, the regular `termios` has the `termios2` fields and there is no +// `termios2`. linux-raw-sys has aliases `termios2` to `termios` to cover this +// difference, but we still need to manually import it since `libc` doesn't +// have this. +#[cfg(all( + linux_kernel, + feature = "termios", + any(target_arch = "powerpc", target_arch = "powerpc64") +))] +pub(crate) use { + linux_raw_sys::general::{termios2, CIBAUD}, + linux_raw_sys::ioctl::{TCGETS2, TCSETS2, TCSETSF2, TCSETSW2}, +}; + +// Automatically enable “large file” support (LFS) features. + +#[cfg(target_os = "vxworks")] +pub(super) use libc::_Vx_ticks64_t as _Vx_ticks_t; +#[cfg(target_os = "aix")] +pub(super) use libc::blksize64_t as blksize_t; +#[cfg(linux_kernel)] +pub(super) use libc::fallocate64 as fallocate; +#[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))] +#[cfg(any(linux_like, target_os = "aix"))] +pub(super) use libc::open64 as open; +#[cfg(any(linux_kernel, target_os = "aix", target_os = "l4re"))] +pub(super) use libc::posix_fallocate64 as posix_fallocate; +#[cfg(any(all(linux_like, not(target_os = "android")), target_os = "aix"))] +pub(super) use libc::{blkcnt64_t as blkcnt_t, rlim64_t as rlim_t}; +#[cfg(any(linux_like, target_os = "aix"))] +pub(super) use libc::{ + fstat64 as fstat, fstatat64 as fstatat, fstatfs64 as fstatfs, fstatvfs64 as fstatvfs, + ftruncate64 as ftruncate, getrlimit64 as getrlimit, ino64_t as ino_t, lseek64 as lseek, + mmap64 as mmap, off64_t as off_t, openat64 as openat, posix_fadvise64 as posix_fadvise, + rlimit64 as rlimit, setrlimit64 as setrlimit, statfs64 as statfs, statvfs64 as statvfs, + RLIM64_INFINITY as RLIM_INFINITY, +}; +#[cfg(apple)] +pub(super) use libc::{ + host_info64_t as host_info_t, host_statistics64 as host_statistics, + vm_statistics64_t as vm_statistics_t, +}; +#[cfg(not(all(linux_kernel, any(target_pointer_width = "32", target_arch = "mips64"))))] +#[cfg(any(linux_like, target_os = "aix"))] +pub(super) use libc::{lstat64 as lstat, stat64 as stat}; +#[cfg(any(linux_kernel, target_os = "aix", target_os = "emscripten"))] +pub(super) use libc::{pread64 as pread, pwrite64 as pwrite}; +#[cfg(any(target_os = "aix", target_os = "linux", target_os = "emscripten"))] +pub(super) use libc::{preadv64 as preadv, pwritev64 as pwritev}; + +#[cfg(all(target_os = "linux", target_env = "gnu"))] +pub(super) unsafe fn prlimit( + pid: libc::pid_t, + resource: libc::__rlimit_resource_t, + new_limit: *const libc::rlimit64, + old_limit: *mut libc::rlimit64, +) -> libc::c_int { + // `prlimit64` wasn't supported in glibc until 2.13. + weak_or_syscall! { + fn prlimit64( + pid: libc::pid_t, + resource: libc::__rlimit_resource_t, + new_limit: *const libc::rlimit64, + old_limit: *mut libc::rlimit64 + ) via SYS_prlimit64 -> libc::c_int + } + + prlimit64(pid, resource, new_limit, old_limit) +} + +#[cfg(all(target_os = "linux", target_env = "musl"))] +pub(super) unsafe fn prlimit( + pid: libc::pid_t, + resource: libc::c_int, + new_limit: *const libc::rlimit64, + old_limit: *mut libc::rlimit64, +) -> libc::c_int { + weak_or_syscall! { + fn prlimit64( + pid: libc::pid_t, + resource: libc::c_int, + new_limit: *const libc::rlimit64, + old_limit: *mut libc::rlimit64 + ) via SYS_prlimit64 -> libc::c_int + } + + prlimit64(pid, resource, new_limit, old_limit) +} + +#[cfg(target_os = "android")] +pub(super) unsafe fn prlimit( + pid: libc::pid_t, + resource: libc::c_int, + new_limit: *const libc::rlimit64, + old_limit: *mut libc::rlimit64, +) -> libc::c_int { + weak_or_syscall! { + fn prlimit64( + pid: libc::pid_t, + resource: libc::c_int, + new_limit: *const libc::rlimit64, + old_limit: *mut libc::rlimit64 + ) via SYS_prlimit64 -> libc::c_int + } + + prlimit64(pid, resource, new_limit, old_limit) +} + +// 64-bit offsets on 32-bit platforms are passed in endianness-specific +// lo/hi pairs. See src/backend/linux_raw/conv.rs for details. +#[cfg(all(linux_kernel, target_endian = "little", target_pointer_width = "32"))] +fn lo(x: i64) -> usize { + (x >> 32) as usize +} +#[cfg(all(linux_kernel, target_endian = "little", target_pointer_width = "32"))] +fn hi(x: i64) -> usize { + x as usize +} +#[cfg(all(linux_kernel, target_endian = "big", target_pointer_width = "32"))] +fn lo(x: i64) -> usize { + x as usize +} +#[cfg(all(linux_kernel, target_endian = "big", target_pointer_width = "32"))] +fn hi(x: i64) -> usize { + (x >> 32) as usize +} + +#[cfg(target_os = "android")] +mod readwrite_pv64 { + use super::*; + + pub(in super::super) unsafe fn preadv64( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, + offset: libc::off64_t, + ) -> libc::ssize_t { + // Older Android libc lacks `preadv64`, so use the `weak!` mechanism to + // test for it, and call back to `libc::syscall`. We don't use + // `weak_or_syscall` here because we need to pass the 64-bit offset + // specially. + weak! { + fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, libc::off64_t) -> libc::ssize_t + } + if let Some(fun) = preadv64.get() { + fun(fd, iov, iovcnt, offset) + } else { + #[cfg(target_pointer_width = "32")] + { + syscall! { + fn preadv( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, + offset_hi: usize, + offset_lo: usize + ) via SYS_preadv -> libc::ssize_t + } + preadv(fd, iov, iovcnt, hi(offset), lo(offset)) + } + #[cfg(target_pointer_width = "64")] + { + syscall! { + fn preadv( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, + offset: libc::off_t + ) via SYS_preadv -> libc::ssize_t + } + preadv(fd, iov, iovcnt, offset) + } + } + } + pub(in super::super) unsafe fn pwritev64( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, + offset: libc::off64_t, + ) -> libc::ssize_t { + // See the comments in `preadv64`. + weak! { + fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, libc::off64_t) -> libc::ssize_t + } + if let Some(fun) = pwritev64.get() { + fun(fd, iov, iovcnt, offset) + } else { + #[cfg(target_pointer_width = "32")] + { + syscall! { + fn pwritev( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, + offset_hi: usize, + offset_lo: usize + ) via SYS_pwritev -> libc::ssize_t + } + pwritev(fd, iov, iovcnt, hi(offset), lo(offset)) + } + #[cfg(target_pointer_width = "64")] + { + syscall! { + fn pwritev( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, + offset: libc::off_t + ) via SYS_pwritev -> libc::ssize_t + } + pwritev(fd, iov, iovcnt, offset) + } + } + } +} +#[cfg(target_os = "android")] +pub(super) use readwrite_pv64::{preadv64 as preadv, pwritev64 as pwritev}; + +// macOS added preadv and pwritev in version 11.0 +#[cfg(apple)] +mod readwrite_pv { + weakcall! { + pub(in super::super) fn preadv( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, + offset: libc::off_t + ) -> libc::ssize_t + } + weakcall! { + pub(in super::super) fn pwritev( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, offset: libc::off_t + ) -> libc::ssize_t + } +} +#[cfg(apple)] +pub(super) use readwrite_pv::{preadv, pwritev}; + +// glibc added `preadv64v2` and `pwritev64v2` in version 2.26. +#[cfg(all(target_os = "linux", target_env = "gnu"))] +mod readwrite_pv64v2 { + use super::*; + + pub(in super::super) unsafe fn preadv64v2( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, + offset: libc::off64_t, + flags: libc::c_int, + ) -> libc::ssize_t { + // Older glibc lacks `preadv64v2`, so use the `weak!` mechanism to + // test for it, and call back to `libc::syscall`. We don't use + // `weak_or_syscall` here because we need to pass the 64-bit offset + // specially. + weak! { + fn preadv64v2(libc::c_int, *const libc::iovec, libc::c_int, libc::off64_t, libc::c_int) -> libc::ssize_t + } + if let Some(fun) = preadv64v2.get() { + fun(fd, iov, iovcnt, offset, flags) + } else { + #[cfg(target_pointer_width = "32")] + { + syscall! { + fn preadv2( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, + offset_hi: usize, + offset_lo: usize, + flags: libc::c_int + ) via SYS_preadv2 -> libc::ssize_t + } + preadv2(fd, iov, iovcnt, hi(offset), lo(offset), flags) + } + #[cfg(target_pointer_width = "64")] + { + syscall! { + fn preadv2( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, + offset: libc::off_t, + flags: libc::c_int + ) via SYS_preadv2 -> libc::ssize_t + } + preadv2(fd, iov, iovcnt, offset, flags) + } + } + } + pub(in super::super) unsafe fn pwritev64v2( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, + offset: libc::off64_t, + flags: libc::c_int, + ) -> libc::ssize_t { + // See the comments in `preadv64v2`. + weak! { + fn pwritev64v2(libc::c_int, *const libc::iovec, libc::c_int, libc::off64_t, libc::c_int) -> libc::ssize_t + } + if let Some(fun) = pwritev64v2.get() { + fun(fd, iov, iovcnt, offset, flags) + } else { + #[cfg(target_pointer_width = "32")] + { + syscall! { + fn pwritev2( + fd: libc::c_int, + iov: *const libc::iovec, + iovec: libc::c_int, + offset_hi: usize, + offset_lo: usize, + flags: libc::c_int + ) via SYS_pwritev2 -> libc::ssize_t + } + pwritev2(fd, iov, iovcnt, hi(offset), lo(offset), flags) + } + #[cfg(target_pointer_width = "64")] + { + syscall! { + fn pwritev2( + fd: libc::c_int, + iov:*const libc::iovec, + iovcnt: libc::c_int, + offset: libc::off_t, + flags: libc::c_int + ) via SYS_pwritev2 -> libc::ssize_t + } + pwritev2(fd, iov, iovcnt, offset, flags) + } + } + } +} +#[cfg(all(target_os = "linux", target_env = "gnu"))] +pub(super) use readwrite_pv64v2::{preadv64v2 as preadv2, pwritev64v2 as pwritev2}; + +// On non-glibc, assume we don't have `pwritev2`/`preadv2` in libc and use +// `c::syscall` instead. +#[cfg(any( + target_os = "android", + all(target_os = "linux", not(target_env = "gnu")), +))] +mod readwrite_pv64v2 { + use super::*; + + pub(in super::super) unsafe fn preadv64v2( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, + offset: libc::off64_t, + flags: libc::c_int, + ) -> libc::ssize_t { + #[cfg(target_pointer_width = "32")] + { + syscall! { + fn preadv2( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, + offset_hi: usize, + offset_lo: usize, + flags: libc::c_int + ) via SYS_preadv2 -> libc::ssize_t + } + preadv2(fd, iov, iovcnt, hi(offset), lo(offset), flags) + } + #[cfg(target_pointer_width = "64")] + { + syscall! { + fn preadv2( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, + offset: libc::off_t, + flags: libc::c_int + ) via SYS_preadv2 -> libc::ssize_t + } + preadv2(fd, iov, iovcnt, offset, flags) + } + } + pub(in super::super) unsafe fn pwritev64v2( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, + offset: libc::off64_t, + flags: libc::c_int, + ) -> libc::ssize_t { + #[cfg(target_pointer_width = "32")] + { + syscall! { + fn pwritev2( + fd: libc::c_int, + iov: *const libc::iovec, + iovcnt: libc::c_int, + offset_hi: usize, + offset_lo: usize, + flags: libc::c_int + ) via SYS_pwritev2 -> libc::ssize_t + } + pwritev2(fd, iov, iovcnt, hi(offset), lo(offset), flags) + } + #[cfg(target_pointer_width = "64")] + { + syscall! { + fn pwritev2( + fd: libc::c_int, + iov:*const libc::iovec, + iovcnt: libc::c_int, + offset: libc::off_t, + flags: libc::c_int + ) via SYS_pwritev2 -> libc::ssize_t + } + pwritev2(fd, iov, iovcnt, offset, flags) + } + } +} +#[cfg(any( + target_os = "android", + all(target_os = "linux", not(target_env = "gnu")), +))] +pub(super) use readwrite_pv64v2::{preadv64v2 as preadv2, pwritev64v2 as pwritev2}; diff --git a/vendor/rustix/src/backend/libc/conv.rs b/vendor/rustix/src/backend/libc/conv.rs index b827d0bbc..d6bcc16ee 100644 --- a/vendor/rustix/src/backend/libc/conv.rs +++ b/vendor/rustix/src/backend/libc/conv.rs @@ -7,13 +7,8 @@ use super::c; use super::fd::{AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, LibcFd, OwnedFd, RawFd}; #[cfg(not(windows))] -#[cfg(feature = "fs")] -use super::offset::libc_off_t; -#[cfg(not(windows))] use crate::ffi::CStr; use crate::io; -#[cfg(windows)] -use core::convert::TryInto; #[cfg(not(windows))] #[inline] @@ -46,15 +41,6 @@ pub(super) fn ret(raw: c::c_int) -> io::Result<()> { } } -#[inline] -pub(super) fn syscall_ret(raw: c::c_long) -> io::Result<()> { - if raw == 0 { - Ok(()) - } else { - Err(io::Errno::last_os_error()) - } -} - #[inline] pub(super) fn nonnegative_ret(raw: c::c_int) -> io::Result<()> { if raw >= 0 { @@ -97,35 +83,10 @@ pub(super) fn ret_usize(raw: c::ssize_t) -> io::Result { } } -#[inline] -pub(super) fn syscall_ret_usize(raw: c::c_long) -> io::Result { - if raw == -1 { - Err(io::Errno::last_os_error()) - } else { - debug_assert!(raw >= 0); - Ok(raw as c::ssize_t as usize) - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -pub(super) fn syscall_ret_u32(raw: c::c_long) -> io::Result { - if raw == -1 { - Err(io::Errno::last_os_error()) - } else { - let r32 = raw as u32; - - // Converting `raw` to `u32` should be lossless. - debug_assert_eq!(r32 as c::c_long, raw); - - Ok(r32) - } -} - #[cfg(not(windows))] #[cfg(feature = "fs")] #[inline] -pub(super) fn ret_off_t(raw: libc_off_t) -> io::Result { +pub(super) fn ret_off_t(raw: c::off_t) -> io::Result { if raw == -1 { Err(io::Errno::last_os_error()) } else { @@ -176,22 +137,6 @@ pub(super) fn ret_discarded_char_ptr(raw: *mut c::c_char) -> io::Result<()> { } } -/// Convert a `c_long` returned from `syscall` to an `OwnedFd`, if valid. -/// -/// # Safety -/// -/// The caller must ensure that this is the return value of a `syscall` call -/// which returns an owned file descriptor. -#[cfg(not(windows))] -#[inline] -pub(super) unsafe fn syscall_ret_owned_fd(raw: c::c_long) -> io::Result { - if raw == -1 { - Err(io::Errno::last_os_error()) - } else { - Ok(OwnedFd::from_raw_fd(raw as RawFd)) - } -} - /// Convert the buffer-length argument value of a `send` or `recv` call. #[cfg(not(windows))] #[inline] @@ -222,3 +167,59 @@ pub(super) fn ret_send_recv(len: isize) -> io::Result { pub(super) fn ret_send_recv(len: i32) -> io::Result { ret_usize(len as isize) } + +/// Convert the value to the `msg_iovlen` field of a `msghdr` struct. +#[cfg(all( + not(any(windows, target_os = "wasi")), + any( + target_os = "android", + all(target_os = "linux", not(target_env = "musl")) + ) +))] +#[inline] +pub(super) fn msg_iov_len(len: usize) -> c::size_t { + len +} + +/// Convert the value to the `msg_iovlen` field of a `msghdr` struct. +#[cfg(all( + not(any(windows, target_os = "wasi")), + not(any( + target_os = "android", + all(target_os = "linux", not(target_env = "musl")) + )) +))] +#[inline] +pub(crate) fn msg_iov_len(len: usize) -> c::c_int { + len.try_into().unwrap_or(c::c_int::MAX) +} + +/// Convert the value to a `socklen_t`. +#[cfg(any( + bsd, + solarish, + target_env = "musl", + target_os = "emscripten", + target_os = "haiku", + target_os = "fuchsia" +))] +#[inline] +pub(crate) fn msg_control_len(len: usize) -> c::socklen_t { + len.try_into().unwrap_or(c::socklen_t::MAX) +} + +/// Convert the value to a `size_t`. +#[cfg(not(any( + bsd, + solarish, + target_env = "musl", + target_os = "emscripten", + target_os = "haiku", + target_os = "fuchsia", + windows, + target_os = "wasi" +)))] +#[inline] +pub(crate) fn msg_control_len(len: usize) -> c::size_t { + len +} diff --git a/vendor/rustix/src/backend/libc/event/epoll.rs b/vendor/rustix/src/backend/libc/event/epoll.rs new file mode 100644 index 000000000..c59a38cd4 --- /dev/null +++ b/vendor/rustix/src/backend/libc/event/epoll.rs @@ -0,0 +1,486 @@ +//! epoll support. +//! +//! This is an experiment, and it isn't yet clear whether epoll is the right +//! level of abstraction at which to introduce safety. But it works fairly well +//! in simple examples 🙂. +//! +//! # Examples +//! +//! ```no_run +//! # #[cfg(feature = "net")] +//! # fn main() -> std::io::Result<()> { +//! use rustix::event::epoll; +//! use rustix::fd::AsFd; +//! use rustix::io::{ioctl_fionbio, read, write}; +//! use rustix::net::{ +//! accept, bind_v4, listen, socket, AddressFamily, Ipv4Addr, SocketAddrV4, SocketType, +//! }; +//! use std::collections::HashMap; +//! use std::os::unix::io::AsRawFd; +//! +//! // Create a socket and listen on it. +//! let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, None)?; +//! bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0))?; +//! listen(&listen_sock, 1)?; +//! +//! // Create an epoll object. Using `Owning` here means the epoll object will +//! // take ownership of the file descriptors registered with it. +//! let epoll = epoll::create(epoll::CreateFlags::CLOEXEC)?; +//! +//! // Register the socket with the epoll object. +//! epoll::add( +//! &epoll, +//! &listen_sock, +//! epoll::EventData::new_u64(1), +//! epoll::EventFlags::IN, +//! )?; +//! +//! // Keep track of the sockets we've opened. +//! let mut next_id = epoll::EventData::new_u64(2); +//! let mut sockets = HashMap::new(); +//! +//! // Process events. +//! let mut event_list = epoll::EventVec::with_capacity(4); +//! loop { +//! epoll::wait(&epoll, &mut event_list, -1)?; +//! for event in &event_list { +//! let target = event.data; +//! if target.u64() == 1 { +//! // Accept a new connection, set it to non-blocking, and +//! // register to be notified when it's ready to write to. +//! let conn_sock = accept(&listen_sock)?; +//! ioctl_fionbio(&conn_sock, true)?; +//! epoll::add( +//! &epoll, +//! &conn_sock, +//! next_id, +//! epoll::EventFlags::OUT | epoll::EventFlags::ET, +//! )?; +//! +//! // Keep track of the socket. +//! sockets.insert(next_id, conn_sock); +//! next_id = epoll::EventData::new_u64(next_id.u64() + 1); +//! } else { +//! // Write a message to the stream and then unregister it. +//! let target = sockets.remove(&target).unwrap(); +//! write(&target, b"hello\n")?; +//! let _ = epoll::delete(&epoll, &target)?; +//! } +//! } +//! } +//! # } +//! # #[cfg(not(feature = "net"))] +//! # fn main() {} +//! ``` + +use crate::backend::c; +use crate::backend::conv::{ret, ret_owned_fd, ret_u32}; +use crate::fd::{AsFd, AsRawFd, OwnedFd}; +use crate::io; +use crate::utils::as_mut_ptr; +use alloc::vec::Vec; +use bitflags::bitflags; +use core::ffi::c_void; +use core::hash::{Hash, Hasher}; +use core::ptr::null_mut; +use core::slice; + +bitflags! { + /// `EPOLL_*` for use with [`new`]. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct CreateFlags: u32 { + /// `EPOLL_CLOEXEC` + const CLOEXEC = bitcast!(c::EPOLL_CLOEXEC); + } +} + +bitflags! { + /// `EPOLL*` for use with [`add`]. + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct EventFlags: u32 { + /// `EPOLLIN` + const IN = bitcast!(c::EPOLLIN); + + /// `EPOLLOUT` + const OUT = bitcast!(c::EPOLLOUT); + + /// `EPOLLPRI` + const PRI = bitcast!(c::EPOLLPRI); + + /// `EPOLLERR` + const ERR = bitcast!(c::EPOLLERR); + + /// `EPOLLHUP` + const HUP = bitcast!(c::EPOLLHUP); + + /// `EPOLLRDNORM` + const RDNORM = bitcast!(c::EPOLLRDNORM); + + /// `EPOLLRDBAND` + const RDBAND = bitcast!(c::EPOLLRDBAND); + + /// `EPOLLWRNORM` + const WRNORM = bitcast!(c::EPOLLWRNORM); + + /// `EPOLLWRBAND` + const WRBAND = bitcast!(c::EPOLLWRBAND); + + /// `EPOLLMSG` + const MSG = bitcast!(c::EPOLLMSG); + + /// `EPOLLRDHUP` + const RDHUP = bitcast!(c::EPOLLRDHUP); + + /// `EPOLLET` + const ET = bitcast!(c::EPOLLET); + + /// `EPOLLONESHOT` + const ONESHOT = bitcast!(c::EPOLLONESHOT); + + /// `EPOLLWAKEUP` + const WAKEUP = bitcast!(c::EPOLLWAKEUP); + + /// `EPOLLEXCLUSIVE` + #[cfg(not(target_os = "android"))] + const EXCLUSIVE = bitcast!(c::EPOLLEXCLUSIVE); + } +} + +/// `epoll_create1(flags)`—Creates a new epoll object. +/// +/// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file +/// descriptor from being implicitly passed across `exec` boundaries. +#[inline] +#[doc(alias = "epoll_create1")] +pub fn create(flags: CreateFlags) -> io::Result { + // SAFETY: We're calling `epoll_create1` via FFI and we know how it + // behaves. + unsafe { ret_owned_fd(c::epoll_create1(bitflags_bits!(flags))) } +} + +/// `epoll_ctl(self, EPOLL_CTL_ADD, data, event)`—Adds an element to an +/// epoll object. +/// +/// This registers interest in any of the events set in `events` occurring +/// on the file descriptor associated with `data`. +/// +/// If [`delete`] is not called on the I/O source passed into this function +/// before the I/O source is `close`d, then the `epoll` will act as if the I/O +/// source is still registered with it. This can lead to spurious events being +/// returned from [`wait`]. If a file descriptor is an +/// `Arc`, then `epoll` can be thought to maintain a +/// `Weak` to the file descriptor. +#[doc(alias = "epoll_ctl")] +pub fn add( + epoll: impl AsFd, + source: impl AsFd, + data: EventData, + event_flags: EventFlags, +) -> io::Result<()> { + // SAFETY: We're calling `epoll_ctl` via FFI and we know how it + // behaves. We use our own `Event` struct instead of libc's because + // ours preserves pointer provenance instead of just using a `u64`, + // and we have tests elsehwere for layout equivalence. + unsafe { + let raw_fd = source.as_fd().as_raw_fd(); + ret(c::epoll_ctl( + epoll.as_fd().as_raw_fd(), + c::EPOLL_CTL_ADD, + raw_fd, + as_mut_ptr(&mut Event { + flags: event_flags, + data, + }) + .cast(), + )) + } +} + +/// `epoll_ctl(self, EPOLL_CTL_MOD, target, event)`—Modifies an element in +/// a given epoll object. +/// +/// This sets the events of interest with `target` to `events`. +#[doc(alias = "epoll_ctl")] +pub fn modify( + epoll: impl AsFd, + source: impl AsFd, + data: EventData, + event_flags: EventFlags, +) -> io::Result<()> { + let raw_fd = source.as_fd().as_raw_fd(); + + // SAFETY: We're calling `epoll_ctl` via FFI and we know how it + // behaves. We use our own `Event` struct instead of libc's because + // ours preserves pointer provenance instead of just using a `u64`, + // and we have tests elsehwere for layout equivalence. + unsafe { + ret(c::epoll_ctl( + epoll.as_fd().as_raw_fd(), + c::EPOLL_CTL_MOD, + raw_fd, + as_mut_ptr(&mut Event { + flags: event_flags, + data, + }) + .cast(), + )) + } +} + +/// `epoll_ctl(self, EPOLL_CTL_DEL, target, NULL)`—Removes an element in +/// a given epoll object. +#[doc(alias = "epoll_ctl")] +pub fn delete(epoll: impl AsFd, source: impl AsFd) -> io::Result<()> { + // SAFETY: We're calling `epoll_ctl` via FFI and we know how it + // behaves. + unsafe { + let raw_fd = source.as_fd().as_raw_fd(); + ret(c::epoll_ctl( + epoll.as_fd().as_raw_fd(), + c::EPOLL_CTL_DEL, + raw_fd, + null_mut(), + )) + } +} + +/// `epoll_wait(self, events, timeout)`—Waits for registered events of +/// interest. +/// +/// For each event of interest, an element is written to `events`. On +/// success, this returns the number of written elements. +pub fn wait(epoll: impl AsFd, event_list: &mut EventVec, timeout: c::c_int) -> io::Result<()> { + // SAFETY: We're calling `epoll_wait` via FFI and we know how it + // behaves. + unsafe { + event_list.events.set_len(0); + let nfds = ret_u32(c::epoll_wait( + epoll.as_fd().as_raw_fd(), + event_list.events.as_mut_ptr().cast::(), + event_list.events.capacity().try_into().unwrap_or(i32::MAX), + timeout, + ))?; + event_list.events.set_len(nfds as usize); + } + + Ok(()) +} + +/// An iterator over the `Event`s in an `EventVec`. +pub struct Iter<'a> { + /// Use `Copied` to copy the struct, since `Event` is `packed` on some + /// platforms, and it's common for users to directly destructure it, + /// which would lead to errors about forming references to packed fields. + iter: core::iter::Copied>, +} + +impl<'a> Iterator for Iter<'a> { + type Item = Event; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next() + } +} + +/// A record of an event that occurred. +#[repr(C)] +#[cfg_attr( + any( + all( + target_arch = "x86", + not(target_env = "musl"), + not(target_os = "android"), + ), + target_arch = "x86_64", + ), + repr(packed) +)] +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +pub struct Event { + /// Which specific event(s) occurred. + pub flags: EventFlags, + /// User data. + pub data: EventData, +} + +/// Data assocated with an [`Event`]. This can either be a 64-bit integer value +/// or a pointer which preserves pointer provenance. +#[repr(C)] +#[derive(Copy, Clone)] +pub union EventData { + /// A 64-bit integer value. + as_u64: u64, + + /// A `*mut c_void` which preserves pointer provenance, extended to be + /// 64-bit so that if we read the value as a `u64` union field, we don't + /// get uninitialized memory. + sixty_four_bit_pointer: SixtyFourBitPointer, +} + +impl EventData { + /// Construct a new value containing a `u64`. + #[inline] + pub const fn new_u64(value: u64) -> Self { + Self { as_u64: value } + } + + /// Construct a new value containing a `*mut c_void`. + #[inline] + pub const fn new_ptr(value: *mut c_void) -> Self { + Self { + sixty_four_bit_pointer: SixtyFourBitPointer { + pointer: value, + #[cfg(target_pointer_width = "32")] + _padding: 0, + }, + } + } + + /// Return the value as a `u64`. + /// + /// If the stored value was a pointer, the pointer is zero-extended to + /// a `u64`. + #[inline] + pub fn u64(self) -> u64 { + unsafe { self.as_u64 } + } + + /// Return the value as a `*mut c_void`. + /// + /// If the stored value was a `u64`, the least-significant bits of the + /// `u64` are returned as a pointer value. + #[inline] + pub fn ptr(self) -> *mut c_void { + unsafe { self.sixty_four_bit_pointer.pointer } + } +} + +impl PartialEq for EventData { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.u64() == other.u64() + } +} + +impl Eq for EventData {} + +impl Hash for EventData { + #[inline] + fn hash(&self, state: &mut H) { + self.u64().hash(state) + } +} + +#[repr(C)] +#[derive(Copy, Clone)] +struct SixtyFourBitPointer { + #[cfg(target_endian = "big")] + #[cfg(target_pointer_width = "32")] + _padding: u32, + + pointer: *mut c_void, + + #[cfg(target_endian = "little")] + #[cfg(target_pointer_width = "32")] + _padding: u32, +} + +/// A vector of `Event`s, plus context for interpreting them. +pub struct EventVec { + events: Vec, +} + +impl EventVec { + /// Constructs an `EventVec` from raw pointer, length, and capacity. + /// + /// # Safety + /// + /// This function calls [`Vec::from_raw_parts`] with its arguments. + /// + /// [`Vec::from_raw_parts`]: https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.from_raw_parts + #[inline] + pub unsafe fn from_raw_parts(ptr: *mut Event, len: usize, capacity: usize) -> Self { + Self { + events: Vec::from_raw_parts(ptr, len, capacity), + } + } + + /// Constructs an `EventVec` with memory for `capacity` `Event`s. + #[inline] + pub fn with_capacity(capacity: usize) -> Self { + Self { + events: Vec::with_capacity(capacity), + } + } + + /// Returns the current `Event` capacity of this `EventVec`. + #[inline] + pub fn capacity(&self) -> usize { + self.events.capacity() + } + + /// Reserves enough memory for at least `additional` more `Event`s. + #[inline] + pub fn reserve(&mut self, additional: usize) { + self.events.reserve(additional); + } + + /// Reserves enough memory for exactly `additional` more `Event`s. + #[inline] + pub fn reserve_exact(&mut self, additional: usize) { + self.events.reserve_exact(additional); + } + + /// Clears all the `Events` out of this `EventVec`. + #[inline] + pub fn clear(&mut self) { + self.events.clear(); + } + + /// Shrinks the capacity of this `EventVec` as much as possible. + #[inline] + pub fn shrink_to_fit(&mut self) { + self.events.shrink_to_fit(); + } + + /// Returns an iterator over the `Event`s in this `EventVec`. + #[inline] + pub fn iter(&self) -> Iter<'_> { + Iter { + iter: self.events.iter().copied(), + } + } + + /// Returns the number of `Event`s logically contained in this `EventVec`. + #[inline] + pub fn len(&mut self) -> usize { + self.events.len() + } + + /// Tests whether this `EventVec` is logically empty. + #[inline] + pub fn is_empty(&mut self) -> bool { + self.events.is_empty() + } +} + +impl<'a> IntoIterator for &'a EventVec { + type IntoIter = Iter<'a>; + type Item = Event; + + #[inline] + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +#[test] +fn test_epoll_layouts() { + check_renamed_type!(Event, epoll_event); + check_renamed_type!(Event, epoll_event); + check_renamed_struct_renamed_field!(Event, epoll_event, flags, events); + check_renamed_struct_renamed_field!(Event, epoll_event, data, u64); +} diff --git a/vendor/rustix/src/backend/libc/event/mod.rs b/vendor/rustix/src/backend/libc/event/mod.rs new file mode 100644 index 000000000..6aed4612a --- /dev/null +++ b/vendor/rustix/src/backend/libc/event/mod.rs @@ -0,0 +1,9 @@ +pub(crate) mod poll_fd; +#[cfg(not(windows))] +pub(crate) mod types; + +#[cfg_attr(windows, path = "windows_syscalls.rs")] +pub(crate) mod syscalls; + +#[cfg(linux_kernel)] +pub mod epoll; diff --git a/vendor/rustix/src/backend/libc/event/poll_fd.rs b/vendor/rustix/src/backend/libc/event/poll_fd.rs new file mode 100644 index 000000000..49a6d1126 --- /dev/null +++ b/vendor/rustix/src/backend/libc/event/poll_fd.rs @@ -0,0 +1,137 @@ +use crate::backend::c; +use crate::backend::conv::borrowed_fd; +use crate::backend::fd::{AsFd, AsRawFd, BorrowedFd, LibcFd}; +use bitflags::bitflags; +use core::marker::PhantomData; +#[cfg(windows)] +use { + crate::backend::fd::{AsSocket, RawFd}, + core::fmt, +}; + +bitflags! { + /// `POLL*` flags for use with [`poll`]. + /// + /// [`poll`]: crate::io::poll + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct PollFlags: c::c_short { + /// `POLLIN` + const IN = c::POLLIN; + /// `POLLPRI` + #[cfg(not(target_os = "wasi"))] + const PRI = c::POLLPRI; + /// `POLLOUT` + const OUT = c::POLLOUT; + /// `POLLRDNORM` + const RDNORM = c::POLLRDNORM; + /// `POLLWRNORM` + const WRNORM = c::POLLWRNORM; + /// `POLLRDBAND` + #[cfg(not(target_os = "wasi"))] + const RDBAND = c::POLLRDBAND; + /// `POLLWRBAND` + #[cfg(not(target_os = "wasi"))] + const WRBAND = c::POLLWRBAND; + /// `POLLERR` + const ERR = c::POLLERR; + /// `POLLHUP` + const HUP = c::POLLHUP; + /// `POLLNVAL` + const NVAL = c::POLLNVAL; + /// `POLLRDHUP` + #[cfg(all( + linux_kernel, + not(any(target_arch = "sparc", target_arch = "sparc64"))), + )] + const RDHUP = c::POLLRDHUP; + } +} + +/// `struct pollfd`—File descriptor and flags for use with [`poll`]. +/// +/// [`poll`]: crate::event::poll +#[doc(alias = "pollfd")] +#[derive(Clone)] +#[cfg_attr(not(windows), derive(Debug))] +#[repr(transparent)] +pub struct PollFd<'fd> { + pollfd: c::pollfd, + _phantom: PhantomData>, +} + +#[cfg(windows)] +impl<'fd> fmt::Debug for PollFd<'fd> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_struct("pollfd") + .field("fd", &self.pollfd.fd) + .field("events", &self.pollfd.events) + .field("revents", &self.pollfd.revents) + .finish() + } +} + +impl<'fd> PollFd<'fd> { + /// Constructs a new `PollFd` holding `fd` and `events`. + #[inline] + pub fn new(fd: &'fd Fd, events: PollFlags) -> Self { + Self::from_borrowed_fd(fd.as_fd(), events) + } + + /// Sets the contained file descriptor to `fd`. + #[inline] + pub fn set_fd(&mut self, fd: &'fd Fd) { + self.pollfd.fd = fd.as_fd().as_raw_fd() as LibcFd; + } + + /// Clears the ready events. + #[inline] + pub fn clear_revents(&mut self) { + self.pollfd.revents = 0; + } + + /// Constructs a new `PollFd` holding `fd` and `events`. + /// + /// This is the same as `new`, but can be used to avoid borrowing the + /// `BorrowedFd`, which can be tricky in situations where the `BorrowedFd` + /// is a temporary. + #[inline] + pub fn from_borrowed_fd(fd: BorrowedFd<'fd>, events: PollFlags) -> Self { + Self { + pollfd: c::pollfd { + fd: borrowed_fd(fd), + events: events.bits(), + revents: 0, + }, + _phantom: PhantomData, + } + } + + /// Returns the ready events. + #[inline] + pub fn revents(&self) -> PollFlags { + // Use `unwrap()` here because in theory we know we know all the bits + // the OS might set here, but OS's have added extensions in the past. + PollFlags::from_bits(self.pollfd.revents).unwrap() + } +} + +#[cfg(not(windows))] +impl<'fd> AsFd for PollFd<'fd> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + // SAFETY: Our constructors and `set_fd` require `pollfd.fd` to be + // valid for the `fd lifetime. + unsafe { BorrowedFd::borrow_raw(self.pollfd.fd) } + } +} + +#[cfg(windows)] +impl<'fd> AsSocket for PollFd<'fd> { + #[inline] + fn as_socket(&self) -> BorrowedFd<'_> { + // SAFETY: Our constructors and `set_fd` require `pollfd.fd` to be + // valid for the `fd lifetime. + unsafe { BorrowedFd::borrow_raw(self.pollfd.fd as RawFd) } + } +} diff --git a/vendor/rustix/src/backend/libc/event/syscalls.rs b/vendor/rustix/src/backend/libc/event/syscalls.rs new file mode 100644 index 000000000..11f6af83e --- /dev/null +++ b/vendor/rustix/src/backend/libc/event/syscalls.rs @@ -0,0 +1,161 @@ +//! libc syscalls supporting `rustix::event`. + +use crate::backend::c; +use crate::backend::conv::ret_c_int; +#[cfg(any(apple, netbsdlike, target_os = "dragonfly", target_os = "solaris"))] +use crate::backend::conv::ret_owned_fd; +use crate::event::PollFd; +#[cfg(any(linux_kernel, bsd, solarish))] +use crate::fd::OwnedFd; +use crate::io; +#[cfg(any(bsd, solarish))] +use {crate::backend::conv::borrowed_fd, crate::fd::BorrowedFd, core::mem::MaybeUninit}; +#[cfg(solarish)] +use { + crate::backend::conv::ret, crate::event::port::Event, crate::utils::as_mut_ptr, + core::ptr::null_mut, +}; +#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "illumos"))] +use {crate::backend::conv::ret_owned_fd, crate::event::EventfdFlags}; +#[cfg(bsd)] +use {crate::event::kqueue::Event, crate::utils::as_ptr, core::ptr::null}; + +#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "illumos"))] +pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result { + #[cfg(linux_kernel)] + unsafe { + syscall! { + fn eventfd2( + initval: c::c_uint, + flags: c::c_int + ) via SYS_eventfd2 -> c::c_int + } + ret_owned_fd(eventfd2(initval, bitflags_bits!(flags))) + } + + #[cfg(any(target_os = "freebsd", target_os = "illumos"))] + unsafe { + ret_owned_fd(c::eventfd(initval, bitflags_bits!(flags))) + } +} + +#[cfg(bsd)] +pub(crate) fn kqueue() -> io::Result { + unsafe { ret_owned_fd(c::kqueue()) } +} + +#[cfg(bsd)] +pub(crate) unsafe fn kevent( + kq: BorrowedFd<'_>, + changelist: &[Event], + eventlist: &mut [MaybeUninit], + timeout: Option<&c::timespec>, +) -> io::Result { + ret_c_int(c::kevent( + borrowed_fd(kq), + changelist.as_ptr().cast(), + changelist + .len() + .try_into() + .map_err(|_| io::Errno::OVERFLOW)?, + eventlist.as_mut_ptr().cast(), + eventlist + .len() + .try_into() + .map_err(|_| io::Errno::OVERFLOW)?, + timeout.map_or(null(), as_ptr), + )) +} + +#[inline] +pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result { + let nfds = fds + .len() + .try_into() + .map_err(|_convert_err| io::Errno::INVAL)?; + + ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) }) + .map(|nready| nready as usize) +} + +#[cfg(solarish)] +pub(crate) fn port_create() -> io::Result { + unsafe { ret_owned_fd(c::port_create()) } +} + +#[cfg(solarish)] +pub(crate) unsafe fn port_associate( + port: BorrowedFd<'_>, + source: c::c_int, + object: c::uintptr_t, + events: c::c_int, + user: *mut c::c_void, +) -> io::Result<()> { + ret(c::port_associate( + borrowed_fd(port), + source, + object, + events, + user, + )) +} + +#[cfg(solarish)] +pub(crate) unsafe fn port_dissociate( + port: BorrowedFd<'_>, + source: c::c_int, + object: c::uintptr_t, +) -> io::Result<()> { + ret(c::port_dissociate(borrowed_fd(port), source, object)) +} + +#[cfg(solarish)] +pub(crate) fn port_get( + port: BorrowedFd<'_>, + timeout: Option<&mut c::timespec>, +) -> io::Result { + let mut event = MaybeUninit::::uninit(); + let timeout = timeout.map_or(null_mut(), as_mut_ptr); + + unsafe { + ret(c::port_get(borrowed_fd(port), event.as_mut_ptr(), timeout))?; + } + + // If we're done, initialize the event and return it. + Ok(Event(unsafe { event.assume_init() })) +} + +#[cfg(solarish)] +pub(crate) fn port_getn( + port: BorrowedFd<'_>, + timeout: Option<&mut c::timespec>, + events: &mut Vec, + mut nget: u32, +) -> io::Result<()> { + let timeout = timeout.map_or(null_mut(), as_mut_ptr); + unsafe { + ret(c::port_getn( + borrowed_fd(port), + events.as_mut_ptr().cast(), + events.len().try_into().unwrap(), + &mut nget, + timeout, + ))?; + } + + // Update the vector length. + unsafe { + events.set_len(nget.try_into().unwrap()); + } + + Ok(()) +} + +#[cfg(solarish)] +pub(crate) fn port_send( + port: BorrowedFd<'_>, + events: c::c_int, + userdata: *mut c::c_void, +) -> io::Result<()> { + unsafe { ret(c::port_send(borrowed_fd(port), events, userdata)) } +} diff --git a/vendor/rustix/src/backend/libc/event/types.rs b/vendor/rustix/src/backend/libc/event/types.rs new file mode 100644 index 000000000..632b1be63 --- /dev/null +++ b/vendor/rustix/src/backend/libc/event/types.rs @@ -0,0 +1,19 @@ +#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "illumos"))] +use {crate::backend::c, bitflags::bitflags}; + +#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "illumos"))] +bitflags! { + /// `EFD_*` flags for use with [`eventfd`]. + /// + /// [`eventfd`]: crate::io::eventfd + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct EventfdFlags: u32 { + /// `EFD_CLOEXEC` + const CLOEXEC = bitcast!(c::EFD_CLOEXEC); + /// `EFD_NONBLOCK` + const NONBLOCK = bitcast!(c::EFD_NONBLOCK); + /// `EFD_SEMAPHORE` + const SEMAPHORE = bitcast!(c::EFD_SEMAPHORE); + } +} diff --git a/vendor/rustix/src/backend/libc/event/windows_syscalls.rs b/vendor/rustix/src/backend/libc/event/windows_syscalls.rs new file mode 100644 index 000000000..8ccad4794 --- /dev/null +++ b/vendor/rustix/src/backend/libc/event/windows_syscalls.rs @@ -0,0 +1,16 @@ +//! Windows system calls in the `event` module. + +use crate::backend::c; +use crate::backend::conv::ret_c_int; +use crate::event::PollFd; +use crate::io; + +pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result { + let nfds = fds + .len() + .try_into() + .map_err(|_convert_err| io::Errno::INVAL)?; + + ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) }) + .map(|nready| nready as usize) +} diff --git a/vendor/rustix/src/backend/libc/fs/dir.rs b/vendor/rustix/src/backend/libc/fs/dir.rs index b6eb32580..c8a4d77c9 100644 --- a/vendor/rustix/src/backend/libc/fs/dir.rs +++ b/vendor/rustix/src/backend/libc/fs/dir.rs @@ -1,8 +1,7 @@ -use super::super::c; -use super::super::conv::owned_fd; -use super::super::offset::libc_ino_t; #[cfg(not(any(solarish, target_os = "haiku")))] use super::types::FileType; +use crate::backend::c; +use crate::backend::conv::owned_fd; use crate::fd::{AsFd, BorrowedFd}; use crate::ffi::{CStr, CString}; use crate::fs::{fcntl_getfl, fstat, openat, Mode, OFlags, Stat}; @@ -18,8 +17,8 @@ use crate::fs::{fstatfs, StatFs}; use crate::fs::{fstatvfs, StatVfs}; use crate::io; #[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] +#[cfg(feature = "process")] use crate::process::fchdir; -#[cfg(target_os = "wasi")] use alloc::borrow::ToOwned; #[cfg(not(linux_like))] use c::readdir as libc_readdir; @@ -139,7 +138,9 @@ impl Dir { } /// `fchdir(self)` + #[cfg(feature = "process")] #[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] + #[cfg_attr(doc_cfg, doc(cfg(feature = "process")))] #[inline] pub fn chdir(&self) -> io::Result<()> { fchdir(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.0.as_ptr())) }) @@ -183,10 +184,10 @@ pub struct DirEntry { d_type: u8, #[cfg(not(any(freebsdlike, netbsdlike)))] - d_ino: libc_ino_t, + d_ino: c::ino_t, #[cfg(any(freebsdlike, netbsdlike))] - d_fileno: libc_ino_t, + d_fileno: c::ino_t, name: CString, } diff --git a/vendor/rustix/src/backend/libc/fs/inotify.rs b/vendor/rustix/src/backend/libc/fs/inotify.rs index 8a42e0583..05d4d904f 100644 --- a/vendor/rustix/src/backend/libc/fs/inotify.rs +++ b/vendor/rustix/src/backend/libc/fs/inotify.rs @@ -1,7 +1,7 @@ //! inotify support for working with inotifies -use super::super::c; -use super::super::conv::{borrowed_fd, c_str, ret, ret_c_int, ret_owned_fd}; +use crate::backend::c; +use crate::backend::conv::{borrowed_fd, c_str, ret, ret_c_int, ret_owned_fd}; use crate::fd::{BorrowedFd, OwnedFd}; use crate::io; use bitflags::bitflags; @@ -10,11 +10,13 @@ bitflags! { /// `IN_*` for use with [`inotify_init`]. /// /// [`inotify_init`]: crate::fs::inotify::inotify_init - pub struct CreateFlags: c::c_int { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct CreateFlags: u32 { /// `IN_CLOEXEC` - const CLOEXEC = c::IN_CLOEXEC; + const CLOEXEC = bitcast!(c::IN_CLOEXEC); /// `IN_NONBLOCK` - const NONBLOCK = c::IN_NONBLOCK; + const NONBLOCK = bitcast!(c::IN_NONBLOCK); } } @@ -22,7 +24,8 @@ bitflags! { /// `IN*` for use with [`inotify_add_watch`]. /// /// [`inotify_add_watch`]: crate::fs::inotify::inotify_add_watch - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct WatchFlags: u32 { /// `IN_ACCESS` const ACCESS = c::IN_ACCESS; @@ -78,7 +81,7 @@ bitflags! { #[doc(alias = "inotify_init1")] pub fn inotify_init(flags: CreateFlags) -> io::Result { // SAFETY: `inotify_init1` has no safety preconditions. - unsafe { ret_owned_fd(c::inotify_init1(flags.bits())) } + unsafe { ret_owned_fd(c::inotify_init1(bitflags_bits!(flags))) } } /// `inotify_add_watch(self, path, flags)`—Adds a watch to inotify @@ -113,7 +116,8 @@ pub fn inotify_add_watch( /// by [`inotify_add_watch`] and not previously have been removed. #[doc(alias = "inotify_rm_watch")] pub fn inotify_remove_watch(inot: BorrowedFd<'_>, wd: i32) -> io::Result<()> { - // Android's `inotify_rm_watch` takes u32 despite `inotify_add_watch` is i32. + // Android's `inotify_rm_watch` takes `u32` despite that + // `inotify_add_watch` expects a `i32`. #[cfg(target_os = "android")] let wd = wd as u32; // SAFETY: The fd is valid and closing an arbitrary wd is valid. diff --git a/vendor/rustix/src/backend/libc/fs/makedev.rs b/vendor/rustix/src/backend/libc/fs/makedev.rs index afe942a59..640d5005b 100644 --- a/vendor/rustix/src/backend/libc/fs/makedev.rs +++ b/vendor/rustix/src/backend/libc/fs/makedev.rs @@ -1,9 +1,10 @@ #[cfg(not(all(target_os = "android", target_pointer_width = "32")))] -use super::super::c; +use crate::backend::c; use crate::fs::Dev; #[cfg(not(any( apple, + solarish, target_os = "aix", target_os = "android", target_os = "emscripten", @@ -13,6 +14,13 @@ pub(crate) fn makedev(maj: u32, min: u32) -> Dev { c::makedev(maj, min) } +#[cfg(solarish)] +pub(crate) fn makedev(maj: u32, min: u32) -> Dev { + // SAFETY: Solarish's `makedev` is marked unsafe but it isn't doing + // anything unsafe. + unsafe { c::makedev(maj, min) } +} + #[cfg(all(target_os = "android", not(target_pointer_width = "32")))] #[inline] pub(crate) fn makedev(maj: u32, min: u32) -> Dev { @@ -54,19 +62,24 @@ pub(crate) fn makedev(maj: u32, min: u32) -> Dev { #[cfg(not(any( apple, freebsdlike, - netbsdlike, target_os = "android", target_os = "emscripten", + target_os = "netbsd" )))] #[inline] pub(crate) fn major(dev: Dev) -> u32 { unsafe { c::major(dev) } } -#[cfg(all(target_os = "android", not(target_pointer_width = "32")))] +#[cfg(any( + apple, + freebsdlike, + target_os = "netbsd", + all(target_os = "android", not(target_pointer_width = "32")), +))] #[inline] pub(crate) fn major(dev: Dev) -> u32 { - // Android's `major` oddly has signed return types. + // On some platforms `major` oddly has signed return types. (unsafe { c::major(dev) }) as u32 } @@ -88,19 +101,24 @@ pub(crate) fn major(dev: Dev) -> u32 { #[cfg(not(any( apple, freebsdlike, - netbsdlike, target_os = "android", target_os = "emscripten", + target_os = "netbsd" )))] #[inline] pub(crate) fn minor(dev: Dev) -> u32 { unsafe { c::minor(dev) } } -#[cfg(all(target_os = "android", not(target_pointer_width = "32")))] +#[cfg(any( + apple, + freebsdlike, + target_os = "netbsd", + all(target_os = "android", not(target_pointer_width = "32")) +))] #[inline] pub(crate) fn minor(dev: Dev) -> u32 { - // Android's `minor` oddly has signed return types. + // On some platforms, `minor` oddly has signed return types. (unsafe { c::minor(dev) }) as u32 } diff --git a/vendor/rustix/src/backend/libc/fs/mod.rs b/vendor/rustix/src/backend/libc/fs/mod.rs index 54a48103c..28579c993 100644 --- a/vendor/rustix/src/backend/libc/fs/mod.rs +++ b/vendor/rustix/src/backend/libc/fs/mod.rs @@ -1,8 +1,8 @@ #[cfg(not(target_os = "redox"))] pub(crate) mod dir; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub mod inotify; -#[cfg(not(any(solarish, target_os = "haiku", target_os = "redox", target_os = "wasi")))] +#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] pub(crate) mod makedev; #[cfg(not(windows))] pub(crate) mod syscalls; diff --git a/vendor/rustix/src/backend/libc/fs/syscalls.rs b/vendor/rustix/src/backend/libc/fs/syscalls.rs index 40c160182..bdba777e9 100644 --- a/vendor/rustix/src/backend/libc/fs/syscalls.rs +++ b/vendor/rustix/src/backend/libc/fs/syscalls.rs @@ -1,48 +1,9 @@ //! libc syscalls supporting `rustix::fs`. -use super::super::c; -use super::super::conv::{borrowed_fd, c_str, ret, ret_c_int, ret_off_t, ret_owned_fd, ret_usize}; -#[cfg(any(target_os = "android", target_os = "linux"))] -use super::super::conv::{syscall_ret, syscall_ret_owned_fd, syscall_ret_usize}; -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] -use super::super::offset::libc_fallocate; -#[cfg(not(any( - apple, - netbsdlike, - solarish, - target_os = "dragonfly", - target_os = "haiku", - target_os = "redox", -)))] -use super::super::offset::libc_posix_fadvise; -#[cfg(not(any( - apple, - netbsdlike, - solarish, - target_os = "aix", - target_os = "android", - target_os = "dragonfly", - target_os = "fuchsia", - target_os = "linux", - target_os = "redox", -)))] -use super::super::offset::libc_posix_fallocate; -use super::super::offset::{libc_fstat, libc_fstatat, libc_ftruncate, libc_lseek, libc_off_t}; -#[cfg(not(any( - solarish, - target_os = "haiku", - target_os = "netbsd", - target_os = "redox", - target_os = "wasi", -)))] -use super::super::offset::{libc_fstatfs, libc_statfs}; -#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] -use super::super::offset::{libc_fstatvfs, libc_statvfs}; -#[cfg(all( - any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), - target_env = "gnu", -))] -use super::super::time::types::LibcTimespec; +use crate::backend::c; +use crate::backend::conv::{ + borrowed_fd, c_str, ret, ret_c_int, ret_off_t, ret_owned_fd, ret_usize, +}; use crate::fd::{BorrowedFd, OwnedFd}; use crate::ffi::CStr; #[cfg(apple)] @@ -56,6 +17,8 @@ use crate::ffi::CString; target_os = "redox", )))] use crate::fs::Advice; +#[cfg(not(target_os = "redox"))] +use crate::fs::AtFlags; #[cfg(not(any( netbsdlike, solarish, @@ -66,14 +29,9 @@ use crate::fs::Advice; use crate::fs::FallocateFlags; #[cfg(not(target_os = "wasi"))] use crate::fs::FlockOperation; -#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "freebsd"))] use crate::fs::MemfdFlags; -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))] use crate::fs::SealFlags; #[cfg(not(any( solarish, @@ -83,38 +41,39 @@ use crate::fs::SealFlags; target_os = "wasi", )))] use crate::fs::StatFs; -#[cfg(any(apple, target_os = "android", target_os = "linux"))] -use crate::fs::XattrFlags; -#[cfg(any(target_os = "android", target_os = "linux"))] -use crate::fs::{cwd, RenameFlags, ResolveFlags, Statx, StatxFlags}; -use crate::fs::{Access, Mode, OFlags, Stat, Timestamps}; +use crate::fs::{Access, Mode, OFlags, SeekFrom, Stat, Timestamps}; #[cfg(not(any(apple, target_os = "redox", target_os = "wasi")))] use crate::fs::{Dev, FileType}; #[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] use crate::fs::{StatVfs, StatVfsMountFlags}; -use crate::io::{self, SeekFrom}; +use crate::io; +#[cfg(all( + any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), + target_env = "gnu", +))] +use crate::timespec::LibcTimespec; #[cfg(not(target_os = "wasi"))] -use crate::process::{Gid, Uid}; +use crate::ugid::{Gid, Uid}; #[cfg(not(all( any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), target_env = "gnu", )))] use crate::utils::as_ptr; -use core::convert::TryInto; -#[cfg(any(apple, target_os = "android", target_os = "linux"))] -use core::mem::size_of; +#[cfg(apple)] +use alloc::vec; use core::mem::MaybeUninit; -#[cfg(any(target_os = "android", target_os = "linux"))] -use core::ptr::null; -#[cfg(any(apple, target_os = "android", target_os = "linux"))] -use core::ptr::null_mut; #[cfg(apple)] use { - super::super::conv::nonnegative_ret, + crate::backend::conv::nonnegative_ret, crate::fs::{copyfile_state_t, CloneFlags, CopyfileFlags}, }; -#[cfg(not(target_os = "redox"))] -use {super::super::offset::libc_openat, crate::fs::AtFlags}; +#[cfg(any(apple, linux_kernel))] +use {crate::fs::XattrFlags, core::mem::size_of, core::ptr::null_mut}; +#[cfg(linux_kernel)] +use { + crate::fs::{RenameFlags, ResolveFlags, Statx, StatxFlags, CWD}, + core::ptr::null, +}; #[cfg(all( any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), @@ -127,6 +86,64 @@ weak!(fn __utimensat64(c::c_int, *const c::c_char, *const LibcTimespec, c::c_int ))] weak!(fn __futimens64(c::c_int, *const LibcTimespec) -> c::c_int); +/// Use a direct syscall (via libc) for `open`. +/// +/// This is only currently necessary as a workaround for old glibc; see below. +#[cfg(all(unix, target_env = "gnu"))] +fn open_via_syscall(path: &CStr, oflags: OFlags, mode: Mode) -> io::Result { + // Linux on aarch64 and riscv64 has no `open` syscall so use `openat`. + #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] + { + openat_via_syscall(CWD, path, oflags, mode) + } + + // Use the `open` syscall. + #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))] + unsafe { + syscall! { + fn open( + pathname: *const c::c_char, + oflags: c::c_int, + mode: c::mode_t + ) via SYS_open -> c::c_int + } + + ret_owned_fd(open( + c_str(path), + bitflags_bits!(oflags), + bitflags_bits!(mode), + )) + } +} + +pub(crate) fn open(path: &CStr, oflags: OFlags, mode: Mode) -> io::Result { + // Work around . + // glibc versions before 2.25 don't handle `O_TMPFILE` correctly. + #[cfg(all(unix, target_env = "gnu"))] + if oflags.contains(OFlags::TMPFILE) && crate::backend::if_glibc_is_less_than_2_25() { + return open_via_syscall(path, oflags, mode); + } + + // On these platforms, `mode_t` is `u16` and can't be passed directly to + // a variadic function. + #[cfg(any( + apple, + freebsdlike, + all(target_os = "android", target_pointer_width = "32") + ))] + let mode: c::c_uint = mode.bits().into(); + + // Otherwise, cast to `mode_t` as that's what `open` is documented to take. + #[cfg(not(any( + apple, + freebsdlike, + all(target_os = "android", target_pointer_width = "32") + )))] + let mode: c::mode_t = mode.bits() as _; + + unsafe { ret_owned_fd(c::open(c_str(path), bitflags_bits!(oflags), mode)) } +} + /// Use a direct syscall (via libc) for `openat`. /// /// This is only currently necessary as a workaround for old glibc; see below. @@ -137,18 +154,22 @@ fn openat_via_syscall( oflags: OFlags, mode: Mode, ) -> io::Result { + syscall! { + fn openat( + base_dirfd: c::c_int, + pathname: *const c::c_char, + oflags: c::c_int, + mode: c::mode_t + ) via SYS_openat -> c::c_int + } + unsafe { - let dirfd = borrowed_fd(dirfd); - let path = c_str(path); - let oflags = oflags.bits(); - let mode = c::c_uint::from(mode.bits()); - ret_owned_fd(c::syscall( - c::SYS_openat, - c::c_long::from(dirfd), - path, - c::c_long::from(oflags), - mode as c::c_long, - ) as c::c_int) + ret_owned_fd(openat( + borrowed_fd(dirfd), + c_str(path), + bitflags_bits!(oflags), + bitflags_bits!(mode), + )) } } @@ -165,15 +186,30 @@ pub(crate) fn openat( if oflags.contains(OFlags::TMPFILE) && crate::backend::if_glibc_is_less_than_2_25() { return openat_via_syscall(dirfd, path, oflags, mode); } + + // On these platforms, `mode_t` is `u16` and can't be passed directly to + // a variadic function. + #[cfg(any( + apple, + freebsdlike, + all(target_os = "android", target_pointer_width = "32") + ))] + let mode: c::c_uint = mode.bits().into(); + + // Otherwise, cast to `mode_t` as that's what `open` is documented to take. + #[cfg(not(any( + apple, + freebsdlike, + all(target_os = "android", target_pointer_width = "32") + )))] + let mode: c::mode_t = mode.bits() as _; + unsafe { - // Pass `mode` as a `c_uint` even if `mode_t` is narrower, since - // `libc_openat` is declared as a variadic function and narrower - // arguments are promoted. - ret_owned_fd(libc_openat( + ret_owned_fd(c::openat( borrowed_fd(dirfd), c_str(path), - oflags.bits(), - c::c_uint::from(mode.bits()), + bitflags_bits!(oflags), + mode, )) } } @@ -189,7 +225,7 @@ pub(crate) fn openat( pub(crate) fn statfs(filename: &CStr) -> io::Result { unsafe { let mut result = MaybeUninit::::uninit(); - ret(libc_statfs(c_str(filename), result.as_mut_ptr()))?; + ret(c::statfs(c_str(filename), result.as_mut_ptr()))?; Ok(result.assume_init()) } } @@ -198,15 +234,30 @@ pub(crate) fn statfs(filename: &CStr) -> io::Result { #[inline] pub(crate) fn statvfs(filename: &CStr) -> io::Result { unsafe { - let mut result = MaybeUninit::::uninit(); - ret(libc_statvfs(c_str(filename), result.as_mut_ptr()))?; + let mut result = MaybeUninit::::uninit(); + ret(c::statvfs(c_str(filename), result.as_mut_ptr()))?; Ok(libc_statvfs_to_statvfs(result.assume_init())) } } +#[inline] +pub(crate) fn readlink(path: &CStr, buf: &mut [u8]) -> io::Result { + unsafe { + ret_usize(c::readlink( + c_str(path), + buf.as_mut_ptr().cast::(), + buf.len(), + )) + } +} + #[cfg(not(target_os = "redox"))] #[inline] -pub(crate) fn readlinkat(dirfd: BorrowedFd<'_>, path: &CStr, buf: &mut [u8]) -> io::Result { +pub(crate) fn readlinkat( + dirfd: BorrowedFd<'_>, + path: &CStr, + buf: &mut [MaybeUninit], +) -> io::Result { unsafe { ret_usize(c::readlinkat( borrowed_fd(dirfd), @@ -217,6 +268,10 @@ pub(crate) fn readlinkat(dirfd: BorrowedFd<'_>, path: &CStr, buf: &mut [u8]) -> } } +pub(crate) fn mkdir(path: &CStr, mode: Mode) -> io::Result<()> { + unsafe { ret(c::mkdir(c_str(path), mode.bits() as c::mode_t)) } +} + #[cfg(not(target_os = "redox"))] pub(crate) fn mkdirat(dirfd: BorrowedFd<'_>, path: &CStr, mode: Mode) -> io::Result<()> { unsafe { @@ -228,21 +283,31 @@ pub(crate) fn mkdirat(dirfd: BorrowedFd<'_>, path: &CStr, mode: Mode) -> io::Res } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub(crate) fn getdents_uninit( fd: BorrowedFd<'_>, buf: &mut [MaybeUninit], ) -> io::Result { + syscall! { + fn getdents64( + fd: c::c_int, + dirp: *mut c::c_void, + count: usize + ) via SYS_getdents64 -> c::ssize_t + } unsafe { - syscall_ret_usize(c::syscall( - c::SYS_getdents64, - fd, - buf.as_mut_ptr().cast::(), + ret_usize(getdents64( + borrowed_fd(fd), + buf.as_mut_ptr().cast::(), buf.len(), )) } } +pub(crate) fn link(old_path: &CStr, new_path: &CStr) -> io::Result<()> { + unsafe { ret(c::link(c_str(old_path), c_str(new_path))) } +} + #[cfg(not(target_os = "redox"))] pub(crate) fn linkat( old_dirfd: BorrowedFd<'_>, @@ -251,20 +316,107 @@ pub(crate) fn linkat( new_path: &CStr, flags: AtFlags, ) -> io::Result<()> { + // macOS <= 10.9 lacks `linkat`. + #[cfg(target_os = "macos")] + unsafe { + weak! { + fn linkat( + c::c_int, + *const c::c_char, + c::c_int, + *const c::c_char, + c::c_int + ) -> c::c_int + } + // If we have `linkat`, use it. + if let Some(libc_linkat) = linkat.get() { + return ret(libc_linkat( + borrowed_fd(old_dirfd), + c_str(old_path), + borrowed_fd(new_dirfd), + c_str(new_path), + bitflags_bits!(flags), + )); + } + // Otherwise, see if we can emulate the `AT_FDCWD` case. + if borrowed_fd(old_dirfd) != c::AT_FDCWD || borrowed_fd(new_dirfd) != c::AT_FDCWD { + return Err(io::Errno::NOSYS); + } + if flags.intersects(!AtFlags::SYMLINK_FOLLOW) { + return Err(io::Errno::INVAL); + } + if !flags.is_empty() { + return Err(io::Errno::OPNOTSUPP); + } + ret(c::link(c_str(old_path), c_str(new_path))) + } + + #[cfg(not(target_os = "macos"))] unsafe { ret(c::linkat( borrowed_fd(old_dirfd), c_str(old_path), borrowed_fd(new_dirfd), c_str(new_path), - flags.bits(), + bitflags_bits!(flags), )) } } +pub(crate) fn rmdir(path: &CStr) -> io::Result<()> { + unsafe { ret(c::rmdir(c_str(path))) } +} + +pub(crate) fn unlink(path: &CStr) -> io::Result<()> { + unsafe { ret(c::unlink(c_str(path))) } +} + #[cfg(not(target_os = "redox"))] pub(crate) fn unlinkat(dirfd: BorrowedFd<'_>, path: &CStr, flags: AtFlags) -> io::Result<()> { - unsafe { ret(c::unlinkat(borrowed_fd(dirfd), c_str(path), flags.bits())) } + // macOS <= 10.9 lacks `unlinkat`. + #[cfg(target_os = "macos")] + unsafe { + weak! { + fn unlinkat( + c::c_int, + *const c::c_char, + c::c_int + ) -> c::c_int + } + // If we have `unlinkat`, use it. + if let Some(libc_unlinkat) = unlinkat.get() { + return ret(libc_unlinkat( + borrowed_fd(dirfd), + c_str(path), + bitflags_bits!(flags), + )); + } + // Otherwise, see if we can emulate the `AT_FDCWD` case. + if borrowed_fd(dirfd) != c::AT_FDCWD { + return Err(io::Errno::NOSYS); + } + if flags.intersects(!AtFlags::REMOVEDIR) { + return Err(io::Errno::INVAL); + } + if flags.contains(AtFlags::REMOVEDIR) { + ret(c::rmdir(c_str(path))) + } else { + ret(c::unlink(c_str(path))) + } + } + + #[cfg(not(target_os = "macos"))] + unsafe { + ret(c::unlinkat( + borrowed_fd(dirfd), + c_str(path), + bitflags_bits!(flags), + )) + } +} + +pub(crate) fn rename(old_path: &CStr, new_path: &CStr) -> io::Result<()> { + unsafe { ret(c::rename(c_str(old_path), c_str(new_path))) } } #[cfg(not(target_os = "redox"))] @@ -274,6 +426,34 @@ pub(crate) fn renameat( new_dirfd: BorrowedFd<'_>, new_path: &CStr, ) -> io::Result<()> { + // macOS <= 10.9 lacks `renameat`. + #[cfg(target_os = "macos")] + unsafe { + weak! { + fn renameat( + c::c_int, + *const c::c_char, + c::c_int, + *const c::c_char + ) -> c::c_int + } + // If we have `renameat`, use it. + if let Some(libc_renameat) = renameat.get() { + return ret(libc_renameat( + borrowed_fd(old_dirfd), + c_str(old_path), + borrowed_fd(new_dirfd), + c_str(new_path), + )); + } + // Otherwise, see if we can emulate the `AT_FDCWD` case. + if borrowed_fd(old_dirfd) != c::AT_FDCWD || borrowed_fd(new_dirfd) != c::AT_FDCWD { + return Err(io::Errno::NOSYS); + } + ret(c::rename(c_str(old_path), c_str(new_path))) + } + + #[cfg(not(target_os = "macos"))] unsafe { ret(c::renameat( borrowed_fd(old_dirfd), @@ -292,7 +472,7 @@ pub(crate) fn renameat2( new_path: &CStr, flags: RenameFlags, ) -> io::Result<()> { - // `getrandom` wasn't supported in glibc until 2.28. + // `renameat2` wasn't supported in glibc until 2.28. weak_or_syscall! { fn renameat2( olddirfd: c::c_int, @@ -332,6 +512,10 @@ pub(crate) fn renameat2( renameat(old_dirfd, old_path, new_dirfd, new_path) } +pub(crate) fn symlink(old_path: &CStr, new_path: &CStr) -> io::Result<()> { + unsafe { ret(c::symlink(c_str(old_path), c_str(new_path))) } +} + #[cfg(not(target_os = "redox"))] pub(crate) fn symlinkat( old_path: &CStr, @@ -347,16 +531,64 @@ pub(crate) fn symlinkat( } } +pub(crate) fn stat(path: &CStr) -> io::Result { + // See the comments in `fstat` about using `crate::fs::statx` here. + #[cfg(all(linux_kernel, any(target_pointer_width = "32", target_arch = "mips64")))] + { + match crate::fs::statx( + crate::fs::CWD, + path, + AtFlags::empty(), + StatxFlags::BASIC_STATS, + ) { + Ok(x) => statx_to_stat(x), + Err(io::Errno::NOSYS) => statat_old(crate::fs::CWD, path, AtFlags::empty()), + Err(err) => Err(err), + } + } + + // Main version: libc is y2038 safe. Or, the platform is not y2038 safe and + // there's nothing practical we can do. + #[cfg(not(all(linux_kernel, any(target_pointer_width = "32", target_arch = "mips64"))))] + unsafe { + let mut stat = MaybeUninit::::uninit(); + ret(c::stat(c_str(path), stat.as_mut_ptr()))?; + Ok(stat.assume_init()) + } +} + +pub(crate) fn lstat(path: &CStr) -> io::Result { + // See the comments in `fstat` about using `crate::fs::statx` here. + #[cfg(all(linux_kernel, any(target_pointer_width = "32", target_arch = "mips64")))] + { + match crate::fs::statx( + crate::fs::CWD, + path, + AtFlags::SYMLINK_NOFOLLOW, + StatxFlags::BASIC_STATS, + ) { + Ok(x) => statx_to_stat(x), + Err(io::Errno::NOSYS) => statat_old(crate::fs::CWD, path, AtFlags::empty()), + Err(err) => Err(err), + } + } + + // Main version: libc is y2038 safe. Or, the platform is not y2038 safe and + // there's nothing practical we can do. + #[cfg(not(all(linux_kernel, any(target_pointer_width = "32", target_arch = "mips64"))))] + unsafe { + let mut stat = MaybeUninit::::uninit(); + ret(c::lstat(c_str(path), stat.as_mut_ptr()))?; + Ok(stat.assume_init()) + } +} + #[cfg(not(target_os = "redox"))] pub(crate) fn statat(dirfd: BorrowedFd<'_>, path: &CStr, flags: AtFlags) -> io::Result { - // 32-bit and mips64 Linux: `struct stat64` is not y2038 compatible; use - // `statx`. - #[cfg(all( - any(target_os = "android", target_os = "linux"), - any(target_pointer_width = "32", target_arch = "mips64"), - ))] + // See the comments in `fstat` about using `crate::fs::statx` here. + #[cfg(all(linux_kernel, any(target_pointer_width = "32", target_arch = "mips64")))] { - match statx(dirfd, path, flags, StatxFlags::BASIC_STATS) { + match crate::fs::statx(dirfd, path, flags, StatxFlags::BASIC_STATS) { Ok(x) => statx_to_stat(x), Err(io::Errno::NOSYS) => statat_old(dirfd, path, flags), Err(err) => Err(err), @@ -365,39 +597,38 @@ pub(crate) fn statat(dirfd: BorrowedFd<'_>, path: &CStr, flags: AtFlags) -> io:: // Main version: libc is y2038 safe. Or, the platform is not y2038 safe and // there's nothing practical we can do. - #[cfg(not(all( - any(target_os = "android", target_os = "linux"), - any(target_pointer_width = "32", target_arch = "mips64"), - )))] + #[cfg(not(all(linux_kernel, any(target_pointer_width = "32", target_arch = "mips64"))))] unsafe { let mut stat = MaybeUninit::::uninit(); - ret(libc_fstatat( + ret(c::fstatat( borrowed_fd(dirfd), c_str(path), stat.as_mut_ptr(), - flags.bits(), + bitflags_bits!(flags), ))?; Ok(stat.assume_init()) } } -#[cfg(all( - any(target_os = "android", target_os = "linux"), - any(target_pointer_width = "32", target_arch = "mips64"), -))] +#[cfg(all(linux_kernel, any(target_pointer_width = "32", target_arch = "mips64")))] fn statat_old(dirfd: BorrowedFd<'_>, path: &CStr, flags: AtFlags) -> io::Result { unsafe { let mut result = MaybeUninit::::uninit(); - ret(libc_fstatat( + ret(c::fstatat( borrowed_fd(dirfd), c_str(path), result.as_mut_ptr(), - flags.bits(), + bitflags_bits!(flags), ))?; stat64_to_stat(result.assume_init()) } } +#[cfg(not(target_os = "emscripten"))] +pub(crate) fn access(path: &CStr, access: Access) -> io::Result<()> { + unsafe { ret(c::access(c_str(path), access.bits())) } +} + #[cfg(not(any(target_os = "emscripten", target_os = "redox")))] pub(crate) fn accessat( dirfd: BorrowedFd<'_>, @@ -405,16 +636,55 @@ pub(crate) fn accessat( access: Access, flags: AtFlags, ) -> io::Result<()> { + // macOS <= 10.9 lacks `faccessat`. + #[cfg(target_os = "macos")] + unsafe { + weak! { + fn faccessat( + c::c_int, + *const c::c_char, + c::c_int, + c::c_int + ) -> c::c_int + } + // If we have `faccessat`, use it. + if let Some(libc_faccessat) = faccessat.get() { + return ret(libc_faccessat( + borrowed_fd(dirfd), + c_str(path), + bitflags_bits!(access), + bitflags_bits!(flags), + )); + } + // Otherwise, see if we can emulate the `AT_FDCWD` case. + if borrowed_fd(dirfd) != c::AT_FDCWD { + return Err(io::Errno::NOSYS); + } + if flags.intersects(!(AtFlags::EACCESS | AtFlags::SYMLINK_NOFOLLOW)) { + return Err(io::Errno::INVAL); + } + if !flags.is_empty() { + return Err(io::Errno::OPNOTSUPP); + } + ret(c::access(c_str(path), bitflags_bits!(access))) + } + + #[cfg(not(target_os = "macos"))] unsafe { ret(c::faccessat( borrowed_fd(dirfd), c_str(path), - access.bits(), - flags.bits(), + bitflags_bits!(access), + bitflags_bits!(flags), )) } } +#[cfg(target_os = "emscripten")] +pub(crate) fn access(_path: &CStr, _access: Access) -> io::Result<()> { + Ok(()) +} + #[cfg(target_os = "emscripten")] pub(crate) fn accessat( _dirfd: BorrowedFd<'_>, @@ -449,7 +719,7 @@ pub(crate) fn utimensat( borrowed_fd(dirfd), c_str(path), libc_times.as_ptr(), - flags.bits(), + bitflags_bits!(flags), )) } else { utimensat_old(dirfd, path, times, flags) @@ -473,7 +743,7 @@ pub(crate) fn utimensat( borrowed_fd(dirfd), c_str(path), as_ptr(times).cast(), - flags.bits(), + bitflags_bits!(flags), )) } @@ -509,7 +779,7 @@ pub(crate) fn utimensat( borrowed_fd(dirfd), c_str(path), as_ptr(times).cast(), - flags.bits(), + bitflags_bits!(flags), )); } @@ -625,16 +895,16 @@ unsafe fn utimensat_old( borrowed_fd(dirfd), c_str(path), old_times.as_ptr(), - flags.bits(), + bitflags_bits!(flags), )) } -#[cfg(not(any( - target_os = "android", - target_os = "linux", - target_os = "redox", - target_os = "wasi", -)))] +#[cfg(not(target_os = "wasi"))] +pub(crate) fn chmod(path: &CStr, mode: Mode) -> io::Result<()> { + unsafe { ret(c::chmod(c_str(path), mode.bits() as c::mode_t)) } +} + +#[cfg(not(any(linux_kernel, target_os = "redox", target_os = "wasi")))] pub(crate) fn chmodat( dirfd: BorrowedFd<'_>, path: &CStr, @@ -646,12 +916,12 @@ pub(crate) fn chmodat( borrowed_fd(dirfd), c_str(path), mode.bits() as c::mode_t, - flags.bits(), + bitflags_bits!(flags), )) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub(crate) fn chmodat( dirfd: BorrowedFd<'_>, path: &CStr, @@ -664,6 +934,13 @@ pub(crate) fn chmodat( // implementations, such as musl, add extra logic to `fchmod` to emulate // support for `AT_SYMLINK_NOFOLLOW`, which uses `/proc` outside our // control. + syscall! { + fn fchmodat( + base_dirfd: c::c_int, + pathname: *const c::c_char, + mode: c::mode_t + ) via SYS_fchmodat -> c::c_int + } if flags == AtFlags::SYMLINK_NOFOLLOW { return Err(io::Errno::OPNOTSUPP); } @@ -671,14 +948,10 @@ pub(crate) fn chmodat( return Err(io::Errno::INVAL); } unsafe { - // Pass `mode` as a `c_uint` even if `mode_t` is narrower, since - // `libc_openat` is declared as a variadic function and narrower - // arguments are promoted. - syscall_ret(c::syscall( - c::SYS_fchmodat, + ret(fchmodat( borrowed_fd(dirfd), c_str(path), - c::c_uint::from(mode.bits()), + mode.bits() as c::mode_t, )) } } @@ -699,7 +972,14 @@ pub(crate) fn fclonefileat( ) via SYS_fclonefileat -> c::c_int } - unsafe { ret(fclonefileat(srcfd, dst_dirfd, c_str(dst), flags.bits())) } + unsafe { + ret(fclonefileat( + srcfd, + dst_dirfd, + c_str(dst), + bitflags_bits!(flags), + )) + } } #[cfg(not(any(target_os = "redox", target_os = "wasi")))] @@ -711,13 +991,13 @@ pub(crate) fn chownat( flags: AtFlags, ) -> io::Result<()> { unsafe { - let (ow, gr) = crate::process::translate_fchown_args(owner, group); + let (ow, gr) = crate::ugid::translate_fchown_args(owner, group); ret(c::fchownat( borrowed_fd(dirfd), c_str(path), ow, gr, - flags.bits(), + bitflags_bits!(flags), )) } } @@ -740,7 +1020,7 @@ pub(crate) fn mknodat( } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub(crate) fn copy_file_range( fd_in: BorrowedFd<'_>, off_in: Option<&mut u64>, @@ -748,26 +1028,36 @@ pub(crate) fn copy_file_range( off_out: Option<&mut u64>, len: usize, ) -> io::Result { + syscall! { + fn copy_file_range( + fd_in: c::c_int, + off_in: *mut c::loff_t, + fd_out: c::c_int, + off_out: *mut c::loff_t, + len: usize, + flags: c::c_uint + ) via SYS_copy_file_range -> c::ssize_t + } + assert_eq!(size_of::(), size_of::()); let mut off_in_val: c::loff_t = 0; let mut off_out_val: c::loff_t = 0; // Silently cast; we'll get `EINVAL` if the value is negative. let off_in_ptr = if let Some(off_in) = &off_in { - off_in_val = (**off_in) as i64; + off_in_val = **off_in as i64; &mut off_in_val } else { null_mut() }; let off_out_ptr = if let Some(off_out) = &off_out { - off_out_val = (**off_out) as i64; + off_out_val = **off_out as i64; &mut off_out_val } else { null_mut() }; let copied = unsafe { - syscall_ret_usize(c::syscall( - c::SYS_copy_file_range, + ret_usize(copy_file_range( borrowed_fd(fd_in), off_in_ptr, borrowed_fd(fd_out), @@ -813,7 +1103,7 @@ pub(crate) fn fadvise(fd: BorrowedFd<'_>, offset: u64, len: u64, advice: Advice) len }; - let err = unsafe { libc_posix_fadvise(borrowed_fd(fd), offset, len, advice as c::c_int) }; + let err = unsafe { c::posix_fadvise(borrowed_fd(fd), offset, len, advice as c::c_int) }; // `posix_fadvise` returns its error status rather than using `errno`. if err == 0 { @@ -824,32 +1114,21 @@ pub(crate) fn fadvise(fd: BorrowedFd<'_>, offset: u64, len: u64, advice: Advice) } pub(crate) fn fcntl_getfl(fd: BorrowedFd<'_>) -> io::Result { - unsafe { ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GETFL)).map(OFlags::from_bits_truncate) } + let flags = unsafe { ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GETFL))? }; + Ok(OFlags::from_bits_retain(bitcast!(flags))) } pub(crate) fn fcntl_setfl(fd: BorrowedFd<'_>, flags: OFlags) -> io::Result<()> { unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_SETFL, flags.bits())) } } -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))] pub(crate) fn fcntl_get_seals(fd: BorrowedFd<'_>) -> io::Result { - unsafe { - ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GET_SEALS)) - .map(|flags| SealFlags::from_bits_unchecked(flags)) - } + let flags = unsafe { ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GET_SEALS))? }; + Ok(SealFlags::from_bits_retain(bitcast!(flags))) } -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))] pub(crate) fn fcntl_add_seals(fd: BorrowedFd<'_>, seals: SealFlags) -> io::Result<()> { unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_ADD_SEALS, seals.bits())) } } @@ -889,7 +1168,7 @@ pub(crate) fn fcntl_lock(fd: BorrowedFd<'_>, operation: FlockOperation) -> io::R } pub(crate) fn seek(fd: BorrowedFd<'_>, pos: SeekFrom) -> io::Result { - let (whence, offset): (c::c_int, libc_off_t) = match pos { + let (whence, offset): (c::c_int, c::off_t) = match pos { SeekFrom::Start(pos) => { let pos: u64 = pos; // Silently cast; we'll get `EINVAL` if the value is negative. @@ -902,51 +1181,58 @@ pub(crate) fn seek(fd: BorrowedFd<'_>, pos: SeekFrom) -> io::Result { #[cfg(any(freebsdlike, target_os = "linux", target_os = "solaris"))] SeekFrom::Hole(offset) => (c::SEEK_HOLE, offset), }; - let offset = unsafe { ret_off_t(libc_lseek(borrowed_fd(fd), offset, whence))? }; + let offset = unsafe { ret_off_t(c::lseek(borrowed_fd(fd), offset, whence))? }; Ok(offset as u64) } pub(crate) fn tell(fd: BorrowedFd<'_>) -> io::Result { - let offset = unsafe { ret_off_t(libc_lseek(borrowed_fd(fd), 0, c::SEEK_CUR))? }; + let offset = unsafe { ret_off_t(c::lseek(borrowed_fd(fd), 0, c::SEEK_CUR))? }; Ok(offset as u64) } -#[cfg(not(any(target_os = "android", target_os = "linux", target_os = "wasi")))] +#[cfg(not(any(linux_kernel, target_os = "wasi")))] pub(crate) fn fchmod(fd: BorrowedFd<'_>, mode: Mode) -> io::Result<()> { - unsafe { ret(c::fchmod(borrowed_fd(fd), mode.bits())) } + unsafe { ret(c::fchmod(borrowed_fd(fd), bitflags_bits!(mode))) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub(crate) fn fchmod(fd: BorrowedFd<'_>, mode: Mode) -> io::Result<()> { // Use `c::syscall` rather than `c::fchmod` because some libc // implementations, such as musl, add extra logic to `fchmod` to emulate // support for `O_PATH`, which uses `/proc` outside our control and // interferes with our own use of `O_PATH`. - unsafe { - syscall_ret(c::syscall( - c::SYS_fchmod, - borrowed_fd(fd), - c::c_uint::from(mode.bits()), - )) + syscall! { + fn fchmod( + fd: c::c_int, + mode: c::mode_t + ) via SYS_fchmod -> c::c_int } + unsafe { ret(fchmod(borrowed_fd(fd), mode.bits() as c::mode_t)) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub(crate) fn fchown(fd: BorrowedFd<'_>, owner: Option, group: Option) -> io::Result<()> { // Use `c::syscall` rather than `c::fchown` because some libc // implementations, such as musl, add extra logic to `fchown` to emulate // support for `O_PATH`, which uses `/proc` outside our control and // interferes with our own use of `O_PATH`. + syscall! { + fn fchown( + fd: c::c_int, + owner: c::uid_t, + group: c::gid_t + ) via SYS_fchown -> c::c_int + } unsafe { - let (ow, gr) = crate::process::translate_fchown_args(owner, group); - syscall_ret(c::syscall(c::SYS_fchown, borrowed_fd(fd), ow, gr)) + let (ow, gr) = crate::ugid::translate_fchown_args(owner, group); + ret(fchown(borrowed_fd(fd), ow, gr)) } } -#[cfg(not(any(target_os = "android", target_os = "linux", target_os = "wasi")))] +#[cfg(not(any(linux_kernel, target_os = "wasi")))] pub(crate) fn fchown(fd: BorrowedFd<'_>, owner: Option, group: Option) -> io::Result<()> { unsafe { - let (ow, gr) = crate::process::translate_fchown_args(owner, group); + let (ow, gr) = crate::ugid::translate_fchown_args(owner, group); ret(c::fchown(borrowed_fd(fd), ow, gr)) } } @@ -956,18 +1242,21 @@ pub(crate) fn flock(fd: BorrowedFd<'_>, operation: FlockOperation) -> io::Result unsafe { ret(c::flock(borrowed_fd(fd), operation as c::c_int)) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub(crate) fn syncfs(fd: BorrowedFd<'_>) -> io::Result<()> { // Some versions of Android libc lack a `syncfs` function. #[cfg(target_os = "android")] - unsafe { - syscall_ret(c::syscall(c::SYS_syncfs, borrowed_fd(fd))) + syscall! { + fn syncfs(fd: c::c_int) via SYS_syncfs -> c::c_int } + // `syncfs` was added to glibc in 2.20. #[cfg(not(target_os = "android"))] - unsafe { - ret(c::syncfs(borrowed_fd(fd))) + weak_or_syscall! { + fn syncfs(fd: c::c_int) via SYS_syncfs -> c::c_int } + + unsafe { ret(syncfs(borrowed_fd(fd))) } } #[cfg(not(any(target_os = "redox", target_os = "wasi")))] @@ -978,12 +1267,13 @@ pub(crate) fn sync() { pub(crate) fn fstat(fd: BorrowedFd<'_>) -> io::Result { // 32-bit and mips64 Linux: `struct stat64` is not y2038 compatible; use // `statx`. - #[cfg(all( - any(target_os = "android", target_os = "linux"), - any(target_pointer_width = "32", target_arch = "mips64"), - ))] + // + // And, some old platforms don't support `statx`, and some fail with a + // confusing error code, so we call `crate::fs::statx` to handle that. If + // `statx` isn't available, fall back to the buggy system call. + #[cfg(all(linux_kernel, any(target_pointer_width = "32", target_arch = "mips64")))] { - match statx(fd, cstr!(""), AtFlags::EMPTY_PATH, StatxFlags::BASIC_STATS) { + match crate::fs::statx(fd, cstr!(""), AtFlags::EMPTY_PATH, StatxFlags::BASIC_STATS) { Ok(x) => statx_to_stat(x), Err(io::Errno::NOSYS) => fstat_old(fd), Err(err) => Err(err), @@ -992,25 +1282,19 @@ pub(crate) fn fstat(fd: BorrowedFd<'_>) -> io::Result { // Main version: libc is y2038 safe. Or, the platform is not y2038 safe and // there's nothing practical we can do. - #[cfg(not(all( - any(target_os = "android", target_os = "linux"), - any(target_pointer_width = "32", target_arch = "mips64"), - )))] + #[cfg(not(all(linux_kernel, any(target_pointer_width = "32", target_arch = "mips64"))))] unsafe { let mut stat = MaybeUninit::::uninit(); - ret(libc_fstat(borrowed_fd(fd), stat.as_mut_ptr()))?; + ret(c::fstat(borrowed_fd(fd), stat.as_mut_ptr()))?; Ok(stat.assume_init()) } } -#[cfg(all( - any(target_os = "android", target_os = "linux"), - any(target_pointer_width = "32", target_arch = "mips64"), -))] +#[cfg(all(linux_kernel, any(target_pointer_width = "32", target_arch = "mips64")))] fn fstat_old(fd: BorrowedFd<'_>) -> io::Result { unsafe { let mut result = MaybeUninit::::uninit(); - ret(libc_fstat(borrowed_fd(fd), result.as_mut_ptr()))?; + ret(c::fstat(borrowed_fd(fd), result.as_mut_ptr()))?; stat64_to_stat(result.assume_init()) } } @@ -1025,22 +1309,22 @@ fn fstat_old(fd: BorrowedFd<'_>) -> io::Result { pub(crate) fn fstatfs(fd: BorrowedFd<'_>) -> io::Result { let mut statfs = MaybeUninit::::uninit(); unsafe { - ret(libc_fstatfs(borrowed_fd(fd), statfs.as_mut_ptr()))?; + ret(c::fstatfs(borrowed_fd(fd), statfs.as_mut_ptr()))?; Ok(statfs.assume_init()) } } #[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] pub(crate) fn fstatvfs(fd: BorrowedFd<'_>) -> io::Result { - let mut statvfs = MaybeUninit::::uninit(); + let mut statvfs = MaybeUninit::::uninit(); unsafe { - ret(libc_fstatvfs(borrowed_fd(fd), statvfs.as_mut_ptr()))?; + ret(c::fstatvfs(borrowed_fd(fd), statvfs.as_mut_ptr()))?; Ok(libc_statvfs_to_statvfs(statvfs.assume_init())) } } #[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] -fn libc_statvfs_to_statvfs(from: libc_statvfs) -> StatVfs { +fn libc_statvfs_to_statvfs(from: c::statvfs) -> StatVfs { StatVfs { f_bsize: from.f_bsize as u64, f_frsize: from.f_frsize as u64, @@ -1051,7 +1335,7 @@ fn libc_statvfs_to_statvfs(from: libc_statvfs) -> StatVfs { f_ffree: from.f_ffree as u64, f_favail: from.f_ffree as u64, f_fsid: from.f_fsid as u64, - f_flag: unsafe { StatVfsMountFlags::from_bits_unchecked(from.f_flag as u64) }, + f_flag: StatVfsMountFlags::from_bits_retain(from.f_flag as u64), f_namemax: from.f_namemax as u64, } } @@ -1174,15 +1458,20 @@ pub(crate) fn fallocate( let offset = offset as i64; let len = len as i64; - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] + #[cfg(any(linux_kernel, target_os = "fuchsia"))] unsafe { - ret(libc_fallocate(borrowed_fd(fd), mode.bits(), offset, len)) + ret(c::fallocate( + borrowed_fd(fd), + bitflags_bits!(mode), + offset, + len, + )) } - #[cfg(not(any(target_os = "android", target_os = "fuchsia", target_os = "linux")))] + #[cfg(not(any(linux_kernel, target_os = "fuchsia")))] { assert!(mode.is_empty()); - let err = unsafe { libc_posix_fallocate(borrowed_fd(fd), offset, len) }; + let err = unsafe { c::posix_fallocate(borrowed_fd(fd), offset, len) }; // `posix_fallocate` returns its error status rather than using `errno`. if err == 0 { @@ -1240,10 +1529,10 @@ pub(crate) fn fdatasync(fd: BorrowedFd<'_>) -> io::Result<()> { pub(crate) fn ftruncate(fd: BorrowedFd<'_>, length: u64) -> io::Result<()> { let length = length.try_into().map_err(|_overflow_err| io::Errno::FBIG)?; - unsafe { ret(libc_ftruncate(borrowed_fd(fd), length)) } + unsafe { ret(c::ftruncate(borrowed_fd(fd), length)) } } -#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "freebsd"))] pub(crate) fn memfd_create(path: &CStr, flags: MemfdFlags) -> io::Result { #[cfg(target_os = "freebsd")] weakcall! { @@ -1253,7 +1542,7 @@ pub(crate) fn memfd_create(path: &CStr, flags: MemfdFlags) -> io::Result c::c_int } - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_kernel)] weak_or_syscall! { fn memfd_create( name: *const c::c_char, @@ -1261,10 +1550,10 @@ pub(crate) fn memfd_create(path: &CStr, flags: MemfdFlags) -> io::Result c::c_int } - unsafe { ret_owned_fd(memfd_create(c_str(path), flags.bits())) } + unsafe { ret_owned_fd(memfd_create(c_str(path), bitflags_bits!(flags))) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub(crate) fn openat2( dirfd: BorrowedFd<'_>, path: &CStr, @@ -1272,45 +1561,38 @@ pub(crate) fn openat2( mode: Mode, resolve: ResolveFlags, ) -> io::Result { - let oflags: i32 = oflags.bits(); - let open_how = OpenHow { - oflag: u64::from(oflags as u32), + use linux_raw_sys::general::open_how; + + syscall! { + fn openat2( + base_dirfd: c::c_int, + pathname: *const c::c_char, + how: *mut open_how, + size: usize + ) via SYS_OPENAT2 -> c::c_int + } + + let oflags = oflags.bits(); + let mut open_how = open_how { + flags: u64::from(oflags), mode: u64::from(mode.bits()), resolve: resolve.bits(), }; unsafe { - syscall_ret_owned_fd(c::syscall( - SYS_OPENAT2, + ret_owned_fd(openat2( borrowed_fd(dirfd), c_str(path), - &open_how, - SIZEOF_OPEN_HOW, + &mut open_how, + size_of::(), )) } } -#[cfg(all( - target_pointer_width = "32", - any(target_os = "android", target_os = "linux"), -))] +#[cfg(all(linux_kernel, target_pointer_width = "32"))] const SYS_OPENAT2: i32 = 437; -#[cfg(all( - target_pointer_width = "64", - any(target_os = "android", target_os = "linux"), -))] +#[cfg(all(linux_kernel, target_pointer_width = "64"))] const SYS_OPENAT2: i64 = 437; -#[cfg(any(target_os = "android", target_os = "linux"))] -#[repr(C)] -#[derive(Debug)] -struct OpenHow { - oflag: u64, - mode: u64, - resolve: u64, -} -#[cfg(any(target_os = "android", target_os = "linux"))] -const SIZEOF_OPEN_HOW: usize = size_of::(); - #[cfg(target_os = "linux")] pub(crate) fn sendfile( out_fd: BorrowedFd<'_>, @@ -1329,10 +1611,7 @@ pub(crate) fn sendfile( } /// Convert from a Linux `statx` value to rustix's `Stat`. -#[cfg(all( - any(target_os = "android", target_os = "linux"), - target_pointer_width = "32", -))] +#[cfg(all(linux_kernel, target_pointer_width = "32"))] fn statx_to_stat(x: crate::fs::Statx) -> io::Result { Ok(Stat { st_dev: crate::fs::makedev(x.stx_dev_major, x.stx_dev_minor).into(), @@ -1369,10 +1648,7 @@ fn statx_to_stat(x: crate::fs::Statx) -> io::Result { /// Convert from a Linux `statx` value to rustix's `Stat`. /// /// mips64' `struct stat64` in libc has private fields, and `stx_blocks` -#[cfg(all( - any(target_os = "android", target_os = "linux"), - target_arch = "mips64", -))] +#[cfg(all(linux_kernel, target_arch = "mips64"))] fn statx_to_stat(x: crate::fs::Statx) -> io::Result { let mut result: Stat = unsafe { core::mem::zeroed() }; @@ -1409,10 +1685,7 @@ fn statx_to_stat(x: crate::fs::Statx) -> io::Result { } /// Convert from a Linux `stat64` value to rustix's `Stat`. -#[cfg(all( - any(target_os = "android", target_os = "linux"), - target_pointer_width = "32", -))] +#[cfg(all(linux_kernel, target_pointer_width = "32"))] fn stat64_to_stat(s64: c::stat64) -> io::Result { Ok(Stat { st_dev: s64.st_dev.try_into().map_err(|_| io::Errno::OVERFLOW)?, @@ -1447,10 +1720,7 @@ fn stat64_to_stat(s64: c::stat64) -> io::Result { /// /// mips64' `struct stat64` in libc has private fields, and `st_blocks` has /// type `i64`. -#[cfg(all( - any(target_os = "android", target_os = "linux"), - target_arch = "mips64", -))] +#[cfg(all(linux_kernel, target_arch = "mips64"))] fn stat64_to_stat(s64: c::stat64) -> io::Result { let mut result: Stat = unsafe { core::mem::zeroed() }; @@ -1483,7 +1753,7 @@ fn stat64_to_stat(s64: c::stat64) -> io::Result { Ok(result) } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[allow(non_upper_case_globals)] mod sys { use super::{c, BorrowedFd, Statx}; @@ -1499,7 +1769,7 @@ mod sys { } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[allow(non_upper_case_globals)] pub(crate) fn statx( dirfd: BorrowedFd<'_>, @@ -1534,7 +1804,7 @@ pub(crate) fn statx( ret(sys::statx( dirfd, c_str(path), - flags.bits(), + bitflags_bits!(flags), mask.bits(), statx_buf.as_mut_ptr(), ))?; @@ -1542,14 +1812,14 @@ pub(crate) fn statx( } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] pub(crate) fn is_statx_available() -> bool { unsafe { // Call `statx` with null pointers so that if it fails for any reason // other than `EFAULT`, we know it's not supported. matches!( - ret(sys::statx(cwd(), null(), 0, 0, null_mut())), + ret(sys::statx(CWD, null(), 0, 0, null_mut())), Err(io::Errno::FAULT) ) } @@ -1575,7 +1845,7 @@ pub(crate) unsafe fn fcopyfile( borrowed_fd(from), borrowed_fd(to), state, - flags.bits(), + bitflags_bits!(flags), )) } @@ -1632,7 +1902,7 @@ pub(crate) fn getpath(fd: BorrowedFd<'_>) -> io::Result { // `F_GETPATH` in terms of `MAXPATHLEN`, and there are no // alternatives. If a better method is invented, it should be used // instead. - let mut buf = alloc::vec![0; c::PATH_MAX as usize]; + let mut buf = vec![0; c::PATH_MAX as usize]; // From the [macOS `fcntl` manual page]: // `F_GETPATH` - Get the path of the file descriptor `Fildes`. The argument @@ -1645,9 +1915,6 @@ pub(crate) fn getpath(fd: BorrowedFd<'_>) -> io::Result { let l = buf.iter().position(|&c| c == 0).unwrap(); buf.truncate(l); - - // TODO: On Rust 1.56, we can use `shrink_to` here. - //buf.shrink_to(l + 1); buf.shrink_to_fit(); Ok(CString::new(buf).unwrap()) @@ -1781,7 +2048,7 @@ struct Attrlist { forkattr: Attrgroup, } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub(crate) fn mount( source: Option<&CStr>, target: &CStr, @@ -1800,12 +2067,12 @@ pub(crate) fn mount( } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub(crate) fn unmount(target: &CStr, flags: super::types::UnmountFlags) -> io::Result<()> { - unsafe { ret(c::umount2(target.as_ptr(), flags.bits())) } + unsafe { ret(c::umount2(target.as_ptr(), bitflags_bits!(flags))) } } -#[cfg(any(apple, target_os = "android", target_os = "linux"))] +#[cfg(any(apple, linux_kernel))] pub(crate) fn getxattr(path: &CStr, name: &CStr, value: &mut [u8]) -> io::Result { let value_ptr = value.as_mut_ptr(); @@ -1832,7 +2099,7 @@ pub(crate) fn getxattr(path: &CStr, name: &CStr, value: &mut [u8]) -> io::Result } } -#[cfg(any(apple, target_os = "android", target_os = "linux"))] +#[cfg(any(apple, linux_kernel))] pub(crate) fn lgetxattr(path: &CStr, name: &CStr, value: &mut [u8]) -> io::Result { let value_ptr = value.as_mut_ptr(); @@ -1859,7 +2126,7 @@ pub(crate) fn lgetxattr(path: &CStr, name: &CStr, value: &mut [u8]) -> io::Resul } } -#[cfg(any(apple, target_os = "android", target_os = "linux"))] +#[cfg(any(apple, linux_kernel))] pub(crate) fn fgetxattr(fd: BorrowedFd<'_>, name: &CStr, value: &mut [u8]) -> io::Result { let value_ptr = value.as_mut_ptr(); @@ -1886,7 +2153,7 @@ pub(crate) fn fgetxattr(fd: BorrowedFd<'_>, name: &CStr, value: &mut [u8]) -> io } } -#[cfg(any(apple, target_os = "android", target_os = "linux"))] +#[cfg(any(apple, linux_kernel))] pub(crate) fn setxattr( path: &CStr, name: &CStr, @@ -1917,7 +2184,7 @@ pub(crate) fn setxattr( } } -#[cfg(any(apple, target_os = "android", target_os = "linux"))] +#[cfg(any(apple, linux_kernel))] pub(crate) fn lsetxattr( path: &CStr, name: &CStr, @@ -1948,7 +2215,7 @@ pub(crate) fn lsetxattr( } } -#[cfg(any(apple, target_os = "android", target_os = "linux"))] +#[cfg(any(apple, linux_kernel))] pub(crate) fn fsetxattr( fd: BorrowedFd<'_>, name: &CStr, @@ -1979,7 +2246,7 @@ pub(crate) fn fsetxattr( } } -#[cfg(any(apple, target_os = "android", target_os = "linux"))] +#[cfg(any(apple, linux_kernel))] pub(crate) fn listxattr(path: &CStr, list: &mut [c::c_char]) -> io::Result { #[cfg(not(apple))] unsafe { @@ -1997,7 +2264,7 @@ pub(crate) fn listxattr(path: &CStr, list: &mut [c::c_char]) -> io::Result io::Result { #[cfg(not(apple))] unsafe { @@ -2015,7 +2282,7 @@ pub(crate) fn llistxattr(path: &CStr, list: &mut [c::c_char]) -> io::Result, list: &mut [c::c_char]) -> io::Result { let fd = borrowed_fd(fd); @@ -2030,7 +2297,7 @@ pub(crate) fn flistxattr(fd: BorrowedFd<'_>, list: &mut [c::c_char]) -> io::Resu } } -#[cfg(any(apple, target_os = "android", target_os = "linux"))] +#[cfg(any(apple, linux_kernel))] pub(crate) fn removexattr(path: &CStr, name: &CStr) -> io::Result<()> { #[cfg(not(apple))] unsafe { @@ -2043,7 +2310,7 @@ pub(crate) fn removexattr(path: &CStr, name: &CStr) -> io::Result<()> { } } -#[cfg(any(apple, target_os = "android", target_os = "linux"))] +#[cfg(any(apple, linux_kernel))] pub(crate) fn lremovexattr(path: &CStr, name: &CStr) -> io::Result<()> { #[cfg(not(apple))] unsafe { @@ -2060,7 +2327,7 @@ pub(crate) fn lremovexattr(path: &CStr, name: &CStr) -> io::Result<()> { } } -#[cfg(any(apple, target_os = "android", target_os = "linux"))] +#[cfg(any(apple, linux_kernel))] pub(crate) fn fremovexattr(fd: BorrowedFd<'_>, name: &CStr) -> io::Result<()> { let fd = borrowed_fd(fd); @@ -2074,3 +2341,52 @@ pub(crate) fn fremovexattr(fd: BorrowedFd<'_>, name: &CStr) -> io::Result<()> { ret(c::fremovexattr(fd, name.as_ptr(), 0)) } } + +#[cfg(linux_kernel)] +#[inline] +pub(crate) fn ioctl_blksszget(fd: BorrowedFd) -> io::Result { + let mut result = MaybeUninit::::uninit(); + unsafe { + ret(c::ioctl(borrowed_fd(fd), c::BLKSSZGET, result.as_mut_ptr()))?; + Ok(result.assume_init() as u32) + } +} + +#[cfg(linux_kernel)] +#[inline] +pub(crate) fn ioctl_blkpbszget(fd: BorrowedFd) -> io::Result { + let mut result = MaybeUninit::::uninit(); + unsafe { + ret(c::ioctl( + borrowed_fd(fd), + c::BLKPBSZGET, + result.as_mut_ptr(), + ))?; + Ok(result.assume_init() as u32) + } +} + +// Sparc lacks `FICLONE`. +#[cfg(all(linux_kernel, not(any(target_arch = "sparc", target_arch = "sparc64"))))] +pub(crate) fn ioctl_ficlone(fd: BorrowedFd<'_>, src_fd: BorrowedFd<'_>) -> io::Result<()> { + unsafe { + ret(c::ioctl( + borrowed_fd(fd), + c::FICLONE as _, + borrowed_fd(src_fd), + )) + } +} + +#[cfg(linux_kernel)] +#[inline] +pub(crate) fn ext4_ioc_resize_fs(fd: BorrowedFd<'_>, blocks: u64) -> io::Result<()> { + // TODO: Fix linux-raw-sys to define ioctl codes for sparc. + #[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] + const EXT4_IOC_RESIZE_FS: u32 = 0x8008_6610; + + #[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))] + use linux_raw_sys::ioctl::EXT4_IOC_RESIZE_FS; + + unsafe { ret(c::ioctl(borrowed_fd(fd), EXT4_IOC_RESIZE_FS as _, &blocks)) } +} diff --git a/vendor/rustix/src/backend/libc/fs/types.rs b/vendor/rustix/src/backend/libc/fs/types.rs index 0cf7fe8ff..b52f0e210 100644 --- a/vendor/rustix/src/backend/libc/fs/types.rs +++ b/vendor/rustix/src/backend/libc/fs/types.rs @@ -1,10 +1,12 @@ -use super::super::c; +use crate::backend::c; use bitflags::bitflags; bitflags! { /// `*_OK` constants for use with [`accessat`]. /// /// [`accessat`]: fn.accessat.html + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct Access: c::c_int { /// `R_OK` const READ_OK = c::R_OK; @@ -27,44 +29,49 @@ bitflags! { /// /// [`openat`]: crate::fs::openat /// [`statat`]: crate::fs::statat - pub struct AtFlags: c::c_int { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct AtFlags: u32 { + /// `AT_SYMLINK_NOFOLLOW` + const SYMLINK_NOFOLLOW = bitcast!(c::AT_SYMLINK_NOFOLLOW); + + /// `AT_EACCESS` + #[cfg(not(any(target_os = "emscripten", target_os = "android")))] + const EACCESS = bitcast!(c::AT_EACCESS); + /// `AT_REMOVEDIR` - const REMOVEDIR = c::AT_REMOVEDIR; + const REMOVEDIR = bitcast!(c::AT_REMOVEDIR); /// `AT_SYMLINK_FOLLOW` - const SYMLINK_FOLLOW = c::AT_SYMLINK_FOLLOW; + const SYMLINK_FOLLOW = bitcast!(c::AT_SYMLINK_FOLLOW); - /// `AT_SYMLINK_NOFOLLOW` - const SYMLINK_NOFOLLOW = c::AT_SYMLINK_NOFOLLOW; + /// `AT_NO_AUTOMOUNT` + #[cfg(any(linux_like, target_os = "fuchsia"))] + const NO_AUTOMOUNT = bitcast!(c::AT_NO_AUTOMOUNT); /// `AT_EMPTY_PATH` #[cfg(any( - target_os = "android", + linux_kernel, target_os = "freebsd", target_os = "fuchsia", - target_os = "linux", ))] - const EMPTY_PATH = c::AT_EMPTY_PATH; + const EMPTY_PATH = bitcast!(c::AT_EMPTY_PATH); /// `AT_RESOLVE_BENEATH` #[cfg(target_os = "freebsd")] - const RESOLVE_BENEATH = c::AT_RESOLVE_BENEATH; - - /// `AT_EACCESS` - #[cfg(not(any(target_os = "emscripten", target_os = "android")))] - const EACCESS = c::AT_EACCESS; + const RESOLVE_BENEATH = bitcast!(c::AT_RESOLVE_BENEATH); /// `AT_STATX_SYNC_AS_STAT` #[cfg(all(target_os = "linux", target_env = "gnu"))] - const STATX_SYNC_AS_STAT = c::AT_STATX_SYNC_AS_STAT; + const STATX_SYNC_AS_STAT = bitcast!(c::AT_STATX_SYNC_AS_STAT); /// `AT_STATX_FORCE_SYNC` #[cfg(all(target_os = "linux", target_env = "gnu"))] - const STATX_FORCE_SYNC = c::AT_STATX_FORCE_SYNC; + const STATX_FORCE_SYNC = bitcast!(c::AT_STATX_FORCE_SYNC); /// `AT_STATX_DONT_SYNC` #[cfg(all(target_os = "linux", target_env = "gnu"))] - const STATX_DONT_SYNC = c::AT_STATX_DONT_SYNC; + const STATX_DONT_SYNC = bitcast!(c::AT_STATX_DONT_SYNC); } } @@ -74,6 +81,8 @@ bitflags! { /// [`openat`]: crate::fs::openat /// [`chmodat`]: crate::fs::chmodat /// [`fchmod`]: crate::fs::fchmod + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct Mode: RawMode { /// `S_IRWXU` #[cfg(not(target_os = "wasi"))] // WASI doesn't have Unix-style mode flags. @@ -166,7 +175,7 @@ impl From for Mode { } impl From for RawMode { - /// Support conversions from `Mode to raw mode values. + /// Support conversions from `Mode` to raw mode values. /// /// ``` /// use rustix::fs::{Mode, RawMode}; @@ -182,9 +191,11 @@ bitflags! { /// `O_*` constants for use with [`openat`]. /// /// [`openat`]: crate::fs::openat - pub struct OFlags: c::c_int { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct OFlags: u32 { /// `O_ACCMODE` - const ACCMODE = c::O_ACCMODE; + const ACCMODE = bitcast!(c::O_ACCMODE); /// Similar to `ACCMODE`, but just includes the read/write flags, and /// no other flags. @@ -193,117 +204,112 @@ bitflags! { /// sometimes we really just want the read/write bits. Caution is /// indicated, as the presence of `O_PATH` may mean that the read/write /// bits don't have their usual meaning. - const RWMODE = c::O_RDONLY | c::O_WRONLY | c::O_RDWR; + const RWMODE = bitcast!(c::O_RDONLY | c::O_WRONLY | c::O_RDWR); /// `O_APPEND` - const APPEND = c::O_APPEND; + const APPEND = bitcast!(c::O_APPEND); /// `O_CREAT` #[doc(alias = "CREAT")] - const CREATE = c::O_CREAT; + const CREATE = bitcast!(c::O_CREAT); /// `O_DIRECTORY` - const DIRECTORY = c::O_DIRECTORY; + const DIRECTORY = bitcast!(c::O_DIRECTORY); /// `O_DSYNC` #[cfg(not(any(target_os = "dragonfly", target_os = "redox")))] - const DSYNC = c::O_DSYNC; + const DSYNC = bitcast!(c::O_DSYNC); /// `O_EXCL` - const EXCL = c::O_EXCL; + const EXCL = bitcast!(c::O_EXCL); /// `O_FSYNC` #[cfg(any( bsd, all(target_os = "linux", not(target_env = "musl")), ))] - const FSYNC = c::O_FSYNC; + const FSYNC = bitcast!(c::O_FSYNC); /// `O_NOFOLLOW` - const NOFOLLOW = c::O_NOFOLLOW; + const NOFOLLOW = bitcast!(c::O_NOFOLLOW); /// `O_NONBLOCK` - const NONBLOCK = c::O_NONBLOCK; + const NONBLOCK = bitcast!(c::O_NONBLOCK); /// `O_RDONLY` - const RDONLY = c::O_RDONLY; + const RDONLY = bitcast!(c::O_RDONLY); /// `O_WRONLY` - const WRONLY = c::O_WRONLY; + const WRONLY = bitcast!(c::O_WRONLY); /// `O_RDWR` - const RDWR = c::O_RDWR; + const RDWR = bitcast!(c::O_RDWR); /// `O_NOCTTY` #[cfg(not(target_os = "redox"))] - const NOCTTY = c::O_NOCTTY; + const NOCTTY = bitcast!(c::O_NOCTTY); /// `O_RSYNC` #[cfg(any( + linux_kernel, netbsdlike, - target_os = "android", target_os = "emscripten", - target_os = "linux", target_os = "wasi", ))] - const RSYNC = c::O_RSYNC; + const RSYNC = bitcast!(c::O_RSYNC); /// `O_SYNC` #[cfg(not(target_os = "redox"))] - const SYNC = c::O_SYNC; + const SYNC = bitcast!(c::O_SYNC); /// `O_TRUNC` - const TRUNC = c::O_TRUNC; + const TRUNC = bitcast!(c::O_TRUNC); /// `O_PATH` #[cfg(any( - target_os = "android", + linux_kernel, target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", - target_os = "linux", target_os = "redox", ))] - const PATH = c::O_PATH; + const PATH = bitcast!(c::O_PATH); /// `O_CLOEXEC` - const CLOEXEC = c::O_CLOEXEC; + const CLOEXEC = bitcast!(c::O_CLOEXEC); /// `O_TMPFILE` #[cfg(any( - target_os = "android", + linux_kernel, target_os = "emscripten", target_os = "fuchsia", - target_os = "linux", ))] - const TMPFILE = c::O_TMPFILE; + const TMPFILE = bitcast!(c::O_TMPFILE); /// `O_NOATIME` #[cfg(any( - target_os = "android", + linux_kernel, target_os = "fuchsia", - target_os = "linux", ))] - const NOATIME = c::O_NOATIME; + const NOATIME = bitcast!(c::O_NOATIME); /// `O_DIRECT` #[cfg(any( - target_os = "android", + linux_kernel, target_os = "emscripten", target_os = "freebsd", target_os = "fuchsia", - target_os = "linux", target_os = "netbsd", ))] - const DIRECT = c::O_DIRECT; + const DIRECT = bitcast!(c::O_DIRECT); /// `O_RESOLVE_BENEATH` #[cfg(target_os = "freebsd")] - const RESOLVE_BENEATH = c::O_RESOLVE_BENEATH; + const RESOLVE_BENEATH = bitcast!(c::O_RESOLVE_BENEATH); /// `O_EMPTY_PATH` #[cfg(target_os = "freebsd")] - const EMPTY_PATH = c::O_EMPTY_PATH; + const EMPTY_PATH = bitcast!(c::O_EMPTY_PATH); } } @@ -312,7 +318,9 @@ bitflags! { /// `CLONE_*` constants for use with [`fclonefileat`]. /// /// [`fclonefileat`]: crate::fs::fclonefileat - pub struct CloneFlags: c::c_int { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct CloneFlags: u32 { /// `CLONE_NOFOLLOW` const NOFOLLOW = 1; @@ -337,6 +345,8 @@ bitflags! { /// `COPYFILE_*` constants for use with [`fcopyfile`]. /// /// [`fcopyfile`]: crate::fs::fcopyfile + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct CopyfileFlags: c::c_uint { /// `COPYFILE_ACL` const ACL = copyfile::ACL; @@ -361,12 +371,13 @@ bitflags! { } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] bitflags! { /// `RESOLVE_*` constants for use with [`openat2`]. /// /// [`openat2`]: crate::fs::openat2 - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct ResolveFlags: u64 { /// `RESOLVE_NO_XDEV` const NO_XDEV = 0x01; @@ -388,20 +399,22 @@ bitflags! { } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] bitflags! { /// `RENAME_*` constants for use with [`renameat_with`]. /// /// [`renameat_with`]: crate::fs::renameat_with + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct RenameFlags: c::c_uint { /// `RENAME_EXCHANGE` - const EXCHANGE = c::RENAME_EXCHANGE as _; + const EXCHANGE = bitcast!(c::RENAME_EXCHANGE); /// `RENAME_NOREPLACE` - const NOREPLACE = c::RENAME_NOREPLACE as _; + const NOREPLACE = bitcast!(c::RENAME_NOREPLACE); /// `RENAME_WHITEOUT` - const WHITEOUT = c::RENAME_WHITEOUT as _; + const WHITEOUT = bitcast!(c::RENAME_WHITEOUT); } } @@ -528,11 +541,13 @@ pub enum Advice { DontNeed = c::POSIX_FADV_DONTNEED as c::c_uint, } -#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "freebsd"))] bitflags! { /// `MFD_*` constants for use with [`memfd_create`]. /// /// [`memfd_create`]: crate::fs::memfd_create + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct MemfdFlags: c::c_uint { /// `MFD_CLOEXEC` const CLOEXEC = c::MFD_CLOEXEC; @@ -570,30 +585,27 @@ bitflags! { } } -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))] bitflags! { /// `F_SEAL_*` constants for use with [`fcntl_add_seals`] and /// [`fcntl_get_seals`]. /// /// [`fcntl_add_seals`]: crate::fs::fcntl_add_seals /// [`fcntl_get_seals`]: crate::fs::fcntl_get_seals - pub struct SealFlags: i32 { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct SealFlags: u32 { /// `F_SEAL_SEAL`. - const SEAL = c::F_SEAL_SEAL; + const SEAL = bitcast!(c::F_SEAL_SEAL); /// `F_SEAL_SHRINK`. - const SHRINK = c::F_SEAL_SHRINK; + const SHRINK = bitcast!(c::F_SEAL_SHRINK); /// `F_SEAL_GROW`. - const GROW = c::F_SEAL_GROW; + const GROW = bitcast!(c::F_SEAL_GROW); /// `F_SEAL_WRITE`. - const WRITE = c::F_SEAL_WRITE; + const WRITE = bitcast!(c::F_SEAL_WRITE); /// `F_SEAL_FUTURE_WRITE` (since Linux 5.1) - #[cfg(any(target_os = "android", target_os = "linux"))] - const FUTURE_WRITE = c::F_SEAL_FUTURE_WRITE; + #[cfg(linux_kernel)] + const FUTURE_WRITE = bitcast!(c::F_SEAL_FUTURE_WRITE); } } @@ -602,6 +614,8 @@ bitflags! { /// `STATX_*` constants for use with [`statx`]. /// /// [`statx`]: crate::fs::statx + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct StatxFlags: u32 { /// `STATX_TYPE` const TYPE = c::STATX_TYPE; @@ -645,6 +659,9 @@ bitflags! { /// `STATX_MNT_ID` (since Linux 5.8) const MNT_ID = c::STATX_MNT_ID; + /// `STATX_DIOALIGN` (since Linux 6.1) + const DIOALIGN = c::STATX_DIOALIGN; + /// `STATX_ALL` const ALL = c::STATX_ALL; } @@ -658,6 +675,8 @@ bitflags! { /// `STATX_*` constants for use with [`statx`]. /// /// [`statx`]: crate::fs::statx + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct StatxFlags: u32 { /// `STATX_TYPE` const TYPE = 0x0001; @@ -711,7 +730,9 @@ bitflags! { /// `FALLOC_FL_*` constants for use with [`fallocate`]. /// /// [`fallocate`]: crate::fs::fallocate - pub struct FallocateFlags: i32 { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct FallocateFlags: u32 { /// `FALLOC_FL_KEEP_SIZE` #[cfg(not(any( bsd, @@ -719,7 +740,7 @@ bitflags! { target_os = "haiku", target_os = "wasi", )))] - const KEEP_SIZE = c::FALLOC_FL_KEEP_SIZE; + const KEEP_SIZE = bitcast!(c::FALLOC_FL_KEEP_SIZE); /// `FALLOC_FL_PUNCH_HOLE` #[cfg(not(any( bsd, @@ -727,7 +748,7 @@ bitflags! { target_os = "haiku", target_os = "wasi", )))] - const PUNCH_HOLE = c::FALLOC_FL_PUNCH_HOLE; + const PUNCH_HOLE = bitcast!(c::FALLOC_FL_PUNCH_HOLE); /// `FALLOC_FL_NO_HIDE_STALE` #[cfg(not(any( bsd, @@ -738,7 +759,7 @@ bitflags! { target_os = "fuchsia", target_os = "wasi", )))] - const NO_HIDE_STALE = c::FALLOC_FL_NO_HIDE_STALE; + const NO_HIDE_STALE = bitcast!(c::FALLOC_FL_NO_HIDE_STALE); /// `FALLOC_FL_COLLAPSE_RANGE` #[cfg(not(any( bsd, @@ -747,7 +768,7 @@ bitflags! { target_os = "emscripten", target_os = "wasi", )))] - const COLLAPSE_RANGE = c::FALLOC_FL_COLLAPSE_RANGE; + const COLLAPSE_RANGE = bitcast!(c::FALLOC_FL_COLLAPSE_RANGE); /// `FALLOC_FL_ZERO_RANGE` #[cfg(not(any( bsd, @@ -756,7 +777,7 @@ bitflags! { target_os = "emscripten", target_os = "wasi", )))] - const ZERO_RANGE = c::FALLOC_FL_ZERO_RANGE; + const ZERO_RANGE = bitcast!(c::FALLOC_FL_ZERO_RANGE); /// `FALLOC_FL_INSERT_RANGE` #[cfg(not(any( bsd, @@ -765,7 +786,7 @@ bitflags! { target_os = "emscripten", target_os = "wasi", )))] - const INSERT_RANGE = c::FALLOC_FL_INSERT_RANGE; + const INSERT_RANGE = bitcast!(c::FALLOC_FL_INSERT_RANGE); /// `FALLOC_FL_UNSHARE_RANGE` #[cfg(not(any( bsd, @@ -774,32 +795,39 @@ bitflags! { target_os = "emscripten", target_os = "wasi", )))] - const UNSHARE_RANGE = c::FALLOC_FL_UNSHARE_RANGE; + const UNSHARE_RANGE = bitcast!(c::FALLOC_FL_UNSHARE_RANGE); } } #[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] bitflags! { /// `ST_*` constants for use with [`StatVfs`]. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct StatVfsMountFlags: u64 { /// `ST_MANDLOCK` - #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "fuchsia", target_os = "linux"))] + #[cfg(any(linux_kernel, target_os = "emscripten", target_os = "fuchsia"))] const MANDLOCK = c::ST_MANDLOCK as u64; /// `ST_NOATIME` - #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "fuchsia", target_os = "linux"))] + #[cfg(any(linux_kernel, target_os = "emscripten", target_os = "fuchsia"))] const NOATIME = c::ST_NOATIME as u64; /// `ST_NODEV` - #[cfg(any(target_os = "aix", target_os = "android", target_os = "emscripten", target_os = "fuchsia", target_os = "linux"))] + #[cfg(any( + linux_kernel, + target_os = "aix", + target_os = "emscripten", + target_os = "fuchsia" + ))] const NODEV = c::ST_NODEV as u64; /// `ST_NODIRATIME` - #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "fuchsia", target_os = "linux"))] + #[cfg(any(linux_kernel, target_os = "emscripten", target_os = "fuchsia"))] const NODIRATIME = c::ST_NODIRATIME as u64; /// `ST_NOEXEC` - #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "fuchsia", target_os = "linux"))] + #[cfg(any(linux_kernel, target_os = "emscripten", target_os = "fuchsia"))] const NOEXEC = c::ST_NOEXEC as u64; /// `ST_NOSUID` @@ -813,7 +841,7 @@ bitflags! { const RELATIME = c::ST_RELATIME as u64; /// `ST_SYNCHRONOUS` - #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "fuchsia", target_os = "linux"))] + #[cfg(any(linux_kernel, target_os = "emscripten", target_os = "fuchsia"))] const SYNCHRONOUS = c::ST_SYNCHRONOUS as u64; } } @@ -824,20 +852,20 @@ bitflags! { /// [`fcntl_lock`]: crate::fs::fcntl_lock #[cfg(not(target_os = "wasi"))] #[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[repr(i32)] +#[repr(u32)] pub enum FlockOperation { /// `LOCK_SH` - LockShared = c::LOCK_SH, + LockShared = bitcast!(c::LOCK_SH), /// `LOCK_EX` - LockExclusive = c::LOCK_EX, + LockExclusive = bitcast!(c::LOCK_EX), /// `LOCK_UN` - Unlock = c::LOCK_UN, + Unlock = bitcast!(c::LOCK_UN), /// `LOCK_SH | LOCK_NB` - NonBlockingLockShared = c::LOCK_SH | c::LOCK_NB, + NonBlockingLockShared = bitcast!(c::LOCK_SH | c::LOCK_NB), /// `LOCK_EX | LOCK_NB` - NonBlockingLockExclusive = c::LOCK_EX | c::LOCK_NB, + NonBlockingLockExclusive = bitcast!(c::LOCK_EX | c::LOCK_NB), /// `LOCK_UN | LOCK_NB` - NonBlockingUnlock = c::LOCK_UN | c::LOCK_NB, + NonBlockingUnlock = bitcast!(c::LOCK_UN | c::LOCK_NB), } /// `struct stat` for use with [`statat`] and [`fstat`]. @@ -852,10 +880,7 @@ pub type Stat = c::stat; /// [`statat`]: crate::fs::statat /// [`fstat`]: crate::fs::fstat #[cfg(any( - all( - any(target_os = "android", target_os = "linux"), - target_pointer_width = "64", - ), + all(linux_kernel, target_pointer_width = "64"), target_os = "emscripten", target_os = "l4re", ))] @@ -868,10 +893,7 @@ pub type Stat = c::stat64; // On 32-bit, Linux's `struct stat64` has a 32-bit `st_mtime` and friends, so // we use our own struct, populated from `statx` where possible, to avoid the // y2038 bug. -#[cfg(all( - any(target_os = "android", target_os = "linux"), - target_pointer_width = "32", -))] +#[cfg(all(linux_kernel, target_pointer_width = "32"))] #[repr(C)] #[derive(Debug, Copy, Clone)] #[allow(missing_docs)] @@ -1053,11 +1075,13 @@ pub type FsWord = u32; #[derive(Copy, Clone)] pub struct copyfile_state_t(pub(crate) *mut c::c_void); -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] bitflags! { /// `MS_*` constants for use with [`mount`]. /// /// [`mount`]: crate::fs::mount + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct MountFlags: c::c_ulong { /// `MS_BIND` const BIND = c::MS_BIND; @@ -1107,11 +1131,13 @@ bitflags! { } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] bitflags! { /// `MS_*` constants for use with [`change_mount`]. /// /// [`change_mount`]: crate::fs::mount::change_mount + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct MountPropagationFlags: c::c_ulong { /// `MS_SHARED` const SHARED = c::MS_SHARED; @@ -1126,30 +1152,34 @@ bitflags! { } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] bitflags! { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub(crate) struct InternalMountFlags: c::c_ulong { const REMOUNT = c::MS_REMOUNT; const MOVE = c::MS_MOVE; } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub(crate) struct MountFlagsArg(pub(crate) c::c_ulong); -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] bitflags! { /// `MNT_*` constants for use with [`unmount`]. /// /// [`unmount`]: crate::fs::mount::unmount - pub struct UnmountFlags: c::c_int { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct UnmountFlags: u32 { /// `MNT_FORCE` - const FORCE = c::MNT_FORCE; + const FORCE = bitcast!(c::MNT_FORCE); /// `MNT_DETACH` - const DETACH = c::MNT_DETACH; + const DETACH = bitcast!(c::MNT_DETACH); /// `MNT_EXPIRE` - const EXPIRE = c::MNT_EXPIRE; + const EXPIRE = bitcast!(c::MNT_EXPIRE); /// `UMOUNT_NOFOLLOW` - const NOFOLLOW = c::UMOUNT_NOFOLLOW; + const NOFOLLOW = bitcast!(c::UMOUNT_NOFOLLOW); } } diff --git a/vendor/rustix/src/backend/libc/io/epoll.rs b/vendor/rustix/src/backend/libc/io/epoll.rs deleted file mode 100644 index 62a3c742b..000000000 --- a/vendor/rustix/src/backend/libc/io/epoll.rs +++ /dev/null @@ -1,366 +0,0 @@ -//! epoll support. -//! -//! This is an experiment, and it isn't yet clear whether epoll is the right -//! level of abstraction at which to introduce safety. But it works fairly well -//! in simple examples 🙂. -//! -//! # Examples -//! -//! ```no_run -//! # #![cfg_attr(io_lifetimes_use_std, feature(io_safety))] -//! # #[cfg(feature = "net")] -//! # fn main() -> std::io::Result<()> { -//! use io_lifetimes::AsFd; -//! use rustix::io::{epoll, ioctl_fionbio, read, write}; -//! use rustix::net::{ -//! accept, bind_v4, listen, socket, AddressFamily, Ipv4Addr, Protocol, SocketAddrV4, -//! SocketType, -//! }; -//! use std::collections::HashMap; -//! use std::os::unix::io::AsRawFd; -//! -//! // Create a socket and listen on it. -//! let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?; -//! bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0))?; -//! listen(&listen_sock, 1)?; -//! -//! // Create an epoll object. Using `Owning` here means the epoll object will -//! // take ownership of the file descriptors registered with it. -//! let epoll = epoll::epoll_create(epoll::CreateFlags::CLOEXEC)?; -//! -//! // Register the socket with the epoll object. -//! epoll::epoll_add(&epoll, &listen_sock, 1, epoll::EventFlags::IN)?; -//! -//! // Keep track of the sockets we've opened. -//! let mut next_id = 2; -//! let mut sockets = HashMap::new(); -//! -//! // Process events. -//! let mut event_list = epoll::EventVec::with_capacity(4); -//! loop { -//! epoll::epoll_wait(&epoll, &mut event_list, -1)?; -//! for (_event_flags, target) in &event_list { -//! if target == 1 { -//! // Accept a new connection, set it to non-blocking, and -//! // register to be notified when it's ready to write to. -//! let conn_sock = accept(&listen_sock)?; -//! ioctl_fionbio(&conn_sock, true)?; -//! epoll::epoll_add( -//! &epoll, -//! &conn_sock, -//! next_id, -//! epoll::EventFlags::OUT | epoll::EventFlags::ET, -//! )?; -//! -//! // Keep track of the socket. -//! sockets.insert(next_id, conn_sock); -//! next_id += 1; -//! } else { -//! // Write a message to the stream and then unregister it. -//! let target = sockets.remove(&target).unwrap(); -//! write(&target, b"hello\n")?; -//! let _ = epoll::epoll_del(&epoll, &target)?; -//! } -//! } -//! } -//! # } -//! # #[cfg(not(feature = "net"))] -//! # fn main() {} -//! ``` - -use super::super::c; -use super::super::conv::{ret, ret_owned_fd, ret_u32}; -use crate::fd::{AsFd, AsRawFd, OwnedFd}; -use crate::io; -use alloc::vec::Vec; -use bitflags::bitflags; -use core::convert::TryInto; -use core::ptr::null_mut; - -bitflags! { - /// `EPOLL_*` for use with [`Epoll::new`]. - pub struct CreateFlags: c::c_int { - /// `EPOLL_CLOEXEC` - const CLOEXEC = c::EPOLL_CLOEXEC; - } -} - -bitflags! { - /// `EPOLL*` for use with [`Epoll::add`]. - #[derive(Default)] - pub struct EventFlags: u32 { - /// `EPOLLIN` - const IN = c::EPOLLIN as u32; - - /// `EPOLLOUT` - const OUT = c::EPOLLOUT as u32; - - /// `EPOLLPRI` - const PRI = c::EPOLLPRI as u32; - - /// `EPOLLERR` - const ERR = c::EPOLLERR as u32; - - /// `EPOLLHUP` - const HUP = c::EPOLLHUP as u32; - - /// `EPOLLRDNORM` - const RDNORM = c::EPOLLRDNORM as u32; - - /// `EPOLLRDBAND` - const RDBAND = c::EPOLLRDBAND as u32; - - /// `EPOLLWRNORM` - const WRNORM = c::EPOLLWRNORM as u32; - - /// `EPOLLWRBAND` - const WRBAND = c::EPOLLWRBAND as u32; - - /// `EPOLLMSG` - const MSG = c::EPOLLMSG as u32; - - /// `EPOLLRDHUP` - const RDHUP = c::EPOLLRDHUP as u32; - - /// `EPOLLET` - const ET = c::EPOLLET as u32; - - /// `EPOLLONESHOT` - const ONESHOT = c::EPOLLONESHOT as u32; - - /// `EPOLLWAKEUP` - const WAKEUP = c::EPOLLWAKEUP as u32; - - /// `EPOLLEXCLUSIVE` - #[cfg(not(target_os = "android"))] - const EXCLUSIVE = c::EPOLLEXCLUSIVE as u32; - } -} - -/// `epoll_create1(flags)`—Creates a new `Epoll`. -/// -/// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file -/// descriptor from being implicitly passed across `exec` boundaries. -#[inline] -#[doc(alias = "epoll_create1")] -pub fn epoll_create(flags: CreateFlags) -> io::Result { - // SAFETY: We're calling `epoll_create1` via FFI and we know how it - // behaves. - unsafe { ret_owned_fd(c::epoll_create1(flags.bits())) } -} - -/// `epoll_ctl(self, EPOLL_CTL_ADD, data, event)`—Adds an element to an -/// `Epoll`. -/// -/// Note that if `epoll_del` is not called on the I/O source passed into -/// this function before the I/O source is `close`d, then the `epoll` will -/// act as if the I/O source is still registered with it. This can lead to -/// spurious events being returned from `epoll_wait`. If a file descriptor -/// is an `Arc`, then `epoll` can be thought to maintain -/// a `Weak` to the file descriptor. -#[doc(alias = "epoll_ctl")] -pub fn epoll_add( - epoll: impl AsFd, - source: impl AsFd, - data: u64, - event_flags: EventFlags, -) -> io::Result<()> { - // SAFETY: We're calling `epoll_ctl` via FFI and we know how it - // behaves. - unsafe { - let raw_fd = source.as_fd().as_raw_fd(); - ret(c::epoll_ctl( - epoll.as_fd().as_raw_fd(), - c::EPOLL_CTL_ADD, - raw_fd, - &mut c::epoll_event { - events: event_flags.bits(), - r#u64: data, - }, - )) - } -} - -/// `epoll_ctl(self, EPOLL_CTL_MOD, target, event)`—Modifies an element in -/// this `Epoll`. -/// -/// This sets the events of interest with `target` to `events`. -#[doc(alias = "epoll_ctl")] -pub fn epoll_mod( - epoll: impl AsFd, - source: impl AsFd, - data: u64, - event_flags: EventFlags, -) -> io::Result<()> { - let raw_fd = source.as_fd().as_raw_fd(); - - // SAFETY: We're calling `epoll_ctl` via FFI and we know how it - // behaves. - unsafe { - ret(c::epoll_ctl( - epoll.as_fd().as_raw_fd(), - c::EPOLL_CTL_MOD, - raw_fd, - &mut c::epoll_event { - events: event_flags.bits(), - r#u64: data, - }, - )) - } -} - -/// `epoll_ctl(self, EPOLL_CTL_DEL, target, NULL)`—Removes an element in -/// this `Epoll`. -#[doc(alias = "epoll_ctl")] -pub fn epoll_del(epoll: impl AsFd, source: impl AsFd) -> io::Result<()> { - // SAFETY: We're calling `epoll_ctl` via FFI and we know how it - // behaves. - unsafe { - let raw_fd = source.as_fd().as_raw_fd(); - ret(c::epoll_ctl( - epoll.as_fd().as_raw_fd(), - c::EPOLL_CTL_DEL, - raw_fd, - null_mut(), - )) - } -} - -/// `epoll_wait(self, events, timeout)`—Waits for registered events of -/// interest. -/// -/// For each event of interest, an element is written to `events`. On -/// success, this returns the number of written elements. -pub fn epoll_wait( - epoll: impl AsFd, - event_list: &mut EventVec, - timeout: c::c_int, -) -> io::Result<()> { - // SAFETY: We're calling `epoll_wait` via FFI and we know how it - // behaves. - unsafe { - event_list.events.set_len(0); - let nfds = ret_u32(c::epoll_wait( - epoll.as_fd().as_raw_fd(), - event_list.events.as_mut_ptr().cast::(), - event_list.events.capacity().try_into().unwrap_or(i32::MAX), - timeout, - ))?; - event_list.events.set_len(nfds as usize); - } - - Ok(()) -} - -/// An iterator over the `Event`s in an `EventVec`. -pub struct Iter<'a> { - iter: core::slice::Iter<'a, Event>, -} - -impl<'a> Iterator for Iter<'a> { - type Item = (EventFlags, u64); - - fn next(&mut self) -> Option { - // SAFETY: `self.context` is guaranteed to be valid because we hold - // `'context` for it. And we know this event is associated with this - // context because `wait` sets both. - self.iter - .next() - .map(|event| (event.event_flags, event.data)) - } -} - -/// A record of an event that occurred. -#[repr(C)] -#[cfg_attr( - any( - all( - target_arch = "x86", - not(target_env = "musl"), - not(target_os = "android"), - ), - target_arch = "x86_64", - ), - repr(packed) -)] -struct Event { - // Match the layout of `c::epoll_event`. We just use a `u64` instead of - // the full union. - event_flags: EventFlags, - data: u64, -} - -/// A vector of `Event`s, plus context for interpreting them. -pub struct EventVec { - events: Vec, -} - -impl EventVec { - /// Constructs an `EventVec` with memory for `capacity` `Event`s. - #[inline] - pub fn with_capacity(capacity: usize) -> Self { - Self { - events: Vec::with_capacity(capacity), - } - } - - /// Returns the current `Event` capacity of this `EventVec`. - #[inline] - pub fn capacity(&self) -> usize { - self.events.capacity() - } - - /// Reserves enough memory for at least `additional` more `Event`s. - #[inline] - pub fn reserve(&mut self, additional: usize) { - self.events.reserve(additional); - } - - /// Reserves enough memory for exactly `additional` more `Event`s. - #[inline] - pub fn reserve_exact(&mut self, additional: usize) { - self.events.reserve_exact(additional); - } - - /// Clears all the `Events` out of this `EventVec`. - #[inline] - pub fn clear(&mut self) { - self.events.clear(); - } - - /// Shrinks the capacity of this `EventVec` as much as possible. - #[inline] - pub fn shrink_to_fit(&mut self) { - self.events.shrink_to_fit(); - } - - /// Returns an iterator over the `Event`s in this `EventVec`. - #[inline] - pub fn iter(&self) -> Iter<'_> { - Iter { - iter: self.events.iter(), - } - } - - /// Returns the number of `Event`s logically contained in this `EventVec`. - #[inline] - pub fn len(&mut self) -> usize { - self.events.len() - } - - /// Tests whether this `EventVec` is logically empty. - #[inline] - pub fn is_empty(&mut self) -> bool { - self.events.is_empty() - } -} - -impl<'a> IntoIterator for &'a EventVec { - type IntoIter = Iter<'a>; - type Item = (EventFlags, u64); - - #[inline] - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} diff --git a/vendor/rustix/src/backend/libc/io/errno.rs b/vendor/rustix/src/backend/libc/io/errno.rs index 9e808c0b4..71fba49e9 100644 --- a/vendor/rustix/src/backend/libc/io/errno.rs +++ b/vendor/rustix/src/backend/libc/io/errno.rs @@ -3,7 +3,7 @@ //! This type holds an OS error code, which conceptually corresponds to an //! `errno` value. -use super::super::c; +use crate::backend::c; use libc_errno::errno; /// The error type for `rustix` APIs. diff --git a/vendor/rustix/src/backend/libc/io/io_slice.rs b/vendor/rustix/src/backend/libc/io/io_slice.rs deleted file mode 100644 index de1ef434c..000000000 --- a/vendor/rustix/src/backend/libc/io/io_slice.rs +++ /dev/null @@ -1,87 +0,0 @@ -//! The following is derived from Rust's -//! library/std/src/sys/unix/io.rs -//! dca3f1b786efd27be3b325ed1e01e247aa589c3b. - -#![allow(missing_docs)] - -use super::super::c; -use core::marker::PhantomData; -use core::slice; - -#[derive(Copy, Clone)] -#[repr(transparent)] -pub struct IoSlice<'a> { - vec: c::iovec, - _p: PhantomData<&'a [u8]>, -} - -impl<'a> IoSlice<'a> { - #[inline] - pub fn new(buf: &'a [u8]) -> IoSlice<'a> { - IoSlice { - vec: c::iovec { - iov_base: buf.as_ptr() as *mut u8 as *mut c::c_void, - iov_len: buf.len(), - }, - _p: PhantomData, - } - } - - #[inline] - pub fn advance(&mut self, n: usize) { - if self.vec.iov_len < n { - panic!("advancing IoSlice beyond its length"); - } - - unsafe { - self.vec.iov_len -= n; - self.vec.iov_base = self.vec.iov_base.add(n); - } - } - - #[inline] - pub fn as_slice(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) } - } -} - -#[repr(transparent)] -pub struct IoSliceMut<'a> { - vec: c::iovec, - _p: PhantomData<&'a mut [u8]>, -} - -impl<'a> IoSliceMut<'a> { - #[inline] - pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { - IoSliceMut { - vec: c::iovec { - iov_base: buf.as_mut_ptr() as *mut c::c_void, - iov_len: buf.len(), - }, - _p: PhantomData, - } - } - - #[inline] - pub fn advance(&mut self, n: usize) { - if self.vec.iov_len < n { - panic!("advancing IoSliceMut beyond its length"); - } - - unsafe { - self.vec.iov_len -= n; - self.vec.iov_base = self.vec.iov_base.add(n); - } - } - - #[inline] - pub fn as_slice(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) } - } - - #[inline] - pub fn as_mut_slice(&mut self) -> &mut [u8] { - unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) } - } -} diff --git a/vendor/rustix/src/backend/libc/io/mod.rs b/vendor/rustix/src/backend/libc/io/mod.rs index 1378adf3d..487388576 100644 --- a/vendor/rustix/src/backend/libc/io/mod.rs +++ b/vendor/rustix/src/backend/libc/io/mod.rs @@ -1,13 +1,6 @@ pub(crate) mod errno; #[cfg(not(windows))] -#[cfg(not(feature = "std"))] -pub(crate) mod io_slice; -pub(crate) mod poll_fd; -#[cfg(not(windows))] pub(crate) mod types; #[cfg_attr(windows, path = "windows_syscalls.rs")] pub(crate) mod syscalls; - -#[cfg(any(target_os = "android", target_os = "linux"))] -pub mod epoll; diff --git a/vendor/rustix/src/backend/libc/io/poll_fd.rs b/vendor/rustix/src/backend/libc/io/poll_fd.rs deleted file mode 100644 index a0568c60a..000000000 --- a/vendor/rustix/src/backend/libc/io/poll_fd.rs +++ /dev/null @@ -1,136 +0,0 @@ -use super::super::c; -use super::super::conv::borrowed_fd; -#[cfg(windows)] -use super::super::fd::RawFd; -use super::super::fd::{AsFd, AsRawFd, BorrowedFd, LibcFd}; -use bitflags::bitflags; -use core::marker::PhantomData; -#[cfg(windows)] -use std::fmt; - -bitflags! { - /// `POLL*` flags for use with [`poll`]. - /// - /// [`poll`]: crate::io::poll - pub struct PollFlags: c::c_short { - /// `POLLIN` - const IN = c::POLLIN; - /// `POLLPRI` - #[cfg(not(target_os = "wasi"))] - const PRI = c::POLLPRI; - /// `POLLOUT` - const OUT = c::POLLOUT; - /// `POLLRDNORM` - #[cfg(not(target_os = "redox"))] - const RDNORM = c::POLLRDNORM; - /// `POLLWRNORM` - #[cfg(not(target_os = "redox"))] - const WRNORM = c::POLLWRNORM; - /// `POLLRDBAND` - #[cfg(not(any(target_os = "redox", target_os = "wasi")))] - const RDBAND = c::POLLRDBAND; - /// `POLLWRBAND` - #[cfg(not(any(target_os = "redox", target_os = "wasi")))] - const WRBAND = c::POLLWRBAND; - /// `POLLERR` - const ERR = c::POLLERR; - /// `POLLHUP` - const HUP = c::POLLHUP; - /// `POLLNVAL` - const NVAL = c::POLLNVAL; - /// `POLLRDHUP` - #[cfg(all( - any(target_os = "android", target_os = "linux"), - not(any(target_arch = "sparc", target_arch = "sparc64"))), - )] - const RDHUP = c::POLLRDHUP; - } -} - -/// `struct pollfd`—File descriptor and flags for use with [`poll`]. -/// -/// [`poll`]: crate::io::poll -#[doc(alias = "pollfd")] -#[derive(Clone)] -#[cfg_attr(not(windows), derive(Debug))] -#[repr(transparent)] -pub struct PollFd<'fd> { - pollfd: c::pollfd, - _phantom: PhantomData>, -} - -#[cfg(windows)] -impl<'fd> fmt::Debug for PollFd<'fd> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_struct("pollfd") - .field("fd", &self.pollfd.fd) - .field("events", &self.pollfd.events) - .field("revents", &self.pollfd.revents) - .finish() - } -} - -impl<'fd> PollFd<'fd> { - /// Constructs a new `PollFd` holding `fd` and `events`. - #[inline] - pub fn new(fd: &'fd Fd, events: PollFlags) -> Self { - Self::from_borrowed_fd(fd.as_fd(), events) - } - - /// Sets the contained file descriptor to `fd`. - #[inline] - pub fn set_fd(&mut self, fd: &'fd Fd) { - self.pollfd.fd = fd.as_fd().as_raw_fd() as LibcFd; - } - - /// Clears the ready events. - #[inline] - pub fn clear_revents(&mut self) { - self.pollfd.revents = 0; - } - - /// Constructs a new `PollFd` holding `fd` and `events`. - /// - /// This is the same as `new`, but can be used to avoid borrowing the - /// `BorrowedFd`, which can be tricky in situations where the `BorrowedFd` - /// is a temporary. - #[inline] - pub fn from_borrowed_fd(fd: BorrowedFd<'fd>, events: PollFlags) -> Self { - Self { - pollfd: c::pollfd { - fd: borrowed_fd(fd), - events: events.bits(), - revents: 0, - }, - _phantom: PhantomData, - } - } - - /// Returns the ready events. - #[inline] - pub fn revents(&self) -> PollFlags { - // Use `unwrap()` here because in theory we know we know all the bits - // the OS might set here, but OS's have added extensions in the past. - PollFlags::from_bits(self.pollfd.revents).unwrap() - } -} - -#[cfg(not(windows))] -impl<'fd> AsFd for PollFd<'fd> { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - // SAFETY: Our constructors and `set_fd` require `pollfd.fd` to be - // valid for the `fd lifetime. - unsafe { BorrowedFd::borrow_raw(self.pollfd.fd) } - } -} - -#[cfg(windows)] -impl<'fd> io_lifetimes::AsSocket for PollFd<'fd> { - #[inline] - fn as_socket(&self) -> BorrowedFd<'_> { - // SAFETY: Our constructors and `set_fd` require `pollfd.fd` to be - // valid for the `fd lifetime. - unsafe { BorrowedFd::borrow_raw(self.pollfd.fd as RawFd) } - } -} diff --git a/vendor/rustix/src/backend/libc/io/syscalls.rs b/vendor/rustix/src/backend/libc/io/syscalls.rs index b74a63fa3..6ac1fa593 100644 --- a/vendor/rustix/src/backend/libc/io/syscalls.rs +++ b/vendor/rustix/src/backend/libc/io/syscalls.rs @@ -1,43 +1,17 @@ //! libc syscalls supporting `rustix::io`. -use super::super::c; -#[cfg(any(target_os = "android", target_os = "linux"))] -use super::super::conv::syscall_ret_owned_fd; -#[cfg(any( - target_os = "android", - all(target_os = "linux", not(target_env = "gnu")), -))] -use super::super::conv::syscall_ret_usize; -use super::super::conv::{borrowed_fd, ret, ret_c_int, ret_discarded_fd, ret_owned_fd, ret_usize}; -use super::super::offset::{libc_pread, libc_pwrite}; -#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "solaris")))] -use super::super::offset::{libc_preadv, libc_pwritev}; -#[cfg(all(target_os = "linux", target_env = "gnu"))] -use super::super::offset::{libc_preadv2, libc_pwritev2}; +use crate::backend::conv::{ + borrowed_fd, ret, ret_c_int, ret_discarded_fd, ret_owned_fd, ret_usize, +}; +use crate::backend::{c, MAX_IOV}; use crate::fd::{AsFd, BorrowedFd, OwnedFd, RawFd}; -#[cfg(bsd)] -use crate::io::kqueue::Event; -#[cfg(solarish)] -use crate::io::port::Event; #[cfg(not(any(target_os = "aix", target_os = "wasi")))] use crate::io::DupFlags; -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "illumos", - target_os = "linux" -))] -use crate::io::EventfdFlags; -#[cfg(not(any(apple, target_os = "aix", target_os = "haiku", target_os = "wasi")))] -use crate::io::PipeFlags; -use crate::io::{self, FdFlags, IoSlice, IoSliceMut, PollFd}; -#[cfg(any(target_os = "android", target_os = "linux"))] -use crate::io::{IoSliceRaw, ReadWriteFlags, SpliceFlags}; +#[cfg(linux_kernel)] +use crate::io::ReadWriteFlags; +use crate::io::{self, FdFlags, IoSlice, IoSliceMut}; use core::cmp::min; -use core::convert::TryInto; use core::mem::MaybeUninit; -#[cfg(any(target_os = "android", target_os = "linux"))] -use core::ptr; #[cfg(all(feature = "fs", feature = "net"))] use libc_errno::errno; @@ -68,7 +42,7 @@ pub(crate) fn pread(fd: BorrowedFd<'_>, buf: &mut [u8], offset: u64) -> io::Resu let offset = offset as i64; unsafe { - ret_usize(libc_pread( + ret_usize(c::pread( borrowed_fd(fd), buf.as_mut_ptr().cast(), len, @@ -83,14 +57,7 @@ pub(crate) fn pwrite(fd: BorrowedFd<'_>, buf: &[u8], offset: u64) -> io::Result< // Silently cast; we'll get `EINVAL` if the value is negative. let offset = offset as i64; - unsafe { - ret_usize(libc_pwrite( - borrowed_fd(fd), - buf.as_ptr().cast(), - len, - offset, - )) - } + unsafe { ret_usize(c::pwrite(borrowed_fd(fd), buf.as_ptr().cast(), len, offset)) } } pub(crate) fn readv(fd: BorrowedFd<'_>, bufs: &mut [IoSliceMut]) -> io::Result { @@ -98,7 +65,7 @@ pub(crate) fn readv(fd: BorrowedFd<'_>, bufs: &mut [IoSliceMut]) -> io::Result(), - min(bufs.len(), max_iov()) as c::c_int, + min(bufs.len(), MAX_IOV) as c::c_int, )) } } @@ -108,7 +75,7 @@ pub(crate) fn writev(fd: BorrowedFd<'_>, bufs: &[IoSlice]) -> io::Result ret_usize(c::writev( borrowed_fd(fd), bufs.as_ptr().cast::(), - min(bufs.len(), max_iov()) as c::c_int, + min(bufs.len(), MAX_IOV) as c::c_int, )) } } @@ -122,10 +89,10 @@ pub(crate) fn preadv( // Silently cast; we'll get `EINVAL` if the value is negative. let offset = offset as i64; unsafe { - ret_usize(libc_preadv( + ret_usize(c::preadv( borrowed_fd(fd), bufs.as_ptr().cast::(), - min(bufs.len(), max_iov()) as c::c_int, + min(bufs.len(), MAX_IOV) as c::c_int, offset, )) } @@ -136,42 +103,16 @@ pub(crate) fn pwritev(fd: BorrowedFd<'_>, bufs: &[IoSlice], offset: u64) -> io:: // Silently cast; we'll get `EINVAL` if the value is negative. let offset = offset as i64; unsafe { - ret_usize(libc_pwritev( - borrowed_fd(fd), - bufs.as_ptr().cast::(), - min(bufs.len(), max_iov()) as c::c_int, - offset, - )) - } -} - -#[cfg(all(target_os = "linux", target_env = "gnu"))] -pub(crate) fn preadv2( - fd: BorrowedFd<'_>, - bufs: &mut [IoSliceMut], - offset: u64, - flags: ReadWriteFlags, -) -> io::Result { - // Silently cast; we'll get `EINVAL` if the value is negative. - let offset = offset as i64; - unsafe { - ret_usize(libc_preadv2( + ret_usize(c::pwritev( borrowed_fd(fd), bufs.as_ptr().cast::(), - min(bufs.len(), max_iov()) as c::c_int, + min(bufs.len(), MAX_IOV) as c::c_int, offset, - flags.bits(), )) } } -/// At present, `libc` only has `preadv2` defined for glibc. On other -/// ABIs, use `c::syscall`. -#[cfg(any( - target_os = "android", - all(target_os = "linux", not(target_env = "gnu")), -))] -#[inline] +#[cfg(linux_kernel)] pub(crate) fn preadv2( fd: BorrowedFd<'_>, bufs: &mut [IoSliceMut], @@ -181,18 +122,17 @@ pub(crate) fn preadv2( // Silently cast; we'll get `EINVAL` if the value is negative. let offset = offset as i64; unsafe { - syscall_ret_usize(c::syscall( - c::SYS_preadv2, + ret_usize(c::preadv2( borrowed_fd(fd), bufs.as_ptr().cast::(), - min(bufs.len(), max_iov()) as c::c_int, + min(bufs.len(), MAX_IOV) as c::c_int, offset, - flags.bits(), + bitflags_bits!(flags), )) } } -#[cfg(all(target_os = "linux", target_env = "gnu"))] +#[cfg(linux_kernel)] pub(crate) fn pwritev2( fd: BorrowedFd<'_>, bufs: &[IoSlice], @@ -202,39 +142,12 @@ pub(crate) fn pwritev2( // Silently cast; we'll get `EINVAL` if the value is negative. let offset = offset as i64; unsafe { - ret_usize(libc_pwritev2( + ret_usize(c::pwritev2( borrowed_fd(fd), bufs.as_ptr().cast::(), - min(bufs.len(), max_iov()) as c::c_int, + min(bufs.len(), MAX_IOV) as c::c_int, offset, - flags.bits(), - )) - } -} - -/// At present, `libc` only has `pwritev2` defined for glibc. On other -/// ABIs, use `c::syscall`. -#[cfg(any( - target_os = "android", - all(target_os = "linux", not(target_env = "gnu")), -))] -#[inline] -pub(crate) fn pwritev2( - fd: BorrowedFd<'_>, - bufs: &[IoSlice], - offset: u64, - flags: ReadWriteFlags, -) -> io::Result { - // Silently cast; we'll get `EINVAL` if the value is negative. - let offset = offset as i64; - unsafe { - syscall_ret_usize(c::syscall( - c::SYS_pwritev2, - borrowed_fd(fd), - bufs.as_ptr().cast::(), - min(bufs.len(), max_iov()) as c::c_int, - offset, - flags.bits(), + bitflags_bits!(flags), )) } } @@ -255,72 +168,10 @@ const READ_LIMIT: usize = c::c_int::MAX as usize - 1; #[cfg(not(target_os = "macos"))] const READ_LIMIT: usize = c::ssize_t::MAX as usize; -#[cfg(bsd)] -const fn max_iov() -> usize { - c::IOV_MAX as usize -} - -#[cfg(any( - target_os = "android", - target_os = "emscripten", - target_os = "linux", - target_os = "nto" -))] -const fn max_iov() -> usize { - c::UIO_MAXIOV as usize -} - -#[cfg(not(any( - bsd, - target_os = "android", - target_os = "emscripten", - target_os = "linux", - target_os = "nto", - target_os = "horizon", -)))] -const fn max_iov() -> usize { - 16 // The minimum value required by POSIX. -} - pub(crate) unsafe fn close(raw_fd: RawFd) { let _ = c::close(raw_fd as c::c_int); } -#[cfg(any(target_os = "android", target_os = "linux"))] -pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result { - unsafe { syscall_ret_owned_fd(c::syscall(c::SYS_eventfd2, initval, flags.bits())) } -} - -#[cfg(any(target_os = "freebsd", target_os = "illumos"))] -pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result { - unsafe { ret_owned_fd(c::eventfd(initval, flags.bits())) } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -pub(crate) fn ioctl_blksszget(fd: BorrowedFd) -> io::Result { - let mut result = MaybeUninit::::uninit(); - unsafe { - ret(c::ioctl(borrowed_fd(fd), c::BLKSSZGET, result.as_mut_ptr()))?; - Ok(result.assume_init() as u32) - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -pub(crate) fn ioctl_blkpbszget(fd: BorrowedFd) -> io::Result { - let mut result = MaybeUninit::::uninit(); - unsafe { - ret(c::ioctl( - borrowed_fd(fd), - c::BLKPBSZGET, - result.as_mut_ptr(), - ))?; - Ok(result.assume_init() as u32) - } -} - -#[cfg(not(target_os = "redox"))] pub(crate) fn ioctl_fionread(fd: BorrowedFd<'_>) -> io::Result { let mut nread = MaybeUninit::::uninit(); unsafe { @@ -339,40 +190,6 @@ pub(crate) fn ioctl_fionbio(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> { } } -#[cfg(any(target_os = "android", target_os = "linux"))] -pub(crate) fn ioctl_ficlone(fd: BorrowedFd<'_>, src_fd: BorrowedFd<'_>) -> io::Result<()> { - // TODO: Enable this on mips and power once libc is updated. - #[cfg(not(any( - target_arch = "mips", - target_arch = "mips64", - target_arch = "powerpc", - target_arch = "powerpc64", - target_arch = "sparc", - target_arch = "sparc64" - )))] - unsafe { - ret(c::ioctl( - borrowed_fd(fd), - c::FICLONE as _, - borrowed_fd(src_fd), - )) - } - - #[cfg(any( - target_arch = "mips", - target_arch = "mips64", - target_arch = "powerpc", - target_arch = "powerpc64", - target_arch = "sparc", - target_arch = "sparc64" - ))] - { - let _ = fd; - let _ = src_fd; - Err(io::Errno::NOSYS) - } -} - #[cfg(not(any(target_os = "redox", target_os = "wasi")))] #[cfg(all(feature = "fs", feature = "net"))] pub(crate) fn is_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> { @@ -410,8 +227,7 @@ pub(crate) fn is_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> { if unsafe { c::send(borrowed_fd(fd), [].as_ptr(), 0, c::MSG_DONTWAIT) } == -1 { #[allow(unreachable_patterns)] // `EAGAIN` may equal `EWOULDBLOCK` match errno().0 { - c::EAGAIN | c::EWOULDBLOCK => (), - c::ENOTSOCK => (), + c::EAGAIN | c::EWOULDBLOCK | c::ENOTSOCK => (), c::EPIPE => write = false, err => return Err(io::Errno(err)), } @@ -427,7 +243,8 @@ pub(crate) fn is_read_write(_fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> { } pub(crate) fn fcntl_getfd(fd: BorrowedFd<'_>) -> io::Result { - unsafe { ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GETFD)).map(FdFlags::from_bits_truncate) } + let flags = unsafe { ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GETFD))? }; + Ok(FdFlags::from_bits_retain(bitcast!(flags))) } pub(crate) fn fcntl_setfd(fd: BorrowedFd<'_>, flags: FdFlags) -> io::Result<()> { @@ -463,7 +280,7 @@ pub(crate) fn dup3(fd: BorrowedFd<'_>, new: &mut OwnedFd, flags: DupFlags) -> io ret_discarded_fd(c::dup3( borrowed_fd(fd), borrowed_fd(new.as_fd()), - flags.bits(), + bitflags_bits!(flags), )) } } @@ -493,199 +310,3 @@ pub(crate) fn ioctl_fioclex(fd: BorrowedFd<'_>) -> io::Result<()> { )) } } - -#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] -pub(crate) fn ioctl_tiocexcl(fd: BorrowedFd) -> io::Result<()> { - unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCEXCL as _)) } -} - -#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] -pub(crate) fn ioctl_tiocnxcl(fd: BorrowedFd) -> io::Result<()> { - unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCNXCL as _)) } -} - -#[cfg(bsd)] -pub(crate) fn kqueue() -> io::Result { - unsafe { ret_owned_fd(c::kqueue()) } -} - -#[cfg(bsd)] -pub(crate) unsafe fn kevent( - kq: BorrowedFd<'_>, - changelist: &[Event], - eventlist: &mut [MaybeUninit], - timeout: Option<&c::timespec>, -) -> io::Result { - ret_c_int(c::kevent( - borrowed_fd(kq), - changelist.as_ptr() as *const _, - changelist - .len() - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?, - eventlist.as_mut_ptr() as *mut _, - eventlist - .len() - .try_into() - .map_err(|_| io::Errno::OVERFLOW)?, - timeout.map_or(core::ptr::null(), |t| t as *const _), - )) -} - -#[cfg(not(target_os = "wasi"))] -pub(crate) fn pipe() -> io::Result<(OwnedFd, OwnedFd)> { - unsafe { - let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit(); - ret(c::pipe(result.as_mut_ptr().cast::()))?; - let [p0, p1] = result.assume_init(); - Ok((p0, p1)) - } -} - -#[cfg(not(any(apple, target_os = "aix", target_os = "haiku", target_os = "wasi")))] -pub(crate) fn pipe_with(flags: PipeFlags) -> io::Result<(OwnedFd, OwnedFd)> { - unsafe { - let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit(); - ret(c::pipe2(result.as_mut_ptr().cast::(), flags.bits()))?; - let [p0, p1] = result.assume_init(); - Ok((p0, p1)) - } -} - -#[inline] -pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result { - let nfds = fds - .len() - .try_into() - .map_err(|_convert_err| io::Errno::INVAL)?; - - ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) }) - .map(|nready| nready as usize) -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -pub fn splice( - fd_in: BorrowedFd, - off_in: Option<&mut u64>, - fd_out: BorrowedFd, - off_out: Option<&mut u64>, - len: usize, - flags: SpliceFlags, -) -> io::Result { - let off_in = off_in - .map(|off| (off as *mut u64).cast()) - .unwrap_or(ptr::null_mut()); - - let off_out = off_out - .map(|off| (off as *mut u64).cast()) - .unwrap_or(ptr::null_mut()); - - unsafe { - ret_usize(c::splice( - borrowed_fd(fd_in), - off_in, - borrowed_fd(fd_out), - off_out, - len, - flags.bits(), - )) - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -pub unsafe fn vmsplice( - fd: BorrowedFd, - bufs: &[IoSliceRaw], - flags: SpliceFlags, -) -> io::Result { - ret_usize(c::vmsplice( - borrowed_fd(fd), - bufs.as_ptr().cast::(), - min(bufs.len(), max_iov()), - flags.bits(), - )) -} - -#[cfg(solarish)] -pub(crate) fn port_create() -> io::Result { - unsafe { ret_owned_fd(c::port_create()) } -} - -#[cfg(solarish)] -pub(crate) unsafe fn port_associate( - port: BorrowedFd<'_>, - source: c::c_int, - object: c::uintptr_t, - events: c::c_int, - user: *mut c::c_void, -) -> io::Result<()> { - ret(c::port_associate( - borrowed_fd(port), - source, - object, - events, - user, - )) -} - -#[cfg(solarish)] -pub(crate) unsafe fn port_dissociate( - port: BorrowedFd<'_>, - source: c::c_int, - object: c::uintptr_t, -) -> io::Result<()> { - ret(c::port_dissociate(borrowed_fd(port), source, object)) -} - -#[cfg(solarish)] -pub(crate) fn port_get( - port: BorrowedFd<'_>, - timeout: Option<&mut c::timespec>, -) -> io::Result { - let mut event = MaybeUninit::::uninit(); - let timeout = timeout.map_or(core::ptr::null_mut(), |t| t as *mut _); - - unsafe { - ret(c::port_get(borrowed_fd(port), event.as_mut_ptr(), timeout))?; - } - - // If we're done, initialize the event and return it. - Ok(Event(unsafe { event.assume_init() })) -} - -#[cfg(solarish)] -pub(crate) fn port_getn( - port: BorrowedFd<'_>, - timeout: Option<&mut c::timespec>, - events: &mut Vec, - mut nget: u32, -) -> io::Result<()> { - let timeout = timeout.map_or(core::ptr::null_mut(), |t| t as *mut _); - unsafe { - ret(c::port_getn( - borrowed_fd(port), - events.as_mut_ptr().cast(), - events.len().try_into().unwrap(), - &mut nget, - timeout, - ))?; - } - - // Update the vector length. - unsafe { - events.set_len(nget.try_into().unwrap()); - } - - Ok(()) -} - -#[cfg(solarish)] -pub(crate) fn port_send( - port: BorrowedFd<'_>, - events: c::c_int, - userdata: *mut c::c_void, -) -> io::Result<()> { - unsafe { ret(c::port_send(borrowed_fd(port), events, userdata)) } -} diff --git a/vendor/rustix/src/backend/libc/io/types.rs b/vendor/rustix/src/backend/libc/io/types.rs index 90a5e15b5..8743336f2 100644 --- a/vendor/rustix/src/backend/libc/io/types.rs +++ b/vendor/rustix/src/backend/libc/io/types.rs @@ -1,51 +1,38 @@ -use super::super::c; +use crate::backend::c; use bitflags::bitflags; -#[cfg(any(target_os = "android", target_os = "linux"))] -use core::marker::PhantomData; bitflags! { /// `FD_*` constants for use with [`fcntl_getfd`] and [`fcntl_setfd`]. /// /// [`fcntl_getfd`]: crate::io::fcntl_getfd /// [`fcntl_setfd`]: crate::io::fcntl_setfd - pub struct FdFlags: c::c_int { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct FdFlags: u32 { /// `FD_CLOEXEC` - const CLOEXEC = c::FD_CLOEXEC; + const CLOEXEC = bitcast!(c::FD_CLOEXEC); } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] bitflags! { /// `RWF_*` constants for use with [`preadv2`] and [`pwritev2`]. /// /// [`preadv2`]: crate::io::preadv2 /// [`pwritev2`]: crate::io::pwritev - pub struct ReadWriteFlags: c::c_int { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct ReadWriteFlags: u32 { /// `RWF_DSYNC` (since Linux 4.7) - const DSYNC = linux_raw_sys::general::RWF_DSYNC as c::c_int; + const DSYNC = linux_raw_sys::general::RWF_DSYNC; /// `RWF_HIPRI` (since Linux 4.6) - const HIPRI = linux_raw_sys::general::RWF_HIPRI as c::c_int; + const HIPRI = linux_raw_sys::general::RWF_HIPRI; /// `RWF_SYNC` (since Linux 4.7) - const SYNC = linux_raw_sys::general::RWF_SYNC as c::c_int; + const SYNC = linux_raw_sys::general::RWF_SYNC; /// `RWF_NOWAIT` (since Linux 4.14) - const NOWAIT = linux_raw_sys::general::RWF_NOWAIT as c::c_int; + const NOWAIT = linux_raw_sys::general::RWF_NOWAIT; /// `RWF_APPEND` (since Linux 4.16) - const APPEND = linux_raw_sys::general::RWF_APPEND as c::c_int; - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -bitflags! { - /// `SPLICE_F_*` constants for use with [`splice`] and [`vmsplice`]. - pub struct SpliceFlags: c::c_uint { - /// `SPLICE_F_MOVE` - const MOVE = c::SPLICE_F_MOVE; - /// `SPLICE_F_NONBLOCK` - const NONBLOCK = c::SPLICE_F_NONBLOCK; - /// `SPLICE_F_MORE` - const MORE = c::SPLICE_F_MORE; - /// `SPLICE_F_GIFT` - const GIFT = c::SPLICE_F_GIFT; + const APPEND = linux_raw_sys::general::RWF_APPEND; } } @@ -54,7 +41,9 @@ bitflags! { /// `O_*` constants for use with [`dup2`]. /// /// [`dup2`]: crate::io::dup2 - pub struct DupFlags: c::c_int { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct DupFlags: u32 { /// `O_CLOEXEC` #[cfg(not(any( apple, @@ -62,97 +51,6 @@ bitflags! { target_os = "android", target_os = "redox", )))] // Android 5.0 has dup3, but libc doesn't have bindings - const CLOEXEC = c::O_CLOEXEC; - } -} - -#[cfg(not(any(apple, target_os = "wasi")))] -bitflags! { - /// `O_*` constants for use with [`pipe_with`]. - /// - /// [`pipe_with`]: crate::io::pipe_with - pub struct PipeFlags: c::c_int { - /// `O_CLOEXEC` - const CLOEXEC = c::O_CLOEXEC; - /// `O_DIRECT` - #[cfg(not(any( - solarish, - target_os = "haiku", - target_os = "openbsd", - target_os = "redox", - )))] - const DIRECT = c::O_DIRECT; - /// `O_NONBLOCK` - const NONBLOCK = c::O_NONBLOCK; - } -} - -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "illumos", - target_os = "linux" -))] -bitflags! { - /// `EFD_*` flags for use with [`eventfd`]. - /// - /// [`eventfd`]: crate::io::eventfd - pub struct EventfdFlags: c::c_int { - /// `EFD_CLOEXEC` - const CLOEXEC = c::EFD_CLOEXEC; - /// `EFD_NONBLOCK` - const NONBLOCK = c::EFD_NONBLOCK; - /// `EFD_SEMAPHORE` - const SEMAPHORE = c::EFD_SEMAPHORE; - } -} - -/// `PIPE_BUF`—The maximum size of a write to a pipe guaranteed to be atomic. -#[cfg(not(any(solarish, target_os = "haiku", target_os = "redox", target_os = "wasi")))] -pub const PIPE_BUF: usize = c::PIPE_BUF; - -#[cfg(not(any(windows, target_os = "redox")))] -pub(crate) const AT_FDCWD: c::c_int = c::AT_FDCWD; -#[cfg(not(windows))] -pub(crate) const STDIN_FILENO: c::c_int = c::STDIN_FILENO; -#[cfg(not(windows))] -pub(crate) const STDOUT_FILENO: c::c_int = c::STDOUT_FILENO; -#[cfg(not(windows))] -pub(crate) const STDERR_FILENO: c::c_int = c::STDERR_FILENO; - -/// A buffer type used with `vmsplice`. -/// It is guaranteed to be ABI compatible with the iovec type on Unix platforms -/// and `WSABUF` on Windows. Unlike `IoSlice` and `IoSliceMut` it is -/// semantically like a raw pointer, and therefore can be shared or mutated as -/// needed. -#[cfg(any(target_os = "android", target_os = "linux"))] -#[repr(transparent)] -pub struct IoSliceRaw<'a> { - _buf: c::iovec, - _lifetime: PhantomData<&'a ()>, -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -impl<'a> IoSliceRaw<'a> { - /// Creates a new `IoSlice` wrapping a byte slice. - pub fn from_slice(buf: &'a [u8]) -> Self { - IoSliceRaw { - _buf: c::iovec { - iov_base: buf.as_ptr() as *mut u8 as *mut c::c_void, - iov_len: buf.len() as _, - }, - _lifetime: PhantomData, - } - } - - /// Creates a new `IoSlice` wrapping a mutable byte slice. - pub fn from_slice_mut(buf: &'a mut [u8]) -> Self { - IoSliceRaw { - _buf: c::iovec { - iov_base: buf.as_mut_ptr() as *mut c::c_void, - iov_len: buf.len() as _, - }, - _lifetime: PhantomData, - } + const CLOEXEC = bitcast!(c::O_CLOEXEC); } } diff --git a/vendor/rustix/src/backend/libc/io/windows_syscalls.rs b/vendor/rustix/src/backend/libc/io/windows_syscalls.rs index 4c6e86f94..c87a2a247 100644 --- a/vendor/rustix/src/backend/libc/io/windows_syscalls.rs +++ b/vendor/rustix/src/backend/libc/io/windows_syscalls.rs @@ -1,12 +1,10 @@ //! Windows system calls in the `io` module. -use super::super::c; -use super::super::conv::{borrowed_fd, ret, ret_c_int}; -use super::super::fd::LibcFd; +use crate::backend::c; +use crate::backend::conv::{borrowed_fd, ret}; +use crate::backend::fd::LibcFd; use crate::fd::{BorrowedFd, RawFd}; use crate::io; -use crate::io::PollFd; -use core::convert::TryInto; use core::mem::MaybeUninit; pub(crate) unsafe fn close(raw_fd: RawFd) { @@ -27,13 +25,3 @@ pub(crate) fn ioctl_fionbio(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> { ret(c::ioctl(borrowed_fd(fd), c::FIONBIO, &mut data)) } } - -pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result { - let nfds = fds - .len() - .try_into() - .map_err(|_convert_err| io::Errno::INVAL)?; - - ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) }) - .map(|nready| nready as usize) -} diff --git a/vendor/rustix/src/backend/libc/io_lifetimes.rs b/vendor/rustix/src/backend/libc/io_lifetimes.rs deleted file mode 100644 index 993365c0c..000000000 --- a/vendor/rustix/src/backend/libc/io_lifetimes.rs +++ /dev/null @@ -1,82 +0,0 @@ -//! `io_lifetimes` types for Windows assuming that Fd is Socket. -//! -//! We can make this assumption since `rustix` supports only `rustix::net` on -//! Windows. - -pub use io_lifetimes::{BorrowedSocket as BorrowedFd, OwnedSocket as OwnedFd}; -#[cfg(feature = "std")] -pub use std::os::windows::io::RawSocket as RawFd; -pub(crate) use windows_sys::Win32::Networking::WinSock::SOCKET as LibcFd; - -// Re-export the `Socket` traits so that users can implement them. -pub use io_lifetimes::AsSocket; - -/// A version of [`AsRawFd`] for use with Winsock2 API. -/// -/// [`AsRawFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.AsRawFd.html -pub trait AsRawFd { - /// A version of [`as_raw_fd`] for use with Winsock2 API. - /// - /// [`as_raw_fd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#tymethod.as_raw_fd - fn as_raw_fd(&self) -> RawFd; -} -#[cfg(feature = "std")] -impl AsRawFd for T { - #[inline] - fn as_raw_fd(&self) -> RawFd { - self.as_raw_socket() - } -} - -/// A version of [`IntoRawFd`] for use with Winsock2 API. -/// -/// [`IntoRawFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.IntoRawFd.html -pub trait IntoRawFd { - /// A version of [`into_raw_fd`] for use with Winsock2 API. - /// - /// [`into_raw_fd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#tymethod.into_raw_fd - fn into_raw_fd(self) -> RawFd; -} -#[cfg(feature = "std")] -impl IntoRawFd for T { - #[inline] - fn into_raw_fd(self) -> RawFd { - self.into_raw_socket() - } -} - -/// A version of [`FromRawFd`] for use with Winsock2 API. -/// -/// [`FromRawFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html -pub trait FromRawFd { - /// A version of [`from_raw_fd`] for use with Winsock2 API. - /// - /// # Safety - /// - /// See the [safety requirements] for [`from_raw_fd`]. - /// - /// [`from_raw_fd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#tymethod.from_raw_fd - /// [safety requirements]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#safety - unsafe fn from_raw_fd(raw_fd: RawFd) -> Self; -} -#[cfg(feature = "std")] -impl FromRawFd for T { - #[inline] - unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { - Self::from_raw_socket(raw_fd) - } -} - -/// A version of [`AsFd`] for use with Winsock2 API. -/// -/// [`AsFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.AsFd.html -pub trait AsFd { - /// An `as_fd` function for Winsock2, where a `Fd` is a `Socket`. - fn as_fd(&self) -> BorrowedFd; -} -impl AsFd for T { - #[inline] - fn as_fd(&self) -> BorrowedFd { - self.as_socket() - } -} diff --git a/vendor/rustix/src/backend/libc/io_uring/syscalls.rs b/vendor/rustix/src/backend/libc/io_uring/syscalls.rs index 17d3eb10c..8e8182401 100644 --- a/vendor/rustix/src/backend/libc/io_uring/syscalls.rs +++ b/vendor/rustix/src/backend/libc/io_uring/syscalls.rs @@ -1,21 +1,20 @@ //! libc syscalls supporting `rustix::io_uring`. -use super::super::c; -use super::super::conv::{borrowed_fd, syscall_ret_owned_fd, syscall_ret_u32}; +use crate::backend::c; +use crate::backend::conv::{borrowed_fd, ret_owned_fd, ret_u32}; use crate::fd::{BorrowedFd, OwnedFd}; use crate::io; use crate::io_uring::{io_uring_params, IoringEnterFlags, IoringRegisterOp}; -use linux_raw_sys::general::{__NR_io_uring_enter, __NR_io_uring_register, __NR_io_uring_setup}; #[inline] pub(crate) fn io_uring_setup(entries: u32, params: &mut io_uring_params) -> io::Result { - unsafe { - syscall_ret_owned_fd(c::syscall( - __NR_io_uring_setup as _, - entries as usize, - params, - )) + syscall! { + fn io_uring_setup( + entries: u32, + params: *mut io_uring_params + ) via SYS_io_uring_setup -> c::c_int } + unsafe { ret_owned_fd(io_uring_setup(entries, params)) } } #[inline] @@ -25,12 +24,19 @@ pub(crate) unsafe fn io_uring_register( arg: *const c::c_void, nr_args: u32, ) -> io::Result { - syscall_ret_u32(c::syscall( - __NR_io_uring_register as _, - borrowed_fd(fd), - opcode as u32 as usize, + syscall! { + fn io_uring_register( + fd: c::c_uint, + opcode: c::c_uint, + arg: *const c::c_void, + nr_args: c::c_uint + ) via SYS_io_uring_register -> c::c_int + } + ret_u32(io_uring_register( + borrowed_fd(fd) as _, + opcode as u32, arg, - nr_args as usize, + nr_args, )) } @@ -43,12 +49,21 @@ pub(crate) unsafe fn io_uring_enter( arg: *const c::c_void, size: usize, ) -> io::Result { - syscall_ret_u32(c::syscall( - __NR_io_uring_enter as _, - borrowed_fd(fd), - to_submit as usize, - min_complete as usize, - flags.bits() as usize, + syscall! { + fn io_uring_enter2( + fd: c::c_uint, + to_submit: c::c_uint, + min_complete: c::c_uint, + flags: c::c_uint, + arg: *const c::c_void, + size: usize + ) via SYS_io_uring_enter -> c::c_int + } + ret_u32(io_uring_enter2( + borrowed_fd(fd) as _, + to_submit, + min_complete, + bitflags_bits!(flags), arg, size, )) diff --git a/vendor/rustix/src/backend/libc/mm/syscalls.rs b/vendor/rustix/src/backend/libc/mm/syscalls.rs index 16636f1b9..4b23a58b7 100644 --- a/vendor/rustix/src/backend/libc/mm/syscalls.rs +++ b/vendor/rustix/src/backend/libc/mm/syscalls.rs @@ -1,19 +1,18 @@ //! libc syscalls supporting `rustix::mm`. -use super::super::c; -#[cfg(any(target_os = "android", target_os = "linux"))] -use super::super::conv::syscall_ret_owned_fd; -use super::super::conv::{borrowed_fd, no_fd, ret}; -use super::super::offset::libc_mmap; #[cfg(not(target_os = "redox"))] use super::types::Advice; #[cfg(any(target_os = "emscripten", target_os = "linux"))] use super::types::MremapFlags; use super::types::{MapFlags, MprotectFlags, MsyncFlags, ProtFlags}; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] use super::types::{MlockFlags, UserfaultfdFlags}; +use crate::backend::c; +#[cfg(linux_kernel)] +use crate::backend::conv::ret_owned_fd; +use crate::backend::conv::{borrowed_fd, no_fd, ret}; use crate::fd::BorrowedFd; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] use crate::fd::OwnedFd; use crate::io; @@ -52,7 +51,7 @@ pub(crate) fn madvise(addr: *mut c::c_void, len: usize, advice: Advice) -> io::R } pub(crate) unsafe fn msync(addr: *mut c::c_void, len: usize, flags: MsyncFlags) -> io::Result<()> { - let err = c::msync(addr, len, flags.bits()); + let err = c::msync(addr, len, bitflags_bits!(flags)); // `msync` returns its error status rather than using `errno`. if err == 0 { @@ -74,11 +73,11 @@ pub(crate) unsafe fn mmap( fd: BorrowedFd<'_>, offset: u64, ) -> io::Result<*mut c::c_void> { - let res = libc_mmap( + let res = c::mmap( ptr, len, - prot.bits(), - flags.bits(), + bitflags_bits!(prot), + bitflags_bits!(flags), borrowed_fd(fd), offset as i64, ); @@ -99,11 +98,11 @@ pub(crate) unsafe fn mmap_anonymous( prot: ProtFlags, flags: MapFlags, ) -> io::Result<*mut c::c_void> { - let res = libc_mmap( + let res = c::mmap( ptr, len, - prot.bits(), - flags.bits() | c::MAP_ANONYMOUS, + bitflags_bits!(prot), + bitflags_bits!(flags | MapFlags::from_bits_retain(bitcast!(c::MAP_ANONYMOUS))), no_fd(), 0, ); @@ -119,7 +118,7 @@ pub(crate) unsafe fn mprotect( len: usize, flags: MprotectFlags, ) -> io::Result<()> { - ret(c::mprotect(ptr, len, flags.bits())) + ret(c::mprotect(ptr, len, bitflags_bits!(flags))) } pub(crate) unsafe fn munmap(ptr: *mut c::c_void, len: usize) -> io::Result<()> { @@ -137,7 +136,7 @@ pub(crate) unsafe fn mremap( new_size: usize, flags: MremapFlags, ) -> io::Result<*mut c::c_void> { - let res = c::mremap(old_address, old_size, new_size, flags.bits()); + let res = c::mremap(old_address, old_size, new_size, bitflags_bits!(flags)); if res == c::MAP_FAILED { Err(io::Errno::last_os_error()) } else { @@ -162,7 +161,7 @@ pub(crate) unsafe fn mremap_fixed( old_address, old_size, new_size, - flags.bits() | c::MAP_FIXED, + bitflags_bits!(flags | MremapFlags::from_bits_retain(bitcast!(c::MAP_FIXED))), new_address, ); if res == c::MAP_FAILED { @@ -185,7 +184,7 @@ pub(crate) unsafe fn mlock(addr: *mut c::c_void, length: usize) -> io::Result<() /// /// `mlock_with` operates on raw pointers and may round out to the nearest page /// boundaries. -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] pub(crate) unsafe fn mlock_with( addr: *mut c::c_void, @@ -200,7 +199,7 @@ pub(crate) unsafe fn mlock_with( ) via SYS_mlock2 -> c::c_int } - ret(mlock2(addr, length, flags.bits())) + ret(mlock2(addr, length, bitflags_bits!(flags))) } /// # Safety @@ -212,7 +211,12 @@ pub(crate) unsafe fn munlock(addr: *mut c::c_void, length: usize) -> io::Result< ret(c::munlock(addr, length)) } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub(crate) unsafe fn userfaultfd(flags: UserfaultfdFlags) -> io::Result { - syscall_ret_owned_fd(c::syscall(c::SYS_userfaultfd, flags.bits())) + syscall! { + fn userfaultfd( + flags: c::c_int + ) via SYS_userfaultfd -> c::c_int + } + ret_owned_fd(userfaultfd(bitflags_bits!(flags))) } diff --git a/vendor/rustix/src/backend/libc/mm/types.rs b/vendor/rustix/src/backend/libc/mm/types.rs index 798fda86b..e4fecfccd 100644 --- a/vendor/rustix/src/backend/libc/mm/types.rs +++ b/vendor/rustix/src/backend/libc/mm/types.rs @@ -1,4 +1,4 @@ -use super::super::c; +use crate::backend::c; use bitflags::bitflags; bitflags! { @@ -7,13 +7,15 @@ bitflags! { /// For `PROT_NONE`, use `ProtFlags::empty()`. /// /// [`mmap`]: crate::io::mmap - pub struct ProtFlags: c::c_int { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct ProtFlags: u32 { /// `PROT_READ` - const READ = c::PROT_READ; + const READ = bitcast!(c::PROT_READ); /// `PROT_WRITE` - const WRITE = c::PROT_WRITE; + const WRITE = bitcast!(c::PROT_WRITE); /// `PROT_EXEC` - const EXEC = c::PROT_EXEC; + const EXEC = bitcast!(c::PROT_EXEC); } } @@ -23,19 +25,21 @@ bitflags! { /// For `PROT_NONE`, use `MprotectFlags::empty()`. /// /// [`mprotect`]: crate::io::mprotect - pub struct MprotectFlags: c::c_int { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct MprotectFlags: u32 { /// `PROT_READ` - const READ = c::PROT_READ; + const READ = bitcast!(c::PROT_READ); /// `PROT_WRITE` - const WRITE = c::PROT_WRITE; + const WRITE = bitcast!(c::PROT_WRITE); /// `PROT_EXEC` - const EXEC = c::PROT_EXEC; + const EXEC = bitcast!(c::PROT_EXEC); /// `PROT_GROWSUP` - #[cfg(any(target_os = "android", target_os = "linux"))] - const GROWSUP = c::PROT_GROWSUP; + #[cfg(linux_kernel)] + const GROWSUP = bitcast!(c::PROT_GROWSUP); /// `PROT_GROWSDOWN` - #[cfg(any(target_os = "android", target_os = "linux"))] - const GROWSDOWN = c::PROT_GROWSDOWN; + #[cfg(linux_kernel)] + const GROWSDOWN = bitcast!(c::PROT_GROWSDOWN); } } @@ -46,9 +50,11 @@ bitflags! { /// /// [`mmap`]: crate::io::mmap /// [`mmap_anonymous`]: crates::io::mmap_anonymous - pub struct MapFlags: c::c_int { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct MapFlags: u32 { /// `MAP_SHARED` - const SHARED = c::MAP_SHARED; + const SHARED = bitcast!(c::MAP_SHARED); /// `MAP_SHARED_VALIDATE` #[cfg(not(any( bsd, @@ -59,9 +65,9 @@ bitflags! { target_os = "haiku", target_os = "redox", )))] - const SHARED_VALIDATE = c::MAP_SHARED_VALIDATE; + const SHARED_VALIDATE = bitcast!(c::MAP_SHARED_VALIDATE); /// `MAP_PRIVATE` - const PRIVATE = c::MAP_PRIVATE; + const PRIVATE = bitcast!(c::MAP_PRIVATE); /// `MAP_DENYWRITE` #[cfg(not(any( bsd, @@ -69,9 +75,9 @@ bitflags! { target_os = "haiku", target_os = "redox", )))] - const DENYWRITE = c::MAP_DENYWRITE; + const DENYWRITE = bitcast!(c::MAP_DENYWRITE); /// `MAP_FIXED` - const FIXED = c::MAP_FIXED; + const FIXED = bitcast!(c::MAP_FIXED); /// `MAP_FIXED_NOREPLACE` #[cfg(not(any( bsd, @@ -82,7 +88,7 @@ bitflags! { target_os = "haiku", target_os = "redox", )))] - const FIXED_NOREPLACE = c::MAP_FIXED_NOREPLACE; + const FIXED_NOREPLACE = bitcast!(c::MAP_FIXED_NOREPLACE); /// `MAP_GROWSDOWN` #[cfg(not(any( bsd, @@ -90,7 +96,7 @@ bitflags! { target_os = "haiku", target_os = "redox", )))] - const GROWSDOWN = c::MAP_GROWSDOWN; + const GROWSDOWN = bitcast!(c::MAP_GROWSDOWN); /// `MAP_HUGETLB` #[cfg(not(any( bsd, @@ -98,7 +104,7 @@ bitflags! { target_os = "haiku", target_os = "redox", )))] - const HUGETLB = c::MAP_HUGETLB; + const HUGETLB = bitcast!(c::MAP_HUGETLB); /// `MAP_HUGE_2MB` #[cfg(not(any( bsd, @@ -109,7 +115,7 @@ bitflags! { target_os = "haiku", target_os = "redox", )))] - const HUGE_2MB = c::MAP_HUGE_2MB; + const HUGE_2MB = bitcast!(c::MAP_HUGE_2MB); /// `MAP_HUGE_1GB` #[cfg(not(any( bsd, @@ -120,7 +126,7 @@ bitflags! { target_os = "haiku", target_os = "redox", )))] - const HUGE_1GB = c::MAP_HUGE_1GB; + const HUGE_1GB = bitcast!(c::MAP_HUGE_1GB); /// `MAP_LOCKED` #[cfg(not(any( bsd, @@ -128,16 +134,16 @@ bitflags! { target_os = "haiku", target_os = "redox", )))] - const LOCKED = c::MAP_LOCKED; + const LOCKED = bitcast!(c::MAP_LOCKED); /// `MAP_NOCORE` #[cfg(freebsdlike)] - const NOCORE = c::MAP_NOCORE; + const NOCORE = bitcast!(c::MAP_NOCORE); /// `MAP_NORESERVE` #[cfg(not(any(freebsdlike, target_os = "redox")))] - const NORESERVE = c::MAP_NORESERVE; + const NORESERVE = bitcast!(c::MAP_NORESERVE); /// `MAP_NOSYNC` #[cfg(freebsdlike)] - const NOSYNC = c::MAP_NOSYNC; + const NOSYNC = bitcast!(c::MAP_NOSYNC); /// `MAP_POPULATE` #[cfg(not(any( bsd, @@ -145,7 +151,7 @@ bitflags! { target_os = "haiku", target_os = "redox", )))] - const POPULATE = c::MAP_POPULATE; + const POPULATE = bitcast!(c::MAP_POPULATE); /// `MAP_STACK` #[cfg(not(any( apple, @@ -155,10 +161,10 @@ bitflags! { target_os = "netbsd", target_os = "redox", )))] - const STACK = c::MAP_STACK; + const STACK = bitcast!(c::MAP_STACK); /// `MAP_PREFAULT_READ` #[cfg(target_os = "freebsd")] - const PREFAULT_READ = c::MAP_PREFAULT_READ; + const PREFAULT_READ = bitcast!(c::MAP_PREFAULT_READ); /// `MAP_SYNC` #[cfg(not(any( bsd, @@ -169,14 +175,14 @@ bitflags! { target_os = "haiku", target_os = "redox", all( - any(target_os = "android", target_os = "linux"), + linux_kernel, any(target_arch = "mips", target_arch = "mips64"), ) )))] - const SYNC = c::MAP_SYNC; + const SYNC = bitcast!(c::MAP_SYNC); /// `MAP_UNINITIALIZED` #[cfg(any())] - const UNINITIALIZED = c::MAP_UNINITIALIZED; + const UNINITIALIZED = bitcast!(c::MAP_UNINITIALIZED); } } @@ -188,9 +194,11 @@ bitflags! { /// /// [`mremap`]: crate::io::mremap /// [`mremap_fixed`]: crate::io::mremap_fixed - pub struct MremapFlags: i32 { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct MremapFlags: u32 { /// `MREMAP_MAYMOVE` - const MAYMOVE = c::MREMAP_MAYMOVE; + const MAYMOVE = bitcast!(c::MREMAP_MAYMOVE); } } @@ -198,27 +206,31 @@ bitflags! { /// `MS_*` flags for use with [`msync`]. /// /// [`msync`]: crate::io::msync - pub struct MsyncFlags: i32 { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct MsyncFlags: u32 { /// `MS_SYNC`—Requests an update and waits for it to complete. - const SYNC = c::MS_SYNC; + const SYNC = bitcast!(c::MS_SYNC); /// `MS_ASYNC`—Specifies that an update be scheduled, but the call /// returns immediately. - const ASYNC = c::MS_ASYNC; + const ASYNC = bitcast!(c::MS_ASYNC); /// `MS_INVALIDATE`—Asks to invalidate other mappings of the same /// file (so that they can be updated with the fresh values just /// written). - const INVALIDATE = c::MS_INVALIDATE; + const INVALIDATE = bitcast!(c::MS_INVALIDATE); } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] bitflags! { /// `MLOCK_*` flags for use with [`mlock_with`]. /// /// [`mlock_with`]: crate::io::mlock_with - pub struct MlockFlags: i32 { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct MlockFlags: u32 { /// `MLOCK_ONFAULT` - const ONFAULT = c::MLOCK_ONFAULT as _; + const ONFAULT = bitcast!(c::MLOCK_ONFAULT); } } @@ -227,122 +239,116 @@ bitflags! { /// [`madvise`]: crate::mm::madvise #[cfg(not(target_os = "redox"))] #[derive(Debug, Copy, Clone, Eq, PartialEq)] -#[repr(i32)] +#[repr(u32)] #[non_exhaustive] pub enum Advice { /// `POSIX_MADV_NORMAL` #[cfg(not(any(target_os = "android", target_os = "haiku")))] - Normal = c::POSIX_MADV_NORMAL, + Normal = bitcast!(c::POSIX_MADV_NORMAL), /// `POSIX_MADV_NORMAL` #[cfg(any(target_os = "android", target_os = "haiku"))] - Normal = c::MADV_NORMAL, + Normal = bitcast!(c::MADV_NORMAL), /// `POSIX_MADV_SEQUENTIAL` #[cfg(not(any(target_os = "android", target_os = "haiku")))] - Sequential = c::POSIX_MADV_SEQUENTIAL, + Sequential = bitcast!(c::POSIX_MADV_SEQUENTIAL), /// `POSIX_MADV_SEQUENTIAL` #[cfg(any(target_os = "android", target_os = "haiku"))] - Sequential = c::MADV_SEQUENTIAL, + Sequential = bitcast!(c::MADV_SEQUENTIAL), /// `POSIX_MADV_RANDOM` #[cfg(not(any(target_os = "android", target_os = "haiku")))] - Random = c::POSIX_MADV_RANDOM, + Random = bitcast!(c::POSIX_MADV_RANDOM), /// `POSIX_MADV_RANDOM` #[cfg(any(target_os = "android", target_os = "haiku"))] - Random = c::MADV_RANDOM, + Random = bitcast!(c::MADV_RANDOM), /// `POSIX_MADV_WILLNEED` #[cfg(not(any(target_os = "android", target_os = "haiku")))] - WillNeed = c::POSIX_MADV_WILLNEED, + WillNeed = bitcast!(c::POSIX_MADV_WILLNEED), /// `POSIX_MADV_WILLNEED` #[cfg(any(target_os = "android", target_os = "haiku"))] - WillNeed = c::MADV_WILLNEED, + WillNeed = bitcast!(c::MADV_WILLNEED), /// `POSIX_MADV_DONTNEED` #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "haiku")))] - DontNeed = c::POSIX_MADV_DONTNEED, + DontNeed = bitcast!(c::POSIX_MADV_DONTNEED), /// `POSIX_MADV_DONTNEED` #[cfg(any(target_os = "android", target_os = "haiku"))] - DontNeed = i32::MAX - 1, + DontNeed = bitcast!(i32::MAX - 1), /// `MADV_DONTNEED` // `MADV_DONTNEED` has the same value as `POSIX_MADV_DONTNEED`. We don't // have a separate `posix_madvise` from `madvise`, so we expose a special // value which we special-case. #[cfg(target_os = "linux")] - LinuxDontNeed = i32::MAX, + LinuxDontNeed = bitcast!(i32::MAX), /// `MADV_DONTNEED` #[cfg(target_os = "android")] - LinuxDontNeed = c::MADV_DONTNEED, + LinuxDontNeed = bitcast!(c::MADV_DONTNEED), /// `MADV_FREE` - #[cfg(any(target_os = "android", target_os = "linux"))] - LinuxFree = c::MADV_FREE, + #[cfg(linux_kernel)] + LinuxFree = bitcast!(c::MADV_FREE), /// `MADV_REMOVE` - #[cfg(any(target_os = "android", target_os = "linux"))] - LinuxRemove = c::MADV_REMOVE, + #[cfg(linux_kernel)] + LinuxRemove = bitcast!(c::MADV_REMOVE), /// `MADV_DONTFORK` - #[cfg(any(target_os = "android", target_os = "linux"))] - LinuxDontFork = c::MADV_DONTFORK, + #[cfg(linux_kernel)] + LinuxDontFork = bitcast!(c::MADV_DONTFORK), /// `MADV_DOFORK` - #[cfg(any(target_os = "android", target_os = "linux"))] - LinuxDoFork = c::MADV_DOFORK, + #[cfg(linux_kernel)] + LinuxDoFork = bitcast!(c::MADV_DOFORK), /// `MADV_HWPOISON` - #[cfg(any(target_os = "android", target_os = "linux"))] - LinuxHwPoison = c::MADV_HWPOISON, + #[cfg(linux_kernel)] + LinuxHwPoison = bitcast!(c::MADV_HWPOISON), /// `MADV_SOFT_OFFLINE` - #[cfg(all( - any(target_os = "android", target_os = "linux"), - not(any(target_arch = "mips", target_arch = "mips64")), - ))] - LinuxSoftOffline = c::MADV_SOFT_OFFLINE, + #[cfg(all(linux_kernel, not(any(target_arch = "mips", target_arch = "mips64"))))] + LinuxSoftOffline = bitcast!(c::MADV_SOFT_OFFLINE), /// `MADV_MERGEABLE` - #[cfg(any(target_os = "android", target_os = "linux"))] - LinuxMergeable = c::MADV_MERGEABLE, + #[cfg(linux_kernel)] + LinuxMergeable = bitcast!(c::MADV_MERGEABLE), /// `MADV_UNMERGEABLE` - #[cfg(any(target_os = "android", target_os = "linux"))] - LinuxUnmergeable = c::MADV_UNMERGEABLE, + #[cfg(linux_kernel)] + LinuxUnmergeable = bitcast!(c::MADV_UNMERGEABLE), /// `MADV_HUGEPAGE` (since Linux 2.6.38) - #[cfg(any(target_os = "android", target_os = "linux"))] - LinuxHugepage = c::MADV_HUGEPAGE, + #[cfg(linux_kernel)] + LinuxHugepage = bitcast!(c::MADV_HUGEPAGE), /// `MADV_NOHUGEPAGE` (since Linux 2.6.38) - #[cfg(any(target_os = "android", target_os = "linux"))] - LinuxNoHugepage = c::MADV_NOHUGEPAGE, + #[cfg(linux_kernel)] + LinuxNoHugepage = bitcast!(c::MADV_NOHUGEPAGE), /// `MADV_DONTDUMP` (since Linux 3.4) - #[cfg(any(target_os = "android", target_os = "linux"))] - LinuxDontDump = c::MADV_DONTDUMP, + #[cfg(linux_kernel)] + LinuxDontDump = bitcast!(c::MADV_DONTDUMP), /// `MADV_DODUMP` (since Linux 3.4) - #[cfg(any(target_os = "android", target_os = "linux"))] - LinuxDoDump = c::MADV_DODUMP, + #[cfg(linux_kernel)] + LinuxDoDump = bitcast!(c::MADV_DODUMP), /// `MADV_WIPEONFORK` (since Linux 4.14) - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg(feature = "mm")] - LinuxWipeOnFork = linux_raw_sys::general::MADV_WIPEONFORK as i32, + #[cfg(linux_kernel)] + LinuxWipeOnFork = bitcast!(c::MADV_WIPEONFORK), /// `MADV_KEEPONFORK` (since Linux 4.14) - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg(feature = "mm")] - LinuxKeepOnFork = linux_raw_sys::general::MADV_KEEPONFORK as i32, + #[cfg(linux_kernel)] + LinuxKeepOnFork = bitcast!(c::MADV_KEEPONFORK), /// `MADV_COLD` (since Linux 5.4) - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg(feature = "mm")] - LinuxCold = linux_raw_sys::general::MADV_COLD as i32, + #[cfg(linux_kernel)] + LinuxCold = bitcast!(c::MADV_COLD), /// `MADV_PAGEOUT` (since Linux 5.4) - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg(feature = "mm")] - LinuxPageOut = linux_raw_sys::general::MADV_PAGEOUT as i32, + #[cfg(linux_kernel)] + LinuxPageOut = bitcast!(c::MADV_PAGEOUT), /// `MADV_POPULATE_READ` (since Linux 5.14) - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg(feature = "mm")] - LinuxPopulateRead = linux_raw_sys::general::MADV_POPULATE_READ as i32, + #[cfg(linux_kernel)] + LinuxPopulateRead = bitcast!(c::MADV_POPULATE_READ), /// `MADV_POPULATE_WRITE` (since Linux 5.14) - #[cfg(any(target_os = "android", target_os = "linux"))] - #[cfg(feature = "mm")] - LinuxPopulateWrite = linux_raw_sys::general::MADV_POPULATE_WRITE as i32, + #[cfg(linux_kernel)] + LinuxPopulateWrite = bitcast!(c::MADV_POPULATE_WRITE), + /// `MADV_DONTNEED_LOCKED` (since Linux 5.18) + #[cfg(linux_kernel)] + LinuxDontneedLocked = bitcast!(c::MADV_DONTNEED_LOCKED), } #[cfg(target_os = "emscripten")] @@ -352,15 +358,17 @@ impl Advice { pub const DontNeed: Self = Self::Normal; } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] bitflags! { /// `O_*` flags for use with [`userfaultfd`]. /// /// [`userfaultfd`]: crate::io::userfaultfd - pub struct UserfaultfdFlags: c::c_int { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct UserfaultfdFlags: u32 { /// `O_CLOEXEC` - const CLOEXEC = c::O_CLOEXEC; + const CLOEXEC = bitcast!(c::O_CLOEXEC); /// `O_NONBLOCK` - const NONBLOCK = c::O_NONBLOCK; + const NONBLOCK = bitcast!(c::O_NONBLOCK); } } diff --git a/vendor/rustix/src/backend/libc/mod.rs b/vendor/rustix/src/backend/libc/mod.rs index f3433903d..357f99484 100644 --- a/vendor/rustix/src/backend/libc/mod.rs +++ b/vendor/rustix/src/backend/libc/mod.rs @@ -12,35 +12,89 @@ #![allow(clippy::useless_conversion)] mod conv; -mod offset; #[cfg(windows)] -mod io_lifetimes; -#[cfg(not(windows))] -#[cfg(not(feature = "std"))] pub(crate) mod fd { - pub(crate) use super::c::c_int as LibcFd; - pub use crate::io::fd::*; -} -#[cfg(windows)] -pub(crate) mod fd { - pub use super::io_lifetimes::*; + pub use crate::maybe_polyfill::os::windows::io::{ + AsRawSocket, AsSocket, BorrowedSocket as BorrowedFd, FromRawSocket, IntoRawSocket, + OwnedSocket as OwnedFd, RawSocket as RawFd, + }; + pub(crate) use windows_sys::Win32::Networking::WinSock::SOCKET as LibcFd; + + /// A version of [`AsRawFd`] for use with Winsock2 API. + /// + /// [`AsRawFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.AsRawFd.html + pub trait AsRawFd { + /// A version of [`as_raw_fd`] for use with Winsock2 API. + /// + /// [`as_raw_fd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#tymethod.as_raw_fd + fn as_raw_fd(&self) -> RawFd; + } + impl AsRawFd for T { + #[inline] + fn as_raw_fd(&self) -> RawFd { + self.as_raw_socket() + } + } + + /// A version of [`IntoRawFd`] for use with Winsock2 API. + /// + /// [`IntoRawFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.IntoRawFd.html + pub trait IntoRawFd { + /// A version of [`into_raw_fd`] for use with Winsock2 API. + /// + /// [`into_raw_fd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#tymethod.into_raw_fd + fn into_raw_fd(self) -> RawFd; + } + impl IntoRawFd for T { + #[inline] + fn into_raw_fd(self) -> RawFd { + self.into_raw_socket() + } + } + + /// A version of [`FromRawFd`] for use with Winsock2 API. + /// + /// [`FromRawFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html + pub trait FromRawFd { + /// A version of [`from_raw_fd`] for use with Winsock2 API. + /// + /// # Safety + /// + /// See the [safety requirements] for [`from_raw_fd`]. + /// + /// [`from_raw_fd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#tymethod.from_raw_fd + /// [safety requirements]: https://doc.rust-lang.org/stable/std/os/fd/trait.FromRawFd.html#safety + unsafe fn from_raw_fd(raw_fd: RawFd) -> Self; + } + impl FromRawFd for T { + #[inline] + unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { + Self::from_raw_socket(raw_fd) + } + } + + /// A version of [`AsFd`] for use with Winsock2 API. + /// + /// [`AsFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.AsFd.html + pub trait AsFd { + /// An `as_fd` function for Winsock2, where a `Fd` is a `Socket`. + fn as_fd(&self) -> BorrowedFd; + } + impl AsFd for T { + #[inline] + fn as_fd(&self) -> BorrowedFd { + self.as_socket() + } + } } #[cfg(not(windows))] -#[cfg(feature = "std")] pub(crate) mod fd { - pub use io_lifetimes::*; - - #[cfg(target_os = "wasi")] - #[allow(unused_imports)] - pub(crate) use super::c::c_int as LibcFd; - #[cfg(unix)] + pub use crate::maybe_polyfill::os::fd::{ + AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd, + }; #[allow(unused_imports)] - pub(crate) use std::os::unix::io::RawFd as LibcFd; - #[cfg(unix)] - pub use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; - #[cfg(target_os = "wasi")] - pub use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; + pub(crate) use RawFd as LibcFd; } // On Windows we emulate selected libc-compatible interfaces. On non-Windows, @@ -48,11 +102,13 @@ pub(crate) mod fd { #[cfg_attr(windows, path = "winsock_c.rs")] pub(crate) mod c; +#[cfg(feature = "event")] +pub(crate) mod event; #[cfg(not(windows))] #[cfg(feature = "fs")] pub(crate) mod fs; pub(crate) mod io; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[cfg(feature = "io_uring")] pub(crate) mod io_uring; #[cfg(not(any(windows, target_os = "wasi")))] @@ -70,17 +126,30 @@ pub(crate) mod net; ))] pub(crate) mod param; #[cfg(not(windows))] +#[cfg(feature = "pipe")] +pub(crate) mod pipe; +#[cfg(not(windows))] +#[cfg(feature = "process")] pub(crate) mod process; #[cfg(not(windows))] +#[cfg(not(target_os = "wasi"))] +#[cfg(feature = "pty")] +pub(crate) mod pty; +#[cfg(not(windows))] #[cfg(feature = "rand")] pub(crate) mod rand; #[cfg(not(windows))] +#[cfg(not(target_os = "wasi"))] +#[cfg(feature = "system")] +pub(crate) mod system; +#[cfg(not(windows))] #[cfg(feature = "termios")] pub(crate) mod termios; #[cfg(not(windows))] #[cfg(feature = "thread")] pub(crate) mod thread; #[cfg(not(windows))] +#[cfg(feature = "time")] pub(crate) mod time; /// If the host libc is glibc, return `true` if it is less than version 2.25. @@ -93,11 +162,38 @@ pub(crate) mod time; #[cfg(all(unix, target_env = "gnu"))] pub(crate) fn if_glibc_is_less_than_2_25() -> bool { // This is also defined inside `weak_or_syscall!` in - // backend/libc/rand/syscalls.rs, but it's not convenient to re-export the weak - // symbol from that macro, so we duplicate it at a small cost here. + // backend/libc/rand/syscalls.rs, but it's not convenient to re-export the + // weak symbol from that macro, so we duplicate it at a small cost here. weak! { fn getrandom(*mut c::c_void, c::size_t, c::c_uint) -> c::ssize_t } // glibc 2.25 has `getrandom`, which is how we satisfy the API contract of // this function. But, there are likely other libc versions which have it. getrandom.get().is_none() } + +// Private modules used by multiple public modules. +#[cfg(any(feature = "procfs", feature = "process", feature = "runtime"))] +#[cfg(not(any(windows, target_os = "wasi")))] +pub(crate) mod pid; +#[cfg(any(feature = "process", feature = "thread"))] +#[cfg(linux_kernel)] +pub(crate) mod prctl; +#[cfg(any(feature = "fs", feature = "thread", feature = "process"))] +#[cfg(not(any(windows, target_os = "wasi")))] +pub(crate) mod ugid; + +#[cfg(bsd)] +const MAX_IOV: usize = c::IOV_MAX as usize; + +#[cfg(any(linux_kernel, target_os = "emscripten", target_os = "nto"))] +const MAX_IOV: usize = c::UIO_MAXIOV as usize; + +#[cfg(not(any( + bsd, + linux_kernel, + windows, + target_os = "emscripten", + target_os = "nto", + target_os = "horizon", +)))] +const MAX_IOV: usize = 16; // The minimum value required by POSIX. diff --git a/vendor/rustix/src/backend/libc/net/addr.rs b/vendor/rustix/src/backend/libc/net/addr.rs index d00a48626..bf7d239de 100644 --- a/vendor/rustix/src/backend/libc/net/addr.rs +++ b/vendor/rustix/src/backend/libc/net/addr.rs @@ -1,18 +1,16 @@ -//! IPv4, IPv6, and Socket addresses. +//! Socket address utilities. -use super::super::c; +use crate::backend::c; #[cfg(unix)] -use crate::ffi::CStr; -#[cfg(unix)] -use crate::io; -#[cfg(unix)] -use crate::path; -#[cfg(not(windows))] -use core::convert::TryInto; -#[cfg(unix)] -use core::fmt; -#[cfg(unix)] -use core::slice; +use { + crate::ffi::CStr, + crate::io, + crate::path, + core::cmp::Ordering, + core::fmt, + core::hash::{Hash, Hasher}, + core::slice, +}; /// `struct sockaddr_un` #[cfg(unix)] @@ -56,14 +54,14 @@ impl SocketAddrUnix { } /// Construct a new abstract Unix-domain address from a byte slice. - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_kernel)] #[inline] pub fn new_abstract_name(name: &[u8]) -> io::Result { let mut unix = Self::init(); if 1 + name.len() > unix.sun_path.len() { return Err(io::Errno::NAMETOOLONG); } - unix.sun_path[0] = b'\0' as c::c_char; + unix.sun_path[0] = 0; for (i, b) in name.iter().enumerate() { unix.sun_path[1 + i] = *b as c::c_char; } @@ -94,11 +92,12 @@ impl SocketAddrUnix { #[inline] pub fn path(&self) -> Option<&CStr> { let len = self.len(); - if len != 0 && self.unix.sun_path[0] != b'\0' as c::c_char { + if len != 0 && self.unix.sun_path[0] != 0 { let end = len as usize - offsetof_sun_path(); let bytes = &self.unix.sun_path[..end]; - // SAFETY: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`. And - // `from_bytes_with_nul_unchecked` since the string is NUL-terminated. + // SAFETY: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`. + // And `from_bytes_with_nul_unchecked` since the string is + // NUL-terminated. unsafe { Some(CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts( bytes.as_ptr().cast(), @@ -111,11 +110,11 @@ impl SocketAddrUnix { } /// For an abstract address, return the identifier. - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_kernel)] #[inline] pub fn abstract_name(&self) -> Option<&[u8]> { let len = self.len(); - if len != 0 && self.unix.sun_path[0] == b'\0' as c::c_char { + if len != 0 && self.unix.sun_path[0] == 0 { let end = len as usize - offsetof_sun_path(); let bytes = &self.unix.sun_path[1..end]; // SAFETY: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`. @@ -159,7 +158,7 @@ impl Eq for SocketAddrUnix {} #[cfg(unix)] impl PartialOrd for SocketAddrUnix { #[inline] - fn partial_cmp(&self, other: &Self) -> Option { + fn partial_cmp(&self, other: &Self) -> Option { let self_len = self.len() - offsetof_sun_path(); let other_len = other.len() - offsetof_sun_path(); self.unix.sun_path[..self_len].partial_cmp(&other.unix.sun_path[..other_len]) @@ -169,7 +168,7 @@ impl PartialOrd for SocketAddrUnix { #[cfg(unix)] impl Ord for SocketAddrUnix { #[inline] - fn cmp(&self, other: &Self) -> core::cmp::Ordering { + fn cmp(&self, other: &Self) -> Ordering { let self_len = self.len() - offsetof_sun_path(); let other_len = other.len() - offsetof_sun_path(); self.unix.sun_path[..self_len].cmp(&other.unix.sun_path[..other_len]) @@ -177,9 +176,9 @@ impl Ord for SocketAddrUnix { } #[cfg(unix)] -impl core::hash::Hash for SocketAddrUnix { +impl Hash for SocketAddrUnix { #[inline] - fn hash(&self, state: &mut H) { + fn hash(&self, state: &mut H) { let self_len = self.len() - offsetof_sun_path(); self.unix.sun_path[..self_len].hash(state) } @@ -191,7 +190,7 @@ impl fmt::Debug for SocketAddrUnix { if let Some(path) = self.path() { path.fmt(fmt) } else { - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_kernel)] if let Some(name) = self.abstract_name() { return name.fmt(fmt); } diff --git a/vendor/rustix/src/backend/libc/net/ext.rs b/vendor/rustix/src/backend/libc/net/ext.rs index f4ad316dd..4b2d10756 100644 --- a/vendor/rustix/src/backend/libc/net/ext.rs +++ b/vendor/rustix/src/backend/libc/net/ext.rs @@ -1,4 +1,4 @@ -use super::super::c; +use crate::backend::c; /// The windows `sockaddr_in6` type is a union with accessor functions which /// are not `const fn`. Define our own layout-compatible version so that we @@ -19,7 +19,6 @@ pub(crate) const fn in_addr_s_addr(addr: c::in_addr) -> u32 { addr.s_addr } -#[cfg(not(feature = "std"))] #[cfg(windows)] #[inline] pub(crate) const fn in_addr_s_addr(addr: c::in_addr) -> u32 { @@ -27,103 +26,52 @@ pub(crate) const fn in_addr_s_addr(addr: c::in_addr) -> u32 { unsafe { core::mem::transmute(addr) } } -// TODO: With Rust 1.55, we can use the above `in_addr_s_addr` definition that -// uses a const-fn transmute. -#[cfg(feature = "std")] -#[cfg(windows)] -#[inline] -pub(crate) fn in_addr_s_addr(addr: c::in_addr) -> u32 { - // This should be `*addr.S_un.S_addr()`, except that isn't a `const fn`. - unsafe { core::mem::transmute(addr) } -} - #[cfg(not(windows))] #[inline] pub(crate) const fn in_addr_new(s_addr: u32) -> c::in_addr { c::in_addr { s_addr } } -#[cfg(not(feature = "std"))] #[cfg(windows)] #[inline] pub(crate) const fn in_addr_new(s_addr: u32) -> c::in_addr { unsafe { core::mem::transmute(s_addr) } } -// TODO: With Rust 1.55, we can use the above `in_addr_new` definition that -// uses a const-fn transmute. -#[cfg(feature = "std")] -#[cfg(windows)] -#[inline] -pub(crate) fn in_addr_new(s_addr: u32) -> c::in_addr { - unsafe { core::mem::transmute(s_addr) } -} - #[cfg(not(windows))] #[inline] pub(crate) const fn in6_addr_s6_addr(addr: c::in6_addr) -> [u8; 16] { addr.s6_addr } -#[cfg(not(feature = "std"))] #[cfg(windows)] #[inline] pub(crate) const fn in6_addr_s6_addr(addr: c::in6_addr) -> [u8; 16] { unsafe { core::mem::transmute(addr) } } -// TODO: With Rust 1.55, we can use the above `in6_addr_s6_addr` definition -// that uses a const-fn transmute. -#[cfg(feature = "std")] -#[cfg(windows)] -#[inline] -pub(crate) fn in6_addr_s6_addr(addr: c::in6_addr) -> [u8; 16] { - unsafe { core::mem::transmute(addr) } -} - #[cfg(not(windows))] #[inline] pub(crate) const fn in6_addr_new(s6_addr: [u8; 16]) -> c::in6_addr { c::in6_addr { s6_addr } } -#[cfg(not(feature = "std"))] #[cfg(windows)] #[inline] pub(crate) const fn in6_addr_new(s6_addr: [u8; 16]) -> c::in6_addr { unsafe { core::mem::transmute(s6_addr) } } -// TODO: With Rust 1.55, we can use the above `in6_addr_new` definition that -// uses a const-fn transmute. -#[cfg(feature = "std")] -#[cfg(windows)] -#[inline] -pub(crate) fn in6_addr_new(s6_addr: [u8; 16]) -> c::in6_addr { - unsafe { core::mem::transmute(s6_addr) } -} - #[cfg(not(windows))] #[inline] -pub(crate) const fn sockaddr_in6_sin6_scope_id(addr: c::sockaddr_in6) -> u32 { - addr.sin6_scope_id -} - -#[cfg(not(feature = "std"))] -#[cfg(windows)] -#[inline] -pub(crate) const fn sockaddr_in6_sin6_scope_id(addr: c::sockaddr_in6) -> u32 { - let addr: sockaddr_in6 = unsafe { core::mem::transmute(addr) }; +pub(crate) const fn sockaddr_in6_sin6_scope_id(addr: &c::sockaddr_in6) -> u32 { addr.sin6_scope_id } -// TODO: With Rust 1.55, we can use the above `sockaddr_in6_sin6_scope_id` -// definition that uses a const-fn transmute. -#[cfg(feature = "std")] #[cfg(windows)] #[inline] -pub(crate) fn sockaddr_in6_sin6_scope_id(addr: c::sockaddr_in6) -> u32 { - let addr: sockaddr_in6 = unsafe { core::mem::transmute(addr) }; +pub(crate) const fn sockaddr_in6_sin6_scope_id(addr: &c::sockaddr_in6) -> u32 { + let addr: &sockaddr_in6 = unsafe { core::mem::transmute(addr) }; addr.sin6_scope_id } @@ -150,7 +98,6 @@ pub(crate) const fn sockaddr_in6_new( } } -#[cfg(not(feature = "std"))] #[cfg(windows)] #[inline] pub(crate) const fn sockaddr_in6_new( @@ -169,25 +116,3 @@ pub(crate) const fn sockaddr_in6_new( }; unsafe { core::mem::transmute(addr) } } - -// TODO: With Rust 1.55, we can use the above `sockaddr_in6_new` definition -// that uses a const-fn transmute. -#[cfg(feature = "std")] -#[cfg(windows)] -#[inline] -pub(crate) fn sockaddr_in6_new( - sin6_family: u16, - sin6_port: u16, - sin6_flowinfo: u32, - sin6_addr: c::in6_addr, - sin6_scope_id: u32, -) -> c::sockaddr_in6 { - let addr = sockaddr_in6 { - sin6_family, - sin6_port, - sin6_flowinfo, - sin6_addr, - sin6_scope_id, - }; - unsafe { core::mem::transmute(addr) } -} diff --git a/vendor/rustix/src/backend/libc/net/mod.rs b/vendor/rustix/src/backend/libc/net/mod.rs index f7196ae4f..1b68f1b26 100644 --- a/vendor/rustix/src/backend/libc/net/mod.rs +++ b/vendor/rustix/src/backend/libc/net/mod.rs @@ -1,7 +1,8 @@ pub(crate) mod addr; pub(crate) mod ext; +#[cfg(not(any(target_os = "redox", target_os = "wasi", windows)))] +pub(crate) mod msghdr; pub(crate) mod read_sockaddr; pub(crate) mod send_recv; pub(crate) mod syscalls; -pub(crate) mod types; pub(crate) mod write_sockaddr; diff --git a/vendor/rustix/src/backend/libc/net/msghdr.rs b/vendor/rustix/src/backend/libc/net/msghdr.rs new file mode 100644 index 000000000..e3f873747 --- /dev/null +++ b/vendor/rustix/src/backend/libc/net/msghdr.rs @@ -0,0 +1,125 @@ +//! Utilities for dealing with message headers. +//! +//! These take closures rather than returning a `c::msghdr` directly because +//! the message headers may reference stack-local data. + +use crate::backend::c; +use crate::backend::conv::{msg_control_len, msg_iov_len}; +use crate::backend::net::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6}; + +use crate::io::{self, IoSlice, IoSliceMut}; +use crate::net::{RecvAncillaryBuffer, SendAncillaryBuffer, SocketAddrV4, SocketAddrV6}; +use crate::utils::as_ptr; + +use core::mem::{size_of, zeroed, MaybeUninit}; + +/// Create a message header intended to receive a datagram. +pub(crate) fn with_recv_msghdr( + name: &mut MaybeUninit, + iov: &mut [IoSliceMut<'_>], + control: &mut RecvAncillaryBuffer<'_>, + f: impl FnOnce(&mut c::msghdr) -> io::Result, +) -> io::Result { + control.clear(); + + let namelen = size_of::() as c::socklen_t; + let mut msghdr = { + let mut h: c::msghdr = unsafe { zeroed() }; + h.msg_name = name.as_mut_ptr().cast(); + h.msg_namelen = namelen; + h.msg_iov = iov.as_mut_ptr().cast(); + h.msg_iovlen = msg_iov_len(iov.len()); + h.msg_control = control.as_control_ptr().cast(); + h.msg_controllen = msg_control_len(control.control_len()); + h + }; + + let res = f(&mut msghdr); + + // Reset the control length. + if res.is_ok() { + unsafe { + control.set_control_len(msghdr.msg_controllen.try_into().unwrap_or(usize::MAX)); + } + } + + res +} + +/// Create a message header intended to send without an address. +pub(crate) fn with_noaddr_msghdr( + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + f: impl FnOnce(c::msghdr) -> R, +) -> R { + f({ + let mut h: c::msghdr = unsafe { zeroed() }; + h.msg_iov = iov.as_ptr() as _; + h.msg_iovlen = msg_iov_len(iov.len()); + h.msg_control = control.as_control_ptr().cast(); + h.msg_controllen = msg_control_len(control.control_len()); + h + }) +} + +/// Create a message header intended to send with an IPv4 address. +pub(crate) fn with_v4_msghdr( + addr: &SocketAddrV4, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + f: impl FnOnce(c::msghdr) -> R, +) -> R { + let encoded = unsafe { encode_sockaddr_v4(addr) }; + + f({ + let mut h: c::msghdr = unsafe { zeroed() }; + h.msg_name = as_ptr(&encoded) as _; + h.msg_namelen = size_of::() as _; + h.msg_iov = iov.as_ptr() as _; + h.msg_iovlen = msg_iov_len(iov.len()); + h.msg_control = control.as_control_ptr().cast(); + h.msg_controllen = msg_control_len(control.control_len()); + h + }) +} + +/// Create a message header intended to send with an IPv6 address. +pub(crate) fn with_v6_msghdr( + addr: &SocketAddrV6, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + f: impl FnOnce(c::msghdr) -> R, +) -> R { + let encoded = unsafe { encode_sockaddr_v6(addr) }; + + f({ + let mut h: c::msghdr = unsafe { zeroed() }; + h.msg_name = as_ptr(&encoded) as _; + h.msg_namelen = size_of::() as _; + h.msg_iov = iov.as_ptr() as _; + h.msg_iovlen = msg_iov_len(iov.len()); + h.msg_control = control.as_control_ptr().cast(); + h.msg_controllen = msg_control_len(control.control_len()); + h + }) +} + +/// Create a message header intended to send with a Unix address. +#[cfg(all(unix, not(target_os = "redox")))] +pub(crate) fn with_unix_msghdr( + addr: &crate::net::SocketAddrUnix, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + f: impl FnOnce(c::msghdr) -> R, +) -> R { + f({ + let mut h: c::msghdr = unsafe { zeroed() }; + h.msg_name = as_ptr(addr) as _; + h.msg_namelen = addr.addr_len(); + h.msg_iov = iov.as_ptr() as _; + h.msg_iovlen = msg_iov_len(iov.len()); + h.msg_control = control.as_control_ptr().cast(); + h.msg_controllen = msg_control_len(control.control_len()); + h + }) +} diff --git a/vendor/rustix/src/backend/libc/net/read_sockaddr.rs b/vendor/rustix/src/backend/libc/net/read_sockaddr.rs index 575102c27..c3b23e8c2 100644 --- a/vendor/rustix/src/backend/libc/net/read_sockaddr.rs +++ b/vendor/rustix/src/backend/libc/net/read_sockaddr.rs @@ -1,13 +1,14 @@ -use super::super::c; +//! The BSD sockets API requires us to read the `ss_family` field before +//! we can interpret the rest of a `sockaddr` produced by the kernel. + #[cfg(unix)] use super::addr::SocketAddrUnix; use super::ext::{in6_addr_s6_addr, in_addr_s_addr, sockaddr_in6_sin6_scope_id}; +use crate::backend::c; #[cfg(not(windows))] use crate::ffi::CStr; use crate::io; use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrV4, SocketAddrV6}; -#[cfg(not(windows))] -use alloc::vec::Vec; use core::mem::size_of; // This must match the header of `sockaddr`. @@ -46,6 +47,11 @@ pub(crate) unsafe fn initialize_family_to_unspec(storage: *mut c::sockaddr_stora (*storage.cast::()).ss_family = c::AF_UNSPEC as _; } +/// Read a socket address encoded in a platform-specific format. +/// +/// # Safety +/// +/// `storage` must point to valid socket address storage. pub(crate) unsafe fn read_sockaddr( storage: *const c::sockaddr_storage, len: usize, @@ -61,7 +67,7 @@ pub(crate) unsafe fn read_sockaddr( if len < size_of::() { return Err(io::Errno::INVAL); } - let decode = *storage.cast::(); + let decode = &*storage.cast::(); Ok(SocketAddrAny::V4(SocketAddrV4::new( Ipv4Addr::from(u32::from_be(in_addr_s_addr(decode.sin_addr))), u16::from_be(decode.sin_port), @@ -71,7 +77,7 @@ pub(crate) unsafe fn read_sockaddr( if len < size_of::() { return Err(io::Errno::INVAL); } - let decode = *storage.cast::(); + let decode = &*storage.cast::(); #[cfg(not(windows))] let s6_addr = decode.sin6_addr.s6_addr; #[cfg(windows)] @@ -93,20 +99,40 @@ pub(crate) unsafe fn read_sockaddr( return Err(io::Errno::INVAL); } if len == offsetof_sun_path { - Ok(SocketAddrAny::Unix(SocketAddrUnix::new(&[][..]).unwrap())) + SocketAddrUnix::new(&[][..]).map(SocketAddrAny::Unix) } else { - let decode = *storage.cast::(); + let decode = &*storage.cast::(); + + // On Linux check for Linux's [abstract namespace]. + // + // [abstract namespace]: https://man7.org/linux/man-pages/man7/unix.7.html + #[cfg(linux_kernel)] + if decode.sun_path[0] == 0 { + return SocketAddrUnix::new_abstract_name(core::mem::transmute::< + &[c::c_char], + &[u8], + >( + &decode.sun_path[1..len - offsetof_sun_path], + )) + .map(SocketAddrAny::Unix); + } + + // Otherwise we expect a NUL-terminated filesystem path. // Trim off unused bytes from the end of `path_bytes`. let path_bytes = if cfg!(target_os = "freebsd") { // FreeBSD sometimes sets the length to longer than the length // of the NUL-terminated string. Find the NUL and truncate the // string accordingly. - &decode.sun_path[..decode.sun_path.iter().position(|b| *b == 0).unwrap()] + &decode.sun_path[..decode + .sun_path + .iter() + .position(|b| *b == 0) + .ok_or(io::Errno::INVAL)?] } else { // Otherwise, use the provided length. let provided_len = len - 1 - offsetof_sun_path; - if decode.sun_path[provided_len] != b'\0' as c::c_char { + if decode.sun_path[provided_len] != 0 { return Err(io::Errno::INVAL); } debug_assert_eq!( @@ -116,10 +142,8 @@ pub(crate) unsafe fn read_sockaddr( &decode.sun_path[..provided_len] }; - Ok(SocketAddrAny::Unix( - SocketAddrUnix::new(path_bytes.iter().map(|c| *c as u8).collect::>()) - .unwrap(), - )) + SocketAddrUnix::new(core::mem::transmute::<&[c::c_char], &[u8]>(path_bytes)) + .map(SocketAddrAny::Unix) } } _ => Err(io::Errno::INVAL), @@ -164,7 +188,7 @@ unsafe fn inner_read_sockaddr_os( match family { c::AF_INET => { assert!(len >= size_of::()); - let decode = *storage.cast::(); + let decode = &*storage.cast::(); SocketAddrAny::V4(SocketAddrV4::new( Ipv4Addr::from(u32::from_be(in_addr_s_addr(decode.sin_addr))), u16::from_be(decode.sin_port), @@ -172,7 +196,7 @@ unsafe fn inner_read_sockaddr_os( } c::AF_INET6 => { assert!(len >= size_of::()); - let decode = *storage.cast::(); + let decode = &*storage.cast::(); SocketAddrAny::V6(SocketAddrV6::new( Ipv6Addr::from(in6_addr_s6_addr(decode.sin6_addr)), u16::from_be(decode.sin6_port), @@ -186,11 +210,26 @@ unsafe fn inner_read_sockaddr_os( if len == offsetof_sun_path { SocketAddrAny::Unix(SocketAddrUnix::new(&[][..]).unwrap()) } else { - let decode = *storage.cast::(); - assert_eq!( - decode.sun_path[len - 1 - offsetof_sun_path], - b'\0' as c::c_char - ); + let decode = &*storage.cast::(); + + // On Linux check for Linux's [abstract namespace]. + // + // [abstract namespace]: https://man7.org/linux/man-pages/man7/unix.7.html + #[cfg(linux_kernel)] + if decode.sun_path[0] == 0 { + return SocketAddrAny::Unix( + SocketAddrUnix::new_abstract_name(core::mem::transmute::< + &[c::c_char], + &[u8], + >( + &decode.sun_path[1..len - offsetof_sun_path], + )) + .unwrap(), + ); + } + + // Otherwise we expect a NUL-terminated filesystem path. + assert_eq!(decode.sun_path[len - 1 - offsetof_sun_path], 0); let path_bytes = &decode.sun_path[..len - 1 - offsetof_sun_path]; // FreeBSD sometimes sets the length to longer than the length @@ -200,7 +239,7 @@ unsafe fn inner_read_sockaddr_os( let path_bytes = &path_bytes[..path_bytes.iter().position(|b| *b == 0).unwrap()]; SocketAddrAny::Unix( - SocketAddrUnix::new(path_bytes.iter().map(|c| *c as u8).collect::>()) + SocketAddrUnix::new(core::mem::transmute::<&[c::c_char], &[u8]>(path_bytes)) .unwrap(), ) } diff --git a/vendor/rustix/src/backend/libc/net/send_recv.rs b/vendor/rustix/src/backend/libc/net/send_recv.rs index 49c6f2c22..e91017e97 100644 --- a/vendor/rustix/src/backend/libc/net/send_recv.rs +++ b/vendor/rustix/src/backend/libc/net/send_recv.rs @@ -1,4 +1,4 @@ -use super::super::c; +use crate::backend::c; use bitflags::bitflags; bitflags! { @@ -6,7 +6,9 @@ bitflags! { /// /// [`send`]: crate::net::send /// [`sendto`]: crate::net::sendto - pub struct SendFlags: i32 { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct SendFlags: u32 { /// `MSG_CONFIRM` #[cfg(not(any( bsd, @@ -14,15 +16,15 @@ bitflags! { windows, target_os = "haiku", )))] - const CONFIRM = c::MSG_CONFIRM; + const CONFIRM = bitcast!(c::MSG_CONFIRM); /// `MSG_DONTROUTE` - const DONTROUTE = c::MSG_DONTROUTE; + const DONTROUTE = bitcast!(c::MSG_DONTROUTE); /// `MSG_DONTWAIT` #[cfg(not(windows))] - const DONTWAIT = c::MSG_DONTWAIT; + const DONTWAIT = bitcast!(c::MSG_DONTWAIT); /// `MSG_EOR` #[cfg(not(windows))] - const EOT = c::MSG_EOR; + const EOT = bitcast!(c::MSG_EOR); /// `MSG_MORE` #[cfg(not(any( bsd, @@ -30,12 +32,12 @@ bitflags! { windows, target_os = "haiku", )))] - const MORE = c::MSG_MORE; + const MORE = bitcast!(c::MSG_MORE); #[cfg(not(any(apple, windows)))] /// `MSG_NOSIGNAL` - const NOSIGNAL = c::MSG_NOSIGNAL; + const NOSIGNAL = bitcast!(c::MSG_NOSIGNAL); /// `MSG_OOB` - const OOB = c::MSG_OOB; + const OOB = bitcast!(c::MSG_OOB); } } @@ -44,13 +46,15 @@ bitflags! { /// /// [`recv`]: crate::net::recv /// [`recvfrom`]: crate::net::recvfrom - pub struct RecvFlags: i32 { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct RecvFlags: u32 { #[cfg(not(any(apple, solarish, windows, target_os = "haiku")))] /// `MSG_CMSG_CLOEXEC` - const CMSG_CLOEXEC = c::MSG_CMSG_CLOEXEC; + const CMSG_CLOEXEC = bitcast!(c::MSG_CMSG_CLOEXEC); /// `MSG_DONTWAIT` #[cfg(not(windows))] - const DONTWAIT = c::MSG_DONTWAIT; + const DONTWAIT = bitcast!(c::MSG_DONTWAIT); /// `MSG_ERRQUEUE` #[cfg(not(any( bsd, @@ -58,14 +62,14 @@ bitflags! { windows, target_os = "haiku", )))] - const ERRQUEUE = c::MSG_ERRQUEUE; + const ERRQUEUE = bitcast!(c::MSG_ERRQUEUE); /// `MSG_OOB` - const OOB = c::MSG_OOB; + const OOB = bitcast!(c::MSG_OOB); /// `MSG_PEEK` - const PEEK = c::MSG_PEEK; + const PEEK = bitcast!(c::MSG_PEEK); /// `MSG_TRUNC` - const TRUNC = c::MSG_TRUNC as c::c_int; + const TRUNC = bitcast!(c::MSG_TRUNC); /// `MSG_WAITALL` - const WAITALL = c::MSG_WAITALL; + const WAITALL = bitcast!(c::MSG_WAITALL); } } diff --git a/vendor/rustix/src/backend/libc/net/syscalls.rs b/vendor/rustix/src/backend/libc/net/syscalls.rs index ac260e552..63067ff38 100644 --- a/vendor/rustix/src/backend/libc/net/syscalls.rs +++ b/vendor/rustix/src/backend/libc/net/syscalls.rs @@ -1,28 +1,29 @@ //! libc syscalls supporting `rustix::net`. -use super::super::c; -use super::super::conv::{borrowed_fd, ret, ret_owned_fd, ret_send_recv, send_recv_len}; #[cfg(unix)] use super::addr::SocketAddrUnix; use super::ext::{in6_addr_new, in_addr_new}; -#[cfg(not(any(target_os = "redox", target_os = "wasi")))] -use super::read_sockaddr::initialize_family_to_unspec; -#[cfg(not(any(target_os = "redox", target_os = "wasi")))] -use super::read_sockaddr::{maybe_read_sockaddr_os, read_sockaddr_os}; -#[cfg(not(any(target_os = "redox", target_os = "wasi")))] -use super::send_recv::{RecvFlags, SendFlags}; -#[cfg(not(any(target_os = "redox", target_os = "wasi")))] -use super::types::{AddressFamily, Protocol, Shutdown, SocketFlags, SocketType}; -#[cfg(not(any(target_os = "redox", target_os = "wasi")))] -use super::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6}; +use crate::backend::c; +use crate::backend::conv::{borrowed_fd, ret, ret_owned_fd, ret_send_recv, send_recv_len}; use crate::fd::{BorrowedFd, OwnedFd}; use crate::io; use crate::net::{SocketAddrAny, SocketAddrV4, SocketAddrV6}; use crate::utils::as_ptr; -use core::convert::TryInto; use core::mem::{size_of, MaybeUninit}; +#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))] +use { + super::msghdr::{with_noaddr_msghdr, with_recv_msghdr, with_v4_msghdr, with_v6_msghdr}, + crate::io::{IoSlice, IoSliceMut}, + crate::net::{RecvAncillaryBuffer, RecvMsgReturn, SendAncillaryBuffer}, +}; #[cfg(not(any(target_os = "redox", target_os = "wasi")))] -use core::ptr::null_mut; +use { + super::read_sockaddr::{initialize_family_to_unspec, maybe_read_sockaddr_os, read_sockaddr_os}, + super::send_recv::{RecvFlags, SendFlags}, + super::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6}, + crate::net::{AddressFamily, Protocol, Shutdown, SocketFlags, SocketType}, + core::ptr::null_mut, +}; #[cfg(not(any(target_os = "redox", target_os = "wasi")))] pub(crate) fn recv(fd: BorrowedFd<'_>, buf: &mut [u8], flags: RecvFlags) -> io::Result { @@ -31,7 +32,7 @@ pub(crate) fn recv(fd: BorrowedFd<'_>, buf: &mut [u8], flags: RecvFlags) -> io:: borrowed_fd(fd), buf.as_mut_ptr().cast(), send_recv_len(buf.len()), - flags.bits(), + bitflags_bits!(flags), )) } } @@ -43,7 +44,7 @@ pub(crate) fn send(fd: BorrowedFd<'_>, buf: &[u8], flags: SendFlags) -> io::Resu borrowed_fd(fd), buf.as_ptr().cast(), send_recv_len(buf.len()), - flags.bits(), + bitflags_bits!(flags), )) } } @@ -67,7 +68,7 @@ pub(crate) fn recvfrom( borrowed_fd(fd), buf.as_mut_ptr().cast(), send_recv_len(buf.len()), - flags.bits(), + bitflags_bits!(flags), storage.as_mut_ptr().cast(), &mut len, )) @@ -92,7 +93,7 @@ pub(crate) fn sendto_v4( borrowed_fd(fd), buf.as_ptr().cast(), send_recv_len(buf.len()), - flags.bits(), + bitflags_bits!(flags), as_ptr(&encode_sockaddr_v4(addr)).cast::(), size_of::() as _, )) @@ -111,7 +112,7 @@ pub(crate) fn sendto_v6( borrowed_fd(fd), buf.as_ptr().cast(), send_recv_len(buf.len()), - flags.bits(), + bitflags_bits!(flags), as_ptr(&encode_sockaddr_v6(addr)).cast::(), size_of::() as _, )) @@ -130,7 +131,7 @@ pub(crate) fn sendto_unix( borrowed_fd(fd), buf.as_ptr().cast(), send_recv_len(buf.len()), - flags.bits(), + bitflags_bits!(flags), as_ptr(&addr.unix).cast(), addr.addr_len(), )) @@ -141,13 +142,17 @@ pub(crate) fn sendto_unix( pub(crate) fn socket( domain: AddressFamily, type_: SocketType, - protocol: Protocol, + protocol: Option, ) -> io::Result { + let raw_protocol = match protocol { + Some(p) => p.0.get(), + None => 0, + }; unsafe { ret_owned_fd(c::socket( domain.0 as c::c_int, type_.0 as c::c_int, - protocol.0, + raw_protocol as c::c_int, )) } } @@ -157,13 +162,17 @@ pub(crate) fn socket_with( domain: AddressFamily, type_: SocketType, flags: SocketFlags, - protocol: Protocol, + protocol: Option, ) -> io::Result { + let raw_protocol = match protocol { + Some(p) => p.0.get(), + None => 0, + }; unsafe { ret_owned_fd(c::socket( domain.0 as c::c_int, - type_.0 as c::c_int | flags.bits(), - protocol.0, + (type_.0 | flags.bits()) as c::c_int, + raw_protocol as c::c_int, )) } } @@ -247,6 +256,105 @@ pub(crate) fn accept(sockfd: BorrowedFd<'_>) -> io::Result { } } +#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))] +pub(crate) fn recvmsg( + sockfd: BorrowedFd<'_>, + iov: &mut [IoSliceMut<'_>], + control: &mut RecvAncillaryBuffer<'_>, + msg_flags: RecvFlags, +) -> io::Result { + let mut storage = MaybeUninit::::uninit(); + + with_recv_msghdr(&mut storage, iov, control, |msghdr| { + let result = unsafe { + ret_send_recv(c::recvmsg( + borrowed_fd(sockfd), + msghdr, + bitflags_bits!(msg_flags), + )) + }; + + result.map(|bytes| { + // Get the address of the sender, if any. + let addr = + unsafe { maybe_read_sockaddr_os(msghdr.msg_name as _, msghdr.msg_namelen as _) }; + + RecvMsgReturn { + bytes, + address: addr, + flags: RecvFlags::from_bits_retain(bitcast!(msghdr.msg_flags)), + } + }) + }) +} + +#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))] +pub(crate) fn sendmsg( + sockfd: BorrowedFd<'_>, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + msg_flags: SendFlags, +) -> io::Result { + with_noaddr_msghdr(iov, control, |msghdr| unsafe { + ret_send_recv(c::sendmsg( + borrowed_fd(sockfd), + &msghdr, + bitflags_bits!(msg_flags), + )) + }) +} + +#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))] +pub(crate) fn sendmsg_v4( + sockfd: BorrowedFd<'_>, + addr: &SocketAddrV4, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + msg_flags: SendFlags, +) -> io::Result { + with_v4_msghdr(addr, iov, control, |msghdr| unsafe { + ret_send_recv(c::sendmsg( + borrowed_fd(sockfd), + &msghdr, + bitflags_bits!(msg_flags), + )) + }) +} + +#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))] +pub(crate) fn sendmsg_v6( + sockfd: BorrowedFd<'_>, + addr: &SocketAddrV6, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + msg_flags: SendFlags, +) -> io::Result { + with_v6_msghdr(addr, iov, control, |msghdr| unsafe { + ret_send_recv(c::sendmsg( + borrowed_fd(sockfd), + &msghdr, + bitflags_bits!(msg_flags), + )) + }) +} + +#[cfg(all(unix, not(target_os = "redox")))] +pub(crate) fn sendmsg_unix( + sockfd: BorrowedFd<'_>, + addr: &SocketAddrUnix, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + msg_flags: SendFlags, +) -> io::Result { + super::msghdr::with_unix_msghdr(addr, iov, control, |msghdr| unsafe { + ret_send_recv(c::sendmsg( + borrowed_fd(sockfd), + &msghdr, + bitflags_bits!(msg_flags), + )) + }) +} + #[cfg(not(any( apple, windows, @@ -260,7 +368,7 @@ pub(crate) fn accept_with(sockfd: BorrowedFd<'_>, flags: SocketFlags) -> io::Res borrowed_fd(sockfd), null_mut(), null_mut(), - flags.bits(), + flags.bits() as c::c_int, ))?; Ok(owned_fd) } @@ -301,7 +409,7 @@ pub(crate) fn acceptfrom_with( borrowed_fd(sockfd), storage.as_mut_ptr().cast(), &mut len, - flags.bits(), + flags.bits() as c::c_int, ))?; Ok(( owned_fd, @@ -368,14 +476,18 @@ pub(crate) fn socketpair( domain: AddressFamily, type_: SocketType, flags: SocketFlags, - protocol: Protocol, + protocol: Option, ) -> io::Result<(OwnedFd, OwnedFd)> { + let raw_protocol = match protocol { + Some(p) => p.0.get(), + None => 0, + }; unsafe { let mut fds = MaybeUninit::<[OwnedFd; 2]>::uninit(); ret(c::socketpair( c::c_int::from(domain.0), - type_.0 as c::c_int | flags.bits(), - protocol.0, + (type_.0 | flags.bits()) as c::c_int, + raw_protocol as c::c_int, fds.as_mut_ptr().cast::(), ))?; @@ -391,14 +503,10 @@ pub(crate) mod sockopt { use crate::net::sockopt::Timeout; use crate::net::{Ipv4Addr, Ipv6Addr, SocketType}; use crate::utils::as_mut_ptr; - use core::convert::TryInto; use core::time::Duration; #[cfg(windows)] use windows_sys::Win32::Foundation::BOOL; - // TODO: With Rust 1.53 we can use `Duration::ZERO` instead. - const DURATION_ZERO: Duration = Duration::from_secs(0); - #[inline] fn getsockopt(fd: BorrowedFd<'_>, level: i32, optname: i32) -> io::Result { use super::*; @@ -512,21 +620,16 @@ pub(crate) mod sockopt { #[inline] pub(crate) fn get_socket_linger(fd: BorrowedFd<'_>) -> io::Result> { let linger: c::linger = getsockopt(fd, c::SOL_SOCKET as _, c::SO_LINGER)?; - // TODO: With Rust 1.50, this could use `.then`. - Ok(if linger.l_onoff != 0 { - Some(Duration::from_secs(linger.l_linger as u64)) - } else { - None - }) + Ok((linger.l_onoff != 0).then(|| Duration::from_secs(linger.l_linger as u64))) } - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_kernel)] #[inline] pub(crate) fn set_socket_passcred(fd: BorrowedFd<'_>, passcred: bool) -> io::Result<()> { setsockopt(fd, c::SOL_SOCKET as _, c::SO_PASSCRED, from_bool(passcred)) } - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_kernel)] #[inline] pub(crate) fn get_socket_passcred(fd: BorrowedFd<'_>) -> io::Result { getsockopt(fd, c::SOL_SOCKET as _, c::SO_PASSCRED).map(to_bool) @@ -546,7 +649,7 @@ pub(crate) mod sockopt { #[cfg(not(windows))] let timeout = match timeout { Some(timeout) => { - if timeout == DURATION_ZERO { + if timeout == Duration::ZERO { return Err(io::Errno::INVAL); } @@ -577,7 +680,7 @@ pub(crate) mod sockopt { #[cfg(windows)] let timeout: u32 = match timeout { Some(timeout) => { - if timeout == DURATION_ZERO { + if timeout == Duration::ZERO { return Err(io::Errno::INVAL); } @@ -633,13 +736,13 @@ pub(crate) mod sockopt { #[cfg(any(apple, target_os = "freebsd"))] #[inline] - pub(crate) fn getsockopt_nosigpipe(fd: BorrowedFd<'_>) -> io::Result { + pub(crate) fn get_socket_nosigpipe(fd: BorrowedFd<'_>) -> io::Result { getsockopt(fd, c::SOL_SOCKET, c::SO_NOSIGPIPE).map(to_bool) } #[cfg(any(apple, target_os = "freebsd"))] #[inline] - pub(crate) fn setsockopt_nosigpipe(fd: BorrowedFd<'_>, val: bool) -> io::Result<()> { + pub(crate) fn set_socket_nosigpipe(fd: BorrowedFd<'_>, val: bool) -> io::Result<()> { setsockopt(fd, c::SOL_SOCKET, c::SO_NOSIGPIPE, from_bool(val)) } @@ -764,14 +867,14 @@ pub(crate) mod sockopt { setsockopt( fd, c::IPPROTO_IP as _, - c::IPV6_MULTICAST_LOOP, + c::IPV6_MULTICAST_HOPS, multicast_hops, ) } #[inline] pub(crate) fn get_ipv6_multicast_hops(fd: BorrowedFd<'_>) -> io::Result { - getsockopt(fd, c::IPPROTO_IP as _, c::IPV6_MULTICAST_LOOP) + getsockopt(fd, c::IPPROTO_IP as _, c::IPV6_MULTICAST_HOPS) } #[inline] diff --git a/vendor/rustix/src/backend/libc/net/types.rs b/vendor/rustix/src/backend/libc/net/types.rs deleted file mode 100644 index d1d769cb4..000000000 --- a/vendor/rustix/src/backend/libc/net/types.rs +++ /dev/null @@ -1,500 +0,0 @@ -use super::super::c; -use bitflags::bitflags; - -/// A type for holding raw integer socket types. -#[doc(hidden)] -pub type RawSocketType = u32; - -/// `SOCK_*` constants for use with [`socket`]. -/// -/// [`socket`]: crate::net::socket -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[repr(transparent)] -pub struct SocketType(pub(crate) RawSocketType); - -#[rustfmt::skip] -impl SocketType { - /// `SOCK_STREAM` - pub const STREAM: Self = Self(c::SOCK_STREAM as u32); - - /// `SOCK_DGRAM` - pub const DGRAM: Self = Self(c::SOCK_DGRAM as u32); - - /// `SOCK_SEQPACKET` - pub const SEQPACKET: Self = Self(c::SOCK_SEQPACKET as u32); - - /// `SOCK_RAW` - pub const RAW: Self = Self(c::SOCK_RAW as u32); - - /// `SOCK_RDM` - #[cfg(not(target_os = "haiku"))] - pub const RDM: Self = Self(c::SOCK_RDM as u32); - - /// Constructs a `SocketType` from a raw integer. - #[inline] - pub const fn from_raw(raw: RawSocketType) -> Self { - Self(raw) - } - - /// Returns the raw integer for this `SocketType`. - #[inline] - pub const fn as_raw(self) -> RawSocketType { - self.0 - } -} - -/// A type for holding raw integer address families. -#[doc(hidden)] -pub type RawAddressFamily = c::sa_family_t; - -/// `AF_*` constants. -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[repr(transparent)] -pub struct AddressFamily(pub(crate) RawAddressFamily); - -#[rustfmt::skip] -#[allow(non_upper_case_globals)] -impl AddressFamily { - /// `AF_UNSPEC` - pub const UNSPEC: Self = Self(c::AF_UNSPEC as _); - /// `AF_INET` - pub const INET: Self = Self(c::AF_INET as _); - /// `AF_INET6` - pub const INET6: Self = Self(c::AF_INET6 as _); - /// `AF_NETLINK` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const NETLINK: Self = Self(c::AF_NETLINK as _); - /// `AF_UNIX`, aka `AF_LOCAL` - #[doc(alias = "LOCAL")] - pub const UNIX: Self = Self(c::AF_UNIX as _); - /// `AF_AX25` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const AX25: Self = Self(c::AF_AX25 as _); - /// `AF_IPX` - pub const IPX: Self = Self(c::AF_IPX as _); - /// `AF_APPLETALK` - pub const APPLETALK: Self = Self(c::AF_APPLETALK as _); - /// `AF_NETROM` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const NETROM: Self = Self(c::AF_NETROM as _); - /// `AF_BRIDGE` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const BRIDGE: Self = Self(c::AF_BRIDGE as _); - /// `AF_ATMPVC` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const ATMPVC: Self = Self(c::AF_ATMPVC as _); - /// `AF_X25` - #[cfg(not(any( - bsd, - windows, - target_os = "haiku", - )))] - pub const X25: Self = Self(c::AF_X25 as _); - /// `AF_ROSE` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const ROSE: Self = Self(c::AF_ROSE as _); - /// `AF_DECnet` - #[cfg(not(target_os = "haiku"))] - pub const DECnet: Self = Self(c::AF_DECnet as _); - /// `AF_NETBEUI` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const NETBEUI: Self = Self(c::AF_NETBEUI as _); - /// `AF_SECURITY` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const SECURITY: Self = Self(c::AF_SECURITY as _); - /// `AF_KEY` - #[cfg(not(any( - bsd, - windows, - target_os = "haiku", - )))] - pub const KEY: Self = Self(c::AF_KEY as _); - /// `AF_PACKET` - #[cfg(not(any( - bsd, - windows, - target_os = "haiku", - )))] - pub const PACKET: Self = Self(c::AF_PACKET as _); - /// `AF_ASH` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const ASH: Self = Self(c::AF_ASH as _); - /// `AF_ECONET` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const ECONET: Self = Self(c::AF_ECONET as _); - /// `AF_ATMSVC` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const ATMSVC: Self = Self(c::AF_ATMSVC as _); - /// `AF_RDS` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const RDS: Self = Self(c::AF_RDS as _); - /// `AF_SNA` - #[cfg(not(target_os = "haiku"))] - pub const SNA: Self = Self(c::AF_SNA as _); - /// `AF_IRDA` - #[cfg(not(any( - bsd, - solarish, - target_os = "haiku", - )))] - pub const IRDA: Self = Self(c::AF_IRDA as _); - /// `AF_PPPOX` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const PPPOX: Self = Self(c::AF_PPPOX as _); - /// `AF_WANPIPE` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const WANPIPE: Self = Self(c::AF_WANPIPE as _); - /// `AF_LLC` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const LLC: Self = Self(c::AF_LLC as _); - /// `AF_CAN` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const CAN: Self = Self(c::AF_CAN as _); - /// `AF_TIPC` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const TIPC: Self = Self(c::AF_TIPC as _); - /// `AF_BLUETOOTH` - #[cfg(not(any(apple, solarish, windows)))] - pub const BLUETOOTH: Self = Self(c::AF_BLUETOOTH as _); - /// `AF_IUCV` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const IUCV: Self = Self(c::AF_IUCV as _); - /// `AF_RXRPC` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const RXRPC: Self = Self(c::AF_RXRPC as _); - /// `AF_ISDN` - #[cfg(not(any(solarish, windows, target_os = "haiku")))] - pub const ISDN: Self = Self(c::AF_ISDN as _); - /// `AF_PHONET` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const PHONET: Self = Self(c::AF_PHONET as _); - /// `AF_IEEE802154` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const IEEE802154: Self = Self(c::AF_IEEE802154 as _); - - /// Constructs a `AddressFamily` from a raw integer. - #[inline] - pub const fn from_raw(raw: RawAddressFamily) -> Self { - Self(raw) - } - - /// Returns the raw integer for this `AddressFamily`. - #[inline] - pub const fn as_raw(self) -> RawAddressFamily { - self.0 - } -} - -/// A type for holding raw integer protocols. -#[doc(hidden)] -pub type RawProtocol = i32; - -/// `IPPROTO_*` constants for use with [`socket`] and [`socket_with`]. -/// -/// [`socket`]: crate::net::socket -/// [`socket_with`]: crate::net::socket_with -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[repr(transparent)] -pub struct Protocol(pub(crate) RawProtocol); - -#[rustfmt::skip] -impl Protocol { - /// `IPPROTO_IP` - pub const IP: Self = Self(c::IPPROTO_IP as _); - /// `IPPROTO_ICMP` - pub const ICMP: Self = Self(c::IPPROTO_ICMP as _); - /// `IPPROTO_IGMP` - #[cfg(not(any(solarish, target_os = "haiku")))] - pub const IGMP: Self = Self(c::IPPROTO_IGMP as _); - /// `IPPROTO_IPIP` - #[cfg(not(any(solarish, windows, target_os = "haiku")))] - pub const IPIP: Self = Self(c::IPPROTO_IPIP as _); - /// `IPPROTO_TCP` - pub const TCP: Self = Self(c::IPPROTO_TCP as _); - /// `IPPROTO_EGP` - #[cfg(not(any(solarish, target_os = "haiku")))] - pub const EGP: Self = Self(c::IPPROTO_EGP as _); - /// `IPPROTO_PUP` - #[cfg(not(any(solarish, target_os = "haiku")))] - pub const PUP: Self = Self(c::IPPROTO_PUP as _); - /// `IPPROTO_UDP` - pub const UDP: Self = Self(c::IPPROTO_UDP as _); - /// `IPPROTO_IDP` - #[cfg(not(any(solarish, target_os = "haiku")))] - pub const IDP: Self = Self(c::IPPROTO_IDP as _); - /// `IPPROTO_TP` - #[cfg(not(any(solarish, windows, target_os = "haiku")))] - pub const TP: Self = Self(c::IPPROTO_TP as _); - /// `IPPROTO_DCCP` - #[cfg(not(any( - apple, - solarish, - windows, - target_os = "dragonfly", - target_os = "haiku", - target_os = "openbsd", - )))] - pub const DCCP: Self = Self(c::IPPROTO_DCCP as _); - /// `IPPROTO_IPV6` - pub const IPV6: Self = Self(c::IPPROTO_IPV6 as _); - /// `IPPROTO_RSVP` - #[cfg(not(any(solarish, windows, target_os = "haiku")))] - pub const RSVP: Self = Self(c::IPPROTO_RSVP as _); - /// `IPPROTO_GRE` - #[cfg(not(any(solarish, windows, target_os = "haiku")))] - pub const GRE: Self = Self(c::IPPROTO_GRE as _); - /// `IPPROTO_ESP` - #[cfg(not(any(solarish, target_os = "haiku")))] - pub const ESP: Self = Self(c::IPPROTO_ESP as _); - /// `IPPROTO_AH` - #[cfg(not(any(solarish, target_os = "haiku")))] - pub const AH: Self = Self(c::IPPROTO_AH as _); - /// `IPPROTO_MTP` - #[cfg(not(any( - solarish, - netbsdlike, - windows, - target_os = "haiku", - )))] - pub const MTP: Self = Self(c::IPPROTO_MTP as _); - /// `IPPROTO_BEETPH` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const BEETPH: Self = Self(c::IPPROTO_BEETPH as _); - /// `IPPROTO_ENCAP` - #[cfg(not(any(solarish, windows, target_os = "haiku")))] - pub const ENCAP: Self = Self(c::IPPROTO_ENCAP as _); - /// `IPPROTO_PIM` - #[cfg(not(any(solarish, target_os = "haiku")))] - pub const PIM: Self = Self(c::IPPROTO_PIM as _); - /// `IPPROTO_COMP` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "haiku", - )))] - pub const COMP: Self = Self(c::IPPROTO_COMP as _); - /// `IPPROTO_SCTP` - #[cfg(not(any(solarish, target_os = "dragonfly", target_os = "haiku", target_os = "openbsd")))] - pub const SCTP: Self = Self(c::IPPROTO_SCTP as _); - /// `IPPROTO_UDPLITE` - #[cfg(not(any( - apple, - netbsdlike, - solarish, - windows, - target_os = "dragonfly", - target_os = "haiku", - )))] - pub const UDPLITE: Self = Self(c::IPPROTO_UDPLITE as _); - /// `IPPROTO_MPLS` - #[cfg(not(any( - apple, - solarish, - windows, - target_os = "dragonfly", - target_os = "haiku", - target_os = "netbsd", - )))] - pub const MPLS: Self = Self(c::IPPROTO_MPLS as _); - /// `IPPROTO_RAW` - pub const RAW: Self = Self(c::IPPROTO_RAW as _); - /// `IPPROTO_MPTCP` - #[cfg(not(any( - bsd, - solarish, - windows, - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia", - target_os = "haiku", - )))] - pub const MPTCP: Self = Self(c::IPPROTO_MPTCP as _); - /// `IPPROTO_FRAGMENT` - #[cfg(not(any(solarish, target_os = "haiku")))] - pub const FRAGMENT: Self = Self(c::IPPROTO_FRAGMENT as _); - /// `IPPROTO_ICMPV6` - pub const ICMPV6: Self = Self(c::IPPROTO_ICMPV6 as _); - /// `IPPROTO_MH` - #[cfg(not(any( - apple, - netbsdlike, - solarish, - windows, - target_os = "dragonfly", - target_os = "haiku", - )))] - pub const MH: Self = Self(c::IPPROTO_MH as _); - /// `IPPROTO_ROUTING` - #[cfg(not(any(solarish, target_os = "haiku")))] - pub const ROUTING: Self = Self(c::IPPROTO_ROUTING as _); - - /// Constructs a `Protocol` from a raw integer. - #[inline] - pub const fn from_raw(raw: RawProtocol) -> Self { - Self(raw) - } - - /// Returns the raw integer for this `Protocol`. - #[inline] - pub const fn as_raw(self) -> RawProtocol { - self.0 - } -} - -/// `SHUT_*` constants for use with [`shutdown`]. -/// -/// [`shutdown`]: crate::net::shutdown -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[repr(i32)] -pub enum Shutdown { - /// `SHUT_RD`—Disable further read operations. - Read = c::SHUT_RD, - /// `SHUT_WR`—Disable further write operations. - Write = c::SHUT_WR, - /// `SHUT_RDWR`—Disable further read and write operations. - ReadWrite = c::SHUT_RDWR, -} - -bitflags! { - /// `SOCK_*` constants for use with [`socket_with`], [`accept_with`] and - /// [`acceptfrom_with`]. - /// - /// [`socket_with`]: crate::net::socket_with - /// [`accept_with`]: crate::net::accept_with - /// [`acceptfrom_with`]: crate::net::acceptfrom_with - pub struct SocketFlags: c::c_int { - /// `SOCK_NONBLOCK` - #[cfg(not(any(apple, windows, target_os = "haiku")))] - const NONBLOCK = c::SOCK_NONBLOCK; - - /// `SOCK_CLOEXEC` - #[cfg(not(any(apple, windows, target_os = "haiku")))] - const CLOEXEC = c::SOCK_CLOEXEC; - } -} - -/// Timeout identifier for use with [`set_socket_timeout`] and -/// [`get_socket_timeout`]. -/// -/// [`set_socket_timeout`]: crate::net::sockopt::set_socket_timeout. -/// [`get_socket_timeout`]: crate::net::sockopt::get_socket_timeout. -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[repr(i32)] -pub enum Timeout { - /// `SO_RCVTIMEO`—Timeout for receiving. - Recv = c::SO_RCVTIMEO, - - /// `SO_SNDTIMEO`—Timeout for sending. - Send = c::SO_SNDTIMEO, -} diff --git a/vendor/rustix/src/backend/libc/net/write_sockaddr.rs b/vendor/rustix/src/backend/libc/net/write_sockaddr.rs index f8ab62966..efb5a4e14 100644 --- a/vendor/rustix/src/backend/libc/net/write_sockaddr.rs +++ b/vendor/rustix/src/backend/libc/net/write_sockaddr.rs @@ -1,11 +1,11 @@ //! The BSD sockets API requires us to read the `ss_family` field before //! we can interpret the rest of a `sockaddr` produced by the kernel. -use super::super::c; use super::addr::SocketAddrStorage; #[cfg(unix)] use super::addr::SocketAddrUnix; use super::ext::{in6_addr_new, in_addr_new, sockaddr_in6_new}; +use crate::backend::c; use crate::net::{SocketAddrAny, SocketAddrV4, SocketAddrV6}; use core::mem::size_of; diff --git a/vendor/rustix/src/backend/libc/offset.rs b/vendor/rustix/src/backend/libc/offset.rs deleted file mode 100644 index d7a803415..000000000 --- a/vendor/rustix/src/backend/libc/offset.rs +++ /dev/null @@ -1,410 +0,0 @@ -//! Automatically enable “large file” support features. - -#[cfg(not(windows))] -use super::c; - -#[cfg(not(any(linux_like, windows)))] -#[cfg(feature = "fs")] -pub(super) use c::{ - fstat as libc_fstat, fstatat as libc_fstatat, ftruncate as libc_ftruncate, ino_t as libc_ino_t, - lseek as libc_lseek, off_t as libc_off_t, -}; - -#[cfg(linux_like)] -#[cfg(feature = "fs")] -pub(super) use c::{ - fstat64 as libc_fstat, fstatat64 as libc_fstatat, ftruncate64 as libc_ftruncate, - ino64_t as libc_ino_t, lseek64 as libc_lseek, off64_t as libc_off_t, -}; - -#[cfg(linux_like)] -pub(super) use c::rlimit64 as libc_rlimit; - -#[cfg(not(any(linux_like, windows, target_os = "wasi")))] -#[cfg(feature = "mm")] -pub(super) use c::mmap as libc_mmap; - -#[cfg(not(any( - linux_like, - windows, - target_os = "fuchsia", - target_os = "redox", - target_os = "wasi", -)))] -pub(super) use c::{rlimit as libc_rlimit, RLIM_INFINITY as LIBC_RLIM_INFINITY}; - -#[cfg(not(any(linux_like, windows, target_os = "fuchsia", target_os = "wasi")))] -pub(super) use c::{getrlimit as libc_getrlimit, setrlimit as libc_setrlimit}; - -#[cfg(linux_like)] -pub(super) use c::{ - getrlimit64 as libc_getrlimit, setrlimit64 as libc_setrlimit, - RLIM64_INFINITY as LIBC_RLIM_INFINITY, -}; - -#[cfg(linux_like)] -#[cfg(feature = "mm")] -pub(super) use c::mmap64 as libc_mmap; - -// `prlimit64` wasn't supported in glibc until 2.13. -#[cfg(all(target_os = "linux", target_env = "gnu"))] -weak_or_syscall! { - fn prlimit64( - pid: c::pid_t, - resource: c::__rlimit_resource_t, - new_limit: *const c::rlimit64, - old_limit: *mut c::rlimit64 - ) via SYS_prlimit64 -> c::c_int -} -#[cfg(all(target_os = "linux", target_env = "musl"))] -weak_or_syscall! { - fn prlimit64( - pid: c::pid_t, - resource: c::c_int, - new_limit: *const c::rlimit64, - old_limit: *mut c::rlimit64 - ) via SYS_prlimit64 -> c::c_int -} -#[cfg(target_os = "android")] -weak_or_syscall! { - fn prlimit64( - pid: c::pid_t, - resource: c::c_int, - new_limit: *const c::rlimit64, - old_limit: *mut c::rlimit64 - ) via SYS_prlimit64 -> c::c_int -} -#[cfg(all(target_os = "linux", target_env = "gnu"))] -pub(super) unsafe fn libc_prlimit( - pid: c::pid_t, - resource: c::__rlimit_resource_t, - new_limit: *const c::rlimit64, - old_limit: *mut c::rlimit64, -) -> c::c_int { - prlimit64(pid, resource, new_limit, old_limit) -} -#[cfg(all(target_os = "linux", target_env = "musl"))] -pub(super) unsafe fn libc_prlimit( - pid: c::pid_t, - resource: c::c_int, - new_limit: *const c::rlimit64, - old_limit: *mut c::rlimit64, -) -> c::c_int { - prlimit64(pid, resource, new_limit, old_limit) -} -#[cfg(target_os = "android")] -pub(super) unsafe fn libc_prlimit( - pid: c::pid_t, - resource: c::c_int, - new_limit: *const c::rlimit64, - old_limit: *mut c::rlimit64, -) -> c::c_int { - prlimit64(pid, resource, new_limit, old_limit) -} - -#[cfg(not(any(linux_like, windows, target_os = "redox")))] -#[cfg(feature = "fs")] -pub(super) use c::openat as libc_openat; -#[cfg(linux_like)] -#[cfg(feature = "fs")] -pub(super) use c::openat64 as libc_openat; - -#[cfg(target_os = "fuchsia")] -#[cfg(feature = "fs")] -pub(super) use c::fallocate as libc_fallocate; -#[cfg(any(target_os = "android", target_os = "linux"))] -#[cfg(feature = "fs")] -pub(super) use c::fallocate64 as libc_fallocate; -#[cfg(not(any( - apple, - linux_like, - netbsdlike, - solarish, - windows, - target_os = "dragonfly", - target_os = "haiku", - target_os = "redox", -)))] -#[cfg(feature = "fs")] -pub(super) use c::posix_fadvise as libc_posix_fadvise; -#[cfg(linux_like)] -#[cfg(feature = "fs")] -pub(super) use c::posix_fadvise64 as libc_posix_fadvise; - -#[cfg(all(not(any( - windows, - target_os = "android", - target_os = "linux", - target_os = "emscripten", -))))] -pub(super) use c::{pread as libc_pread, pwrite as libc_pwrite}; -#[cfg(any(target_os = "android", target_os = "linux", target_os = "emscripten"))] -pub(super) use c::{pread64 as libc_pread, pwrite64 as libc_pwrite}; -#[cfg(not(any( - apple, - windows, - target_os = "android", - target_os = "emscripten", - target_os = "haiku", - target_os = "linux", - target_os = "redox", - target_os = "solaris", -)))] -pub(super) use c::{preadv as libc_preadv, pwritev as libc_pwritev}; -#[cfg(any(target_os = "linux", target_os = "emscripten"))] -pub(super) use c::{preadv64 as libc_preadv, pwritev64 as libc_pwritev}; - -#[cfg(target_os = "android")] -mod readwrite_pv64 { - use super::c; - - // 64-bit offsets on 32-bit platforms are passed in endianness-specific - // lo/hi pairs. See src/backend/linux_raw/conv.rs for details. - #[cfg(all(target_endian = "little", target_pointer_width = "32"))] - fn lo(x: u64) -> usize { - (x >> 32) as usize - } - #[cfg(all(target_endian = "little", target_pointer_width = "32"))] - fn hi(x: u64) -> usize { - (x & 0xffff_ffff) as usize - } - #[cfg(all(target_endian = "big", target_pointer_width = "32"))] - fn lo(x: u64) -> usize { - (x & 0xffff_ffff) as usize - } - #[cfg(all(target_endian = "big", target_pointer_width = "32"))] - fn hi(x: u64) -> usize { - (x >> 32) as usize - } - - pub(in super::super) unsafe fn preadv64( - fd: c::c_int, - iov: *const c::iovec, - iovcnt: c::c_int, - offset: c::off64_t, - ) -> c::ssize_t { - // Older Android libc lacks `preadv64`, so use the `weak!` mechanism to - // test for it, and call back to `c::syscall`. We don't use - // `weak_or_syscall` here because we need to pass the 64-bit offset - // specially. - weak! { - fn preadv64(c::c_int, *const c::iovec, c::c_int, c::off64_t) -> c::ssize_t - } - if let Some(fun) = preadv64.get() { - fun(fd, iov, iovcnt, offset) - } else { - #[cfg(target_pointer_width = "32")] - { - c::syscall( - c::SYS_preadv, - fd, - iov, - iovcnt, - hi(offset as u64), - lo(offset as u64), - ) as c::ssize_t - } - #[cfg(target_pointer_width = "64")] - { - c::syscall(c::SYS_preadv, fd, iov, iovcnt, offset) as c::ssize_t - } - } - } - pub(in super::super) unsafe fn pwritev64( - fd: c::c_int, - iov: *const c::iovec, - iovcnt: c::c_int, - offset: c::off64_t, - ) -> c::ssize_t { - // See the comments in `preadv64`. - weak! { - fn pwritev64(c::c_int, *const c::iovec, c::c_int, c::off64_t) -> c::ssize_t - } - if let Some(fun) = pwritev64.get() { - fun(fd, iov, iovcnt, offset) - } else { - #[cfg(target_pointer_width = "32")] - { - c::syscall( - c::SYS_pwritev, - fd, - iov, - iovcnt, - hi(offset as u64), - lo(offset as u64), - ) as c::ssize_t - } - #[cfg(target_pointer_width = "64")] - { - c::syscall(c::SYS_pwritev, fd, iov, iovcnt, offset) as c::ssize_t - } - } - } -} -#[cfg(target_os = "android")] -pub(super) use readwrite_pv64::{preadv64 as libc_preadv, pwritev64 as libc_pwritev}; - -// macOS added preadv and pwritev in version 11.0 -#[cfg(apple)] -mod readwrite_pv { - use super::c; - - weakcall! { - pub(in super::super) fn preadv( - fd: c::c_int, - iov: *const c::iovec, - iovcnt: c::c_int, - offset: c::off_t - ) -> c::ssize_t - } - weakcall! { - pub(in super::super) fn pwritev( - fd: c::c_int, - iov: *const c::iovec, - iovcnt: c::c_int, offset: c::off_t - ) -> c::ssize_t - } -} -#[cfg(apple)] -pub(super) use readwrite_pv::{preadv as libc_preadv, pwritev as libc_pwritev}; - -// glibc added `preadv64v2` and `pwritev64v2` in version 2.26. -#[cfg(all(target_os = "linux", target_env = "gnu"))] -mod readwrite_pv64v2 { - use super::c; - - // 64-bit offsets on 32-bit platforms are passed in endianness-specific - // lo/hi pairs. See src/backend/linux_raw/conv.rs for details. - #[cfg(all(target_endian = "little", target_pointer_width = "32"))] - fn lo(x: u64) -> usize { - (x >> 32) as usize - } - #[cfg(all(target_endian = "little", target_pointer_width = "32"))] - fn hi(x: u64) -> usize { - (x & 0xffff_ffff) as usize - } - #[cfg(all(target_endian = "big", target_pointer_width = "32"))] - fn lo(x: u64) -> usize { - (x & 0xffff_ffff) as usize - } - #[cfg(all(target_endian = "big", target_pointer_width = "32"))] - fn hi(x: u64) -> usize { - (x >> 32) as usize - } - - pub(in super::super) unsafe fn preadv64v2( - fd: c::c_int, - iov: *const c::iovec, - iovcnt: c::c_int, - offset: c::off64_t, - flags: c::c_int, - ) -> c::ssize_t { - // Older glibc lacks `preadv64v2`, so use the `weak!` mechanism to - // test for it, and call back to `c::syscall`. We don't use - // `weak_or_syscall` here because we need to pass the 64-bit offset - // specially. - weak! { - fn preadv64v2(c::c_int, *const c::iovec, c::c_int, c::off64_t, c::c_int) -> c::ssize_t - } - if let Some(fun) = preadv64v2.get() { - fun(fd, iov, iovcnt, offset, flags) - } else { - #[cfg(target_pointer_width = "32")] - { - c::syscall( - c::SYS_preadv, - fd, - iov, - iovcnt, - hi(offset as u64), - lo(offset as u64), - flags, - ) as c::ssize_t - } - #[cfg(target_pointer_width = "64")] - { - c::syscall(c::SYS_preadv2, fd, iov, iovcnt, offset, flags) as c::ssize_t - } - } - } - pub(in super::super) unsafe fn pwritev64v2( - fd: c::c_int, - iov: *const c::iovec, - iovcnt: c::c_int, - offset: c::off64_t, - flags: c::c_int, - ) -> c::ssize_t { - // See the comments in `preadv64v2`. - weak! { - fn pwritev64v2(c::c_int, *const c::iovec, c::c_int, c::off64_t, c::c_int) -> c::ssize_t - } - if let Some(fun) = pwritev64v2.get() { - fun(fd, iov, iovcnt, offset, flags) - } else { - #[cfg(target_pointer_width = "32")] - { - c::syscall( - c::SYS_pwritev, - fd, - iov, - iovcnt, - hi(offset as u64), - lo(offset as u64), - flags, - ) as c::ssize_t - } - #[cfg(target_pointer_width = "64")] - { - c::syscall(c::SYS_pwritev2, fd, iov, iovcnt, offset, flags) as c::ssize_t - } - } - } -} -#[cfg(all(target_os = "linux", target_env = "gnu"))] -pub(super) use readwrite_pv64v2::{preadv64v2 as libc_preadv2, pwritev64v2 as libc_pwritev2}; - -#[cfg(not(any( - apple, - netbsdlike, - solarish, - windows, - target_os = "aix", - target_os = "android", - target_os = "dragonfly", - target_os = "fuchsia", - target_os = "linux", - target_os = "l4re", - target_os = "redox", -)))] -#[cfg(feature = "fs")] -pub(super) use c::posix_fallocate as libc_posix_fallocate; -#[cfg(target_os = "l4re")] -#[cfg(feature = "fs")] -pub(super) use c::posix_fallocate64 as libc_posix_fallocate; -#[cfg(not(any( - linux_like, - solarish, - windows, - target_os = "haiku", - target_os = "netbsd", - target_os = "redox", - target_os = "wasi", -)))] -#[cfg(feature = "fs")] -pub(super) use {c::fstatfs as libc_fstatfs, c::statfs as libc_statfs}; -#[cfg(not(any( - linux_like, - windows, - target_os = "haiku", - target_os = "redox", - target_os = "wasi", -)))] -#[cfg(feature = "fs")] -pub(super) use {c::fstatvfs as libc_fstatvfs, c::statvfs as libc_statvfs}; - -#[cfg(linux_like)] -#[cfg(feature = "fs")] -pub(super) use { - c::fstatfs64 as libc_fstatfs, c::fstatvfs64 as libc_fstatvfs, c::statfs64 as libc_statfs, - c::statvfs64 as libc_statvfs, -}; diff --git a/vendor/rustix/src/backend/libc/param/auxv.rs b/vendor/rustix/src/backend/libc/param/auxv.rs index a770c60d8..0eeb972cc 100644 --- a/vendor/rustix/src/backend/libc/param/auxv.rs +++ b/vendor/rustix/src/backend/libc/param/auxv.rs @@ -1,4 +1,4 @@ -use super::super::c; +use crate::backend::c; #[cfg(any( all(target_os = "android", target_pointer_width = "64"), target_os = "linux", diff --git a/vendor/rustix/src/backend/libc/pid/mod.rs b/vendor/rustix/src/backend/libc/pid/mod.rs new file mode 100644 index 000000000..ef944f04d --- /dev/null +++ b/vendor/rustix/src/backend/libc/pid/mod.rs @@ -0,0 +1 @@ +pub(crate) mod syscalls; diff --git a/vendor/rustix/src/backend/libc/pid/syscalls.rs b/vendor/rustix/src/backend/libc/pid/syscalls.rs new file mode 100644 index 000000000..d0ed4bc9f --- /dev/null +++ b/vendor/rustix/src/backend/libc/pid/syscalls.rs @@ -0,0 +1,14 @@ +//! libc syscalls for PIDs + +use crate::backend::c; +use crate::pid::Pid; + +#[cfg(not(target_os = "wasi"))] +#[inline] +#[must_use] +pub(crate) fn getpid() -> Pid { + unsafe { + let pid = c::getpid(); + Pid::from_raw_unchecked(pid) + } +} diff --git a/vendor/rustix/src/backend/libc/pipe/mod.rs b/vendor/rustix/src/backend/libc/pipe/mod.rs new file mode 100644 index 000000000..1e0181a99 --- /dev/null +++ b/vendor/rustix/src/backend/libc/pipe/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod syscalls; +pub(crate) mod types; diff --git a/vendor/rustix/src/backend/libc/pipe/syscalls.rs b/vendor/rustix/src/backend/libc/pipe/syscalls.rs new file mode 100644 index 000000000..c5ded9174 --- /dev/null +++ b/vendor/rustix/src/backend/libc/pipe/syscalls.rs @@ -0,0 +1,111 @@ +use crate::backend::c; +use crate::backend::conv::ret; +use crate::fd::OwnedFd; +use crate::io; +#[cfg(not(any(apple, target_os = "aix", target_os = "haiku", target_os = "wasi")))] +use crate::pipe::PipeFlags; +use core::mem::MaybeUninit; +#[cfg(linux_kernel)] +use { + crate::backend::conv::{borrowed_fd, ret_c_int, ret_usize}, + crate::backend::MAX_IOV, + crate::fd::BorrowedFd, + crate::pipe::{IoSliceRaw, SpliceFlags}, + crate::utils::optional_as_mut_ptr, + core::cmp::min, +}; + +#[cfg(not(target_os = "wasi"))] +pub(crate) fn pipe() -> io::Result<(OwnedFd, OwnedFd)> { + unsafe { + let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit(); + ret(c::pipe(result.as_mut_ptr().cast::()))?; + let [p0, p1] = result.assume_init(); + Ok((p0, p1)) + } +} + +#[cfg(not(any(apple, target_os = "aix", target_os = "haiku", target_os = "wasi")))] +pub(crate) fn pipe_with(flags: PipeFlags) -> io::Result<(OwnedFd, OwnedFd)> { + unsafe { + let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit(); + ret(c::pipe2( + result.as_mut_ptr().cast::(), + bitflags_bits!(flags), + ))?; + let [p0, p1] = result.assume_init(); + Ok((p0, p1)) + } +} + +#[cfg(linux_kernel)] +#[inline] +pub fn splice( + fd_in: BorrowedFd, + off_in: Option<&mut u64>, + fd_out: BorrowedFd, + off_out: Option<&mut u64>, + len: usize, + flags: SpliceFlags, +) -> io::Result { + let off_in = optional_as_mut_ptr(off_in).cast(); + let off_out = optional_as_mut_ptr(off_out).cast(); + + unsafe { + ret_usize(c::splice( + borrowed_fd(fd_in), + off_in, + borrowed_fd(fd_out), + off_out, + len, + flags.bits(), + )) + } +} + +#[cfg(linux_kernel)] +#[inline] +pub unsafe fn vmsplice( + fd: BorrowedFd, + bufs: &[IoSliceRaw], + flags: SpliceFlags, +) -> io::Result { + ret_usize(c::vmsplice( + borrowed_fd(fd), + bufs.as_ptr().cast::(), + min(bufs.len(), MAX_IOV), + flags.bits(), + )) +} + +#[cfg(linux_kernel)] +#[inline] +pub fn tee( + fd_in: BorrowedFd, + fd_out: BorrowedFd, + len: usize, + flags: SpliceFlags, +) -> io::Result { + unsafe { + ret_usize(c::tee( + borrowed_fd(fd_in), + borrowed_fd(fd_out), + len, + flags.bits(), + )) + } +} + +#[cfg(linux_kernel)] +#[inline] +pub(crate) fn fcntl_getpipe_sz(fd: BorrowedFd<'_>) -> io::Result { + unsafe { ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GETPIPE_SZ)).map(|size| size as usize) } +} + +#[cfg(linux_kernel)] +#[inline] +pub(crate) fn fcntl_setpipe_sz(fd: BorrowedFd<'_>, size: usize) -> io::Result<()> { + let size: c::c_int = size.try_into().map_err(|_| io::Errno::PERM)?; + + unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_SETPIPE_SZ, size)) } +} diff --git a/vendor/rustix/src/backend/libc/pipe/types.rs b/vendor/rustix/src/backend/libc/pipe/types.rs new file mode 100644 index 000000000..f48d8041b --- /dev/null +++ b/vendor/rustix/src/backend/libc/pipe/types.rs @@ -0,0 +1,93 @@ +#[cfg(linux_kernel)] +use core::marker::PhantomData; +#[cfg(not(any(apple, target_os = "wasi")))] +use {crate::backend::c, bitflags::bitflags}; + +#[cfg(not(any(apple, target_os = "wasi")))] +bitflags! { + /// `O_*` constants for use with [`pipe_with`]. + /// + /// [`pipe_with`]: crate::io::pipe_with + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct PipeFlags: u32 { + /// `O_CLOEXEC` + const CLOEXEC = bitcast!(c::O_CLOEXEC); + /// `O_DIRECT` + #[cfg(not(any( + solarish, + target_os = "haiku", + target_os = "openbsd", + target_os = "redox", + )))] + const DIRECT = bitcast!(c::O_DIRECT); + /// `O_NONBLOCK` + const NONBLOCK = bitcast!(c::O_NONBLOCK); + } +} + +#[cfg(linux_kernel)] +bitflags! { + /// `SPLICE_F_*` constants for use with [`splice`], [`vmsplice`], + /// and [`tee`]. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct SpliceFlags: c::c_uint { + /// `SPLICE_F_MOVE` + const MOVE = c::SPLICE_F_MOVE; + /// `SPLICE_F_NONBLOCK` + const NONBLOCK = c::SPLICE_F_NONBLOCK; + /// `SPLICE_F_MORE` + const MORE = c::SPLICE_F_MORE; + /// `SPLICE_F_GIFT` + const GIFT = c::SPLICE_F_GIFT; + } +} + +/// A buffer type used with `vmsplice`. +/// +/// It is guaranteed to be ABI compatible with the iovec type on Unix platforms +/// and `WSABUF` on Windows. Unlike `IoSlice` and `IoSliceMut` it is +/// semantically like a raw pointer, and therefore can be shared or mutated as +/// needed. +#[cfg(linux_kernel)] +#[repr(transparent)] +pub struct IoSliceRaw<'a> { + _buf: c::iovec, + _lifetime: PhantomData<&'a ()>, +} + +#[cfg(linux_kernel)] +impl<'a> IoSliceRaw<'a> { + /// Creates a new `IoSlice` wrapping a byte slice. + pub fn from_slice(buf: &'a [u8]) -> Self { + IoSliceRaw { + _buf: c::iovec { + iov_base: buf.as_ptr() as *mut u8 as *mut c::c_void, + iov_len: buf.len() as _, + }, + _lifetime: PhantomData, + } + } + + /// Creates a new `IoSlice` wrapping a mutable byte slice. + pub fn from_slice_mut(buf: &'a mut [u8]) -> Self { + IoSliceRaw { + _buf: c::iovec { + iov_base: buf.as_mut_ptr() as *mut c::c_void, + iov_len: buf.len() as _, + }, + _lifetime: PhantomData, + } + } +} + +#[cfg(not(any(apple, target_os = "wasi")))] +#[test] +fn test_types() { + use core::mem::size_of; + assert_eq!(size_of::(), size_of::()); + + #[cfg(linux_kernel)] + assert_eq!(size_of::(), size_of::()); +} diff --git a/vendor/rustix/src/backend/libc/prctl/mod.rs b/vendor/rustix/src/backend/libc/prctl/mod.rs new file mode 100644 index 000000000..ef944f04d --- /dev/null +++ b/vendor/rustix/src/backend/libc/prctl/mod.rs @@ -0,0 +1 @@ +pub(crate) mod syscalls; diff --git a/vendor/rustix/src/backend/libc/prctl/syscalls.rs b/vendor/rustix/src/backend/libc/prctl/syscalls.rs new file mode 100644 index 000000000..451cecc29 --- /dev/null +++ b/vendor/rustix/src/backend/libc/prctl/syscalls.rs @@ -0,0 +1,14 @@ +use crate::backend::c; +use crate::backend::conv::ret_c_int; +use crate::io; + +#[inline] +pub(crate) unsafe fn prctl( + option: c::c_int, + arg2: *mut c::c_void, + arg3: *mut c::c_void, + arg4: *mut c::c_void, + arg5: *mut c::c_void, +) -> io::Result { + ret_c_int(c::prctl(option, arg2, arg3, arg4, arg5)) +} diff --git a/vendor/rustix/src/backend/libc/process/cpu_set.rs b/vendor/rustix/src/backend/libc/process/cpu_set.rs index a9d6d89c2..4cf06b96a 100644 --- a/vendor/rustix/src/backend/libc/process/cpu_set.rs +++ b/vendor/rustix/src/backend/libc/process/cpu_set.rs @@ -2,8 +2,8 @@ #![allow(non_snake_case)] -use super::super::c; use super::types::{RawCpuSet, CPU_SETSIZE}; +use crate::backend::c; #[inline] pub(crate) fn CPU_SET(cpu: usize, cpuset: &mut RawCpuSet) { @@ -43,9 +43,8 @@ pub(crate) fn CPU_ISSET(cpu: usize, cpuset: &RawCpuSet) -> bool { unsafe { c::CPU_ISSET(cpu, cpuset) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] pub(crate) fn CPU_COUNT(cpuset: &RawCpuSet) -> u32 { - use core::convert::TryInto; unsafe { c::CPU_COUNT(cpuset).try_into().unwrap() } } diff --git a/vendor/rustix/src/backend/libc/process/mod.rs b/vendor/rustix/src/backend/libc/process/mod.rs index 8675c1af9..24f43d443 100644 --- a/vendor/rustix/src/backend/libc/process/mod.rs +++ b/vendor/rustix/src/backend/libc/process/mod.rs @@ -1,9 +1,4 @@ -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "dragonfly", target_os = "fuchsia"))] pub(crate) mod cpu_set; #[cfg(not(windows))] pub(crate) mod syscalls; diff --git a/vendor/rustix/src/backend/libc/process/syscalls.rs b/vendor/rustix/src/backend/libc/process/syscalls.rs index d8f4fe3a4..0aa29b0b1 100644 --- a/vendor/rustix/src/backend/libc/process/syscalls.rs +++ b/vendor/rustix/src/backend/libc/process/syscalls.rs @@ -1,52 +1,43 @@ //! libc syscalls supporting `rustix::process`. -use super::super::c; -#[cfg(not(any(target_os = "wasi", target_os = "fuchsia")))] -use super::super::conv::borrowed_fd; -use super::super::conv::{c_str, ret, ret_c_int, ret_discarded_char_ptr}; -#[cfg(not(target_os = "wasi"))] -use super::super::conv::{ret_infallible, ret_pid_t, ret_usize}; -#[cfg(any(target_os = "android", target_os = "linux"))] -use super::super::conv::{syscall_ret, syscall_ret_u32}; -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "dragonfly", target_os = "fuchsia"))] use super::types::RawCpuSet; -#[cfg(not(any(target_os = "wasi", target_os = "fuchsia")))] +use crate::backend::c; +#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +use crate::backend::conv::ret_infallible; +#[cfg(linux_kernel)] +use crate::backend::conv::ret_u32; +#[cfg(not(target_os = "wasi"))] +use crate::backend::conv::{borrowed_fd, ret_pid_t, ret_usize}; +#[cfg(feature = "fs")] +use crate::backend::conv::{c_str, ret_discarded_char_ptr}; +use crate::backend::conv::{ret, ret_c_int}; +#[cfg(not(target_os = "wasi"))] use crate::fd::BorrowedFd; #[cfg(target_os = "linux")] -use crate::fd::{AsRawFd, OwnedFd}; +use crate::fd::{AsRawFd, OwnedFd, RawFd}; +#[cfg(feature = "fs")] use crate::ffi::CStr; #[cfg(feature = "fs")] use crate::fs::Mode; use crate::io; -#[cfg(any(target_os = "android", target_os = "linux"))] -use crate::process::Sysinfo; -#[cfg(not(any(target_os = "wasi", target_os = "redox", target_os = "openbsd")))] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] +use crate::process::Uid; +#[cfg(linux_kernel)] +use crate::process::{Cpuid, MembarrierCommand, MembarrierQuery}; +#[cfg(not(target_os = "wasi"))] +use crate::process::{Gid, Pid, RawPid, Signal, WaitOptions, WaitStatus}; +#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +use crate::process::{Resource, Rlimit}; +#[cfg(not(any(target_os = "redox", target_os = "openbsd", target_os = "wasi")))] use crate::process::{WaitId, WaitidOptions, WaitidStatus}; use core::mem::MaybeUninit; #[cfg(target_os = "linux")] -use {super::super::conv::syscall_ret_owned_fd, crate::process::PidfdFlags}; -#[cfg(any(target_os = "android", target_os = "linux"))] use { - super::super::offset::libc_prlimit, - crate::process::{Cpuid, MembarrierCommand, MembarrierQuery}, -}; -#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] -use { - super::super::offset::{libc_getrlimit, libc_rlimit, libc_setrlimit, LIBC_RLIM_INFINITY}, - crate::process::{Resource, Rlimit}, -}; -#[cfg(not(target_os = "wasi"))] -use { - super::types::RawUname, - crate::process::{Gid, Pid, RawNonZeroPid, RawPid, Signal, Uid, WaitOptions, WaitStatus}, - core::convert::TryInto, + super::super::conv::ret_owned_fd, crate::process::PidfdFlags, crate::process::PidfdGetfdFlags, }; +#[cfg(feature = "fs")] #[cfg(not(target_os = "wasi"))] pub(crate) fn chdir(path: &CStr) -> io::Result<()> { unsafe { ret(c::chdir(c_str(path))) } @@ -57,17 +48,29 @@ pub(crate) fn fchdir(dirfd: BorrowedFd<'_>) -> io::Result<()> { unsafe { ret(c::fchdir(borrowed_fd(dirfd))) } } +#[cfg(feature = "fs")] #[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] pub(crate) fn chroot(path: &CStr) -> io::Result<()> { unsafe { ret(c::chroot(c_str(path))) } } +#[cfg(feature = "fs")] #[cfg(not(target_os = "wasi"))] -pub(crate) fn getcwd(buf: &mut [u8]) -> io::Result<()> { +pub(crate) fn getcwd(buf: &mut [MaybeUninit]) -> io::Result<()> { unsafe { ret_discarded_char_ptr(c::getcwd(buf.as_mut_ptr().cast(), buf.len())) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +// The `membarrier` syscall has a third argument, but it's only used when +// the `flags` argument is `MEMBARRIER_CMD_FLAG_CPU`. +#[cfg(linux_kernel)] +syscall! { + fn membarrier_all( + cmd: c::c_int, + flags: c::c_uint + ) via SYS_membarrier -> c::c_int +} + +#[cfg(linux_kernel)] pub(crate) fn membarrier_query() -> MembarrierQuery { // glibc does not have a wrapper for `membarrier`; [the documentation] // says to use `syscall`. @@ -75,79 +78,36 @@ pub(crate) fn membarrier_query() -> MembarrierQuery { // [the documentation]: https://man7.org/linux/man-pages/man2/membarrier.2.html#NOTES const MEMBARRIER_CMD_QUERY: u32 = 0; unsafe { - match syscall_ret_u32(c::syscall(c::SYS_membarrier, MEMBARRIER_CMD_QUERY, 0)) { - Ok(query) => MembarrierQuery::from_bits_unchecked(query), + match ret_u32(membarrier_all(MEMBARRIER_CMD_QUERY as i32, 0)) { + Ok(query) => MembarrierQuery::from_bits_retain(query), Err(_) => MembarrierQuery::empty(), } } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub(crate) fn membarrier(cmd: MembarrierCommand) -> io::Result<()> { - unsafe { syscall_ret(c::syscall(c::SYS_membarrier, cmd as u32, 0)) } + unsafe { ret(membarrier_all(cmd as i32, 0)) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub(crate) fn membarrier_cpu(cmd: MembarrierCommand, cpu: Cpuid) -> io::Result<()> { const MEMBARRIER_CMD_FLAG_CPU: u32 = 1; - unsafe { - syscall_ret(c::syscall( - c::SYS_membarrier, - cmd as u32, - MEMBARRIER_CMD_FLAG_CPU, - cpu.as_raw(), - )) - } -} - -#[cfg(not(target_os = "wasi"))] -#[inline] -#[must_use] -pub(crate) fn getuid() -> Uid { - unsafe { - let uid = c::getuid(); - Uid::from_raw(uid) - } -} - -#[cfg(not(target_os = "wasi"))] -#[inline] -#[must_use] -pub(crate) fn geteuid() -> Uid { - unsafe { - let uid = c::geteuid(); - Uid::from_raw(uid) - } -} -#[cfg(not(target_os = "wasi"))] -#[inline] -#[must_use] -pub(crate) fn getgid() -> Gid { - unsafe { - let gid = c::getgid(); - Gid::from_raw(gid) + syscall! { + fn membarrier_cpu( + cmd: c::c_int, + flags: c::c_uint, + cpu_id: c::c_int + ) via SYS_membarrier -> c::c_int } -} -#[cfg(not(target_os = "wasi"))] -#[inline] -#[must_use] -pub(crate) fn getegid() -> Gid { unsafe { - let gid = c::getegid(); - Gid::from_raw(gid) - } -} - -#[cfg(not(target_os = "wasi"))] -#[inline] -#[must_use] -pub(crate) fn getpid() -> Pid { - unsafe { - let pid = c::getpid(); - debug_assert_ne!(pid, 0); - Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid)) + ret(membarrier_cpu( + cmd as i32, + MEMBARRIER_CMD_FLAG_CPU, + bitcast!(cpu.as_raw()), + )) } } @@ -166,8 +126,7 @@ pub(crate) fn getppid() -> Option { pub(crate) fn getpgid(pid: Option) -> io::Result { unsafe { let pgid = ret_pid_t(c::getpgid(Pid::as_raw(pid) as _))?; - debug_assert_ne!(pgid, 0); - Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pgid))) + Ok(Pid::from_raw_unchecked(pgid)) } } @@ -183,17 +142,11 @@ pub(crate) fn setpgid(pid: Option, pgid: Option) -> io::Result<()> { pub(crate) fn getpgrp() -> Pid { unsafe { let pgid = c::getpgrp(); - debug_assert_ne!(pgid, 0); - Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pgid)) + Pid::from_raw_unchecked(pgid) } } -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "dragonfly", target_os = "fuchsia"))] #[inline] pub(crate) fn sched_getaffinity(pid: Option, cpuset: &mut RawCpuSet) -> io::Result<()> { unsafe { @@ -205,12 +158,7 @@ pub(crate) fn sched_getaffinity(pid: Option, cpuset: &mut RawCpuSet) -> io: } } -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "dragonfly", target_os = "fuchsia"))] #[inline] pub(crate) fn sched_setaffinity(pid: Option, cpuset: &RawCpuSet) -> io::Result<()> { unsafe { @@ -229,22 +177,11 @@ pub(crate) fn sched_yield() { } } -#[cfg(not(target_os = "wasi"))] -#[inline] -pub(crate) fn uname() -> RawUname { - let mut uname = MaybeUninit::::uninit(); - unsafe { - ret_infallible(c::uname(uname.as_mut_ptr())); - uname.assume_init() - } -} - #[cfg(not(target_os = "wasi"))] #[cfg(feature = "fs")] #[inline] pub(crate) fn umask(mask: Mode) -> Mode { - // TODO: Use `from_bits_retain` when we switch to bitflags 2.0. - unsafe { Mode::from_bits_truncate(c::umask(mask.bits() as _) as _) } + unsafe { Mode::from_bits_retain(c::umask(mask.bits() as c::mode_t).into()) } } #[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] @@ -259,7 +196,7 @@ pub(crate) fn nice(inc: i32) -> io::Result { } } -#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] #[inline] pub(crate) fn getpriority_user(uid: Uid) -> io::Result { libc_errno::set_errno(libc_errno::Errno(0)); @@ -271,7 +208,7 @@ pub(crate) fn getpriority_user(uid: Uid) -> io::Result { } } -#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] #[inline] pub(crate) fn getpriority_pgrp(pgid: Option) -> io::Result { libc_errno::set_errno(libc_errno::Errno(0)); @@ -283,7 +220,7 @@ pub(crate) fn getpriority_pgrp(pgid: Option) -> io::Result { } } -#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] #[inline] pub(crate) fn getpriority_process(pid: Option) -> io::Result { libc_errno::set_errno(libc_errno::Errno(0)); @@ -295,13 +232,13 @@ pub(crate) fn getpriority_process(pid: Option) -> io::Result { } } -#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] #[inline] pub(crate) fn setpriority_user(uid: Uid, priority: i32) -> io::Result<()> { unsafe { ret(c::setpriority(c::PRIO_USER, uid.as_raw() as _, priority)) } } -#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] #[inline] pub(crate) fn setpriority_pgrp(pgid: Option, priority: i32) -> io::Result<()> { unsafe { @@ -313,7 +250,7 @@ pub(crate) fn setpriority_pgrp(pgid: Option, priority: i32) -> io::Result<( } } -#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] #[inline] pub(crate) fn setpriority_process(pid: Option, priority: i32) -> io::Result<()> { unsafe { @@ -328,9 +265,9 @@ pub(crate) fn setpriority_process(pid: Option, priority: i32) -> io::Result #[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] #[inline] pub(crate) fn getrlimit(limit: Resource) -> Rlimit { - let mut result = MaybeUninit::::uninit(); + let mut result = MaybeUninit::::uninit(); unsafe { - ret_infallible(libc_getrlimit(limit as _, result.as_mut_ptr())); + ret_infallible(c::getrlimit(limit as _, result.as_mut_ptr())); rlimit_from_libc(result.assume_init()) } } @@ -339,16 +276,16 @@ pub(crate) fn getrlimit(limit: Resource) -> Rlimit { #[inline] pub(crate) fn setrlimit(limit: Resource, new: Rlimit) -> io::Result<()> { let lim = rlimit_to_libc(new)?; - unsafe { ret(libc_setrlimit(limit as _, &lim)) } + unsafe { ret(c::setrlimit(limit as _, &lim)) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] pub(crate) fn prlimit(pid: Option, limit: Resource, new: Rlimit) -> io::Result { let lim = rlimit_to_libc(new)?; - let mut result = MaybeUninit::::uninit(); + let mut result = MaybeUninit::::uninit(); unsafe { - ret(libc_prlimit( + ret(c::prlimit( Pid::as_raw(pid), limit as _, &lim, @@ -358,15 +295,15 @@ pub(crate) fn prlimit(pid: Option, limit: Resource, new: Rlimit) -> io::Res } } -/// Convert a Rust [`Rlimit`] to a C `libc_rlimit`. +/// Convert a Rust [`Rlimit`] to a C `c::rlimit`. #[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] -fn rlimit_from_libc(lim: libc_rlimit) -> Rlimit { - let current = if lim.rlim_cur == LIBC_RLIM_INFINITY { +fn rlimit_from_libc(lim: c::rlimit) -> Rlimit { + let current = if lim.rlim_cur == c::RLIM_INFINITY { None } else { Some(lim.rlim_cur.try_into().unwrap()) }; - let maximum = if lim.rlim_max == LIBC_RLIM_INFINITY { + let maximum = if lim.rlim_max == c::RLIM_INFINITY { None } else { Some(lim.rlim_max.try_into().unwrap()) @@ -374,19 +311,19 @@ fn rlimit_from_libc(lim: libc_rlimit) -> Rlimit { Rlimit { current, maximum } } -/// Convert a C `libc_rlimit` to a Rust `Rlimit`. +/// Convert a C `c::rlimit` to a Rust `Rlimit`. #[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] -fn rlimit_to_libc(lim: Rlimit) -> io::Result { +fn rlimit_to_libc(lim: Rlimit) -> io::Result { let Rlimit { current, maximum } = lim; let rlim_cur = match current { Some(r) => r.try_into().map_err(|_e| io::Errno::INVAL)?, - None => LIBC_RLIM_INFINITY as _, + None => c::RLIM_INFINITY as _, }; let rlim_max = match maximum { Some(r) => r.try_into().map_err(|_e| io::Errno::INVAL)?, - None => LIBC_RLIM_INFINITY as _, + None => c::RLIM_INFINITY as _, }; - Ok(libc_rlimit { rlim_cur, rlim_max }) + Ok(c::rlimit { rlim_cur, rlim_max }) } #[cfg(not(target_os = "wasi"))] @@ -413,12 +350,7 @@ pub(crate) fn _waitpid( unsafe { let mut status: c::c_int = 0; let pid = ret_c_int(c::waitpid(pid as _, &mut status, waitopts.bits() as _))?; - Ok(RawNonZeroPid::new(pid).map(|non_zero| { - ( - Pid::from_raw_nonzero(non_zero), - WaitStatus::new(status as _), - ) - })) + Ok(Pid::from_raw(pid).map(|pid| (pid, WaitStatus::new(status as _)))) } } @@ -503,8 +435,8 @@ unsafe fn cvt_waitid_status(status: MaybeUninit) -> Option) -> Option ! { - // `_exit` and `_Exit` are the same; it's just a matter of which ones - // the libc bindings expose. - #[cfg(any(target_os = "wasi", target_os = "solid"))] - unsafe { - c::_Exit(code) - } - #[cfg(unix)] - unsafe { - c::_exit(code) - } -} - #[cfg(not(any(target_os = "redox", target_os = "wasi")))] #[inline] pub(crate) fn getsid(pid: Option) -> io::Result { unsafe { let pid = ret_pid_t(c::getsid(Pid::as_raw(pid) as _))?; - debug_assert_ne!(pid, 0); - Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid))) + Ok(Pid::from_raw_unchecked(pid)) } } @@ -543,8 +460,7 @@ pub(crate) fn getsid(pid: Option) -> io::Result { pub(crate) fn setsid() -> io::Result { unsafe { let pid = ret_c_int(c::setsid())?; - debug_assert_ne!(pid, 0); - Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid))) + Ok(Pid::from_raw_unchecked(pid)) } } @@ -589,18 +505,6 @@ pub(crate) fn test_kill_current_process_group() -> io::Result<()> { unsafe { ret(c::kill(0, 0)) } } -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -pub(crate) unsafe fn prctl( - option: c::c_int, - arg2: *mut c::c_void, - arg3: *mut c::c_void, - arg4: *mut c::c_void, - arg5: *mut c::c_void, -) -> io::Result { - ret_c_int(c::prctl(option, arg2, arg3, arg4, arg5)) -} - #[cfg(freebsdlike)] #[inline] pub(crate) unsafe fn procctl( @@ -614,11 +518,38 @@ pub(crate) unsafe fn procctl( #[cfg(target_os = "linux")] pub(crate) fn pidfd_open(pid: Pid, flags: PidfdFlags) -> io::Result { + syscall! { + fn pidfd_open( + pid: c::pid_t, + flags: c::c_uint + ) via SYS_pidfd_open -> c::c_int + } unsafe { - syscall_ret_owned_fd(c::syscall( - c::SYS_pidfd_open, + ret_owned_fd(pidfd_open( pid.as_raw_nonzero().get(), - flags.bits(), + bitflags_bits!(flags), + )) + } +} + +#[cfg(target_os = "linux")] +pub(crate) fn pidfd_getfd( + pidfd: BorrowedFd<'_>, + targetfd: RawFd, + flags: PidfdGetfdFlags, +) -> io::Result { + syscall! { + fn pidfd_getfd( + pidfd: c::c_int, + targetfd: c::c_int, + flags: c::c_uint + ) via SYS_pidfd_getfd -> c::c_int + } + unsafe { + ret_owned_fd(pidfd_getfd( + borrowed_fd(pidfd), + targetfd, + bitflags_bits!(flags), )) } } @@ -630,21 +561,8 @@ pub(crate) fn getgroups(buf: &mut [Gid]) -> io::Result { unsafe { ret_usize(c::getgroups(len, buf.as_mut_ptr().cast()) as isize) } } -#[cfg(any(target_os = "android", target_os = "linux"))] -pub(crate) fn sysinfo() -> Sysinfo { - let mut info = MaybeUninit::::uninit(); - unsafe { - ret_infallible(c::sysinfo(info.as_mut_ptr())); - info.assume_init() - } -} - -#[cfg(not(any(target_os = "emscripten", target_os = "redox", target_os = "wasi")))] -pub(crate) fn sethostname(name: &[u8]) -> io::Result<()> { - unsafe { - ret(c::sethostname( - name.as_ptr().cast(), - name.len().try_into().map_err(|_| io::Errno::INVAL)?, - )) - } +#[cfg(not(any(target_os = "redox", target_os = "wasi")))] +#[inline] +pub(crate) fn ioctl_tiocsctty(fd: BorrowedFd<'_>) -> io::Result<()> { + unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCSCTTY as _, &0_u32)) } } diff --git a/vendor/rustix/src/backend/libc/process/types.rs b/vendor/rustix/src/backend/libc/process/types.rs index e7f10dbff..980c0effe 100644 --- a/vendor/rustix/src/backend/libc/process/types.rs +++ b/vendor/rustix/src/backend/libc/process/types.rs @@ -1,8 +1,4 @@ -use super::super::c; - -/// `sysinfo` -#[cfg(any(target_os = "android", target_os = "linux"))] -pub type Sysinfo = c::sysinfo; +use crate::backend::c; /// A command for use with [`membarrier`] and [`membarrier_cpu`]. /// @@ -11,7 +7,7 @@ pub type Sysinfo = c::sysinfo; /// [`membarrier`]: crate::process::membarrier /// [`membarrier_cpu`]: crate::process::membarrier_cpu /// [`membarrier_query`]: crate::process::membarrier_query -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[derive(Copy, Clone, Eq, PartialEq, Debug)] #[repr(u32)] pub enum MembarrierCommand { @@ -46,48 +42,48 @@ pub enum MembarrierCommand { /// [`prlimit`]: crate::process::prlimit #[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] #[derive(Copy, Clone, Debug, Eq, PartialEq)] -#[repr(i32)] +#[repr(u32)] pub enum Resource { /// `RLIMIT_CPU` - Cpu = c::RLIMIT_CPU as c::c_int, + Cpu = bitcast!(c::RLIMIT_CPU), /// `RLIMIT_FSIZE` - Fsize = c::RLIMIT_FSIZE as c::c_int, + Fsize = bitcast!(c::RLIMIT_FSIZE), /// `RLIMIT_DATA` - Data = c::RLIMIT_DATA as c::c_int, + Data = bitcast!(c::RLIMIT_DATA), /// `RLIMIT_STACK` - Stack = c::RLIMIT_STACK as c::c_int, + Stack = bitcast!(c::RLIMIT_STACK), /// `RLIMIT_CORE` #[cfg(not(target_os = "haiku"))] - Core = c::RLIMIT_CORE as c::c_int, + Core = bitcast!(c::RLIMIT_CORE), /// `RLIMIT_RSS` #[cfg(not(any(apple, solarish, target_os = "haiku")))] - Rss = c::RLIMIT_RSS as c::c_int, + Rss = bitcast!(c::RLIMIT_RSS), /// `RLIMIT_NPROC` #[cfg(not(any(solarish, target_os = "haiku")))] - Nproc = c::RLIMIT_NPROC as c::c_int, + Nproc = bitcast!(c::RLIMIT_NPROC), /// `RLIMIT_NOFILE` - Nofile = c::RLIMIT_NOFILE as c::c_int, + Nofile = bitcast!(c::RLIMIT_NOFILE), /// `RLIMIT_MEMLOCK` #[cfg(not(any(solarish, target_os = "aix", target_os = "haiku")))] - Memlock = c::RLIMIT_MEMLOCK as c::c_int, + Memlock = bitcast!(c::RLIMIT_MEMLOCK), /// `RLIMIT_AS` #[cfg(not(target_os = "openbsd"))] - As = c::RLIMIT_AS as c::c_int, + As = bitcast!(c::RLIMIT_AS), /// `RLIMIT_LOCKS` #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] - Locks = c::RLIMIT_LOCKS as c::c_int, + Locks = bitcast!(c::RLIMIT_LOCKS), /// `RLIMIT_SIGPENDING` #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] - Sigpending = c::RLIMIT_SIGPENDING as c::c_int, + Sigpending = bitcast!(c::RLIMIT_SIGPENDING), /// `RLIMIT_MSGQUEUE` #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] - Msgqueue = c::RLIMIT_MSGQUEUE as c::c_int, + Msgqueue = bitcast!(c::RLIMIT_MSGQUEUE), /// `RLIMIT_NICE` #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] - Nice = c::RLIMIT_NICE as c::c_int, + Nice = bitcast!(c::RLIMIT_NICE), /// `RLIMIT_RTPRIO` #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] - Rtprio = c::RLIMIT_RTPRIO as c::c_int, + Rtprio = bitcast!(c::RLIMIT_RTPRIO), /// `RLIMIT_RTTIME` #[cfg(not(any( bsd, @@ -97,7 +93,7 @@ pub enum Resource { target_os = "emscripten", target_os = "haiku", )))] - Rttime = c::RLIMIT_RTTIME as c::c_int, + Rttime = bitcast!(c::RLIMIT_RTTIME), } #[cfg(apple)] @@ -107,224 +103,21 @@ impl Resource { pub const Rss: Self = Self::As; } -/// A signal number for use with [`kill_process`], [`kill_process_group`], -/// and [`kill_current_process_group`]. -/// -/// [`kill_process`]: crate::process::kill_process -/// [`kill_process_group`]: crate::process::kill_process_group -/// [`kill_current_process_group`]: crate::process::kill_current_process_group -#[cfg(not(target_os = "wasi"))] -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -#[repr(i32)] -pub enum Signal { - /// `SIGHUP` - Hup = c::SIGHUP, - /// `SIGINT` - Int = c::SIGINT, - /// `SIGQUIT` - Quit = c::SIGQUIT, - /// `SIGILL` - Ill = c::SIGILL, - /// `SIGTRAP` - Trap = c::SIGTRAP, - /// `SIGABRT`, aka `SIGIOT` - #[doc(alias = "Iot")] - #[doc(alias = "Abrt")] - Abort = c::SIGABRT, - /// `SIGBUS` - Bus = c::SIGBUS, - /// `SIGFPE` - Fpe = c::SIGFPE, - /// `SIGKILL` - Kill = c::SIGKILL, - /// `SIGUSR1` - Usr1 = c::SIGUSR1, - /// `SIGSEGV` - Segv = c::SIGSEGV, - /// `SIGUSR2` - Usr2 = c::SIGUSR2, - /// `SIGPIPE` - Pipe = c::SIGPIPE, - /// `SIGALRM` - #[doc(alias = "Alrm")] - Alarm = c::SIGALRM, - /// `SIGTERM` - Term = c::SIGTERM, - /// `SIGSTKFLT` - #[cfg(not(any( - bsd, - solarish, - target_os = "aix", - target_os = "haiku", - all( - any(target_os = "android", target_os = "linux"), - any( - target_arch = "mips", - target_arch = "mips64", - target_arch = "sparc", - target_arch = "sparc64" - ), - ) - )))] - Stkflt = c::SIGSTKFLT, - /// `SIGCHLD` - #[doc(alias = "Chld")] - Child = c::SIGCHLD, - /// `SIGCONT` - Cont = c::SIGCONT, - /// `SIGSTOP` - Stop = c::SIGSTOP, - /// `SIGTSTP` - Tstp = c::SIGTSTP, - /// `SIGTTIN` - Ttin = c::SIGTTIN, - /// `SIGTTOU` - Ttou = c::SIGTTOU, - /// `SIGURG` - Urg = c::SIGURG, - /// `SIGXCPU` - Xcpu = c::SIGXCPU, - /// `SIGXFSZ` - Xfsz = c::SIGXFSZ, - /// `SIGVTALRM` - #[doc(alias = "Vtalrm")] - Vtalarm = c::SIGVTALRM, - /// `SIGPROF` - Prof = c::SIGPROF, - /// `SIGWINCH` - Winch = c::SIGWINCH, - /// `SIGIO`, aka `SIGPOLL` - #[doc(alias = "Poll")] - #[cfg(not(target_os = "haiku"))] - Io = c::SIGIO, - /// `SIGPWR` - #[cfg(not(any(bsd, target_os = "haiku")))] - #[doc(alias = "Pwr")] - Power = c::SIGPWR, - /// `SIGSYS`, aka `SIGUNUSED` - #[doc(alias = "Unused")] - Sys = c::SIGSYS, - /// `SIGEMT` - #[cfg(bsd)] - Emt = c::SIGEMT, - /// `SIGINFO` - #[cfg(bsd)] - Info = c::SIGINFO, - /// `SIGTHR` - #[cfg(target_os = "freebsd")] - #[doc(alias = "Lwp")] - Thr = c::SIGTHR, - /// `SIGLIBRT` - #[cfg(target_os = "freebsd")] - Librt = c::SIGLIBRT, -} - -#[cfg(not(target_os = "wasi"))] -impl Signal { - /// Convert a raw signal number into a `Signal`, if possible. - pub fn from_raw(sig: i32) -> Option { - match sig as _ { - c::SIGHUP => Some(Self::Hup), - c::SIGINT => Some(Self::Int), - c::SIGQUIT => Some(Self::Quit), - c::SIGILL => Some(Self::Ill), - c::SIGTRAP => Some(Self::Trap), - c::SIGABRT => Some(Self::Abort), - c::SIGBUS => Some(Self::Bus), - c::SIGFPE => Some(Self::Fpe), - c::SIGKILL => Some(Self::Kill), - c::SIGUSR1 => Some(Self::Usr1), - c::SIGSEGV => Some(Self::Segv), - c::SIGUSR2 => Some(Self::Usr2), - c::SIGPIPE => Some(Self::Pipe), - c::SIGALRM => Some(Self::Alarm), - c::SIGTERM => Some(Self::Term), - #[cfg(not(any( - bsd, - solarish, - target_os = "aix", - target_os = "haiku", - all( - any(target_os = "android", target_os = "linux"), - any( - target_arch = "mips", - target_arch = "mips64", - target_arch = "sparc", - target_arch = "sparc64" - ), - ) - )))] - c::SIGSTKFLT => Some(Self::Stkflt), - c::SIGCHLD => Some(Self::Child), - c::SIGCONT => Some(Self::Cont), - c::SIGSTOP => Some(Self::Stop), - c::SIGTSTP => Some(Self::Tstp), - c::SIGTTIN => Some(Self::Ttin), - c::SIGTTOU => Some(Self::Ttou), - c::SIGURG => Some(Self::Urg), - c::SIGXCPU => Some(Self::Xcpu), - c::SIGXFSZ => Some(Self::Xfsz), - c::SIGVTALRM => Some(Self::Vtalarm), - c::SIGPROF => Some(Self::Prof), - c::SIGWINCH => Some(Self::Winch), - #[cfg(not(target_os = "haiku"))] - c::SIGIO => Some(Self::Io), - #[cfg(not(any(bsd, target_os = "haiku")))] - c::SIGPWR => Some(Self::Power), - c::SIGSYS => Some(Self::Sys), - #[cfg(bsd)] - c::SIGEMT => Some(Self::Emt), - #[cfg(bsd)] - c::SIGINFO => Some(Self::Info), - #[cfg(target_os = "freebsd")] - c::SIGTHR => Some(Self::Thr), - #[cfg(target_os = "freebsd")] - c::SIGLIBRT => Some(Self::Librt), - _ => None, - } - } -} - pub const EXIT_SUCCESS: c::c_int = c::EXIT_SUCCESS; pub const EXIT_FAILURE: c::c_int = c::EXIT_FAILURE; #[cfg(not(target_os = "wasi"))] pub const EXIT_SIGNALED_SIGABRT: c::c_int = 128 + c::SIGABRT; -/// A process identifier as a raw integer. -#[cfg(not(target_os = "wasi"))] -pub type RawPid = c::pid_t; -/// A non-zero process identifier as a raw non-zero integer. -#[cfg(not(target_os = "wasi"))] -pub type RawNonZeroPid = core::num::NonZeroI32; -/// A group identifier as a raw integer. -#[cfg(not(target_os = "wasi"))] -pub type RawGid = c::gid_t; -/// A user identifier as a raw integer. -#[cfg(not(target_os = "wasi"))] -pub type RawUid = c::uid_t; /// A CPU identifier as a raw integer. -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub type RawCpuid = u32; -#[cfg(target_os = "freebsd")] +#[cfg(freebsdlike)] pub type RawId = c::id_t; -#[cfg(not(target_os = "wasi"))] -pub(crate) type RawUname = c::utsname; - -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "dragonfly", target_os = "fuchsia"))] pub(crate) type RawCpuSet = c::cpu_set_t; -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "dragonfly", target_os = "fuchsia"))] #[inline] pub(crate) fn raw_cpu_set_new() -> RawCpuSet { let mut set = unsafe { core::mem::zeroed() }; @@ -332,7 +125,7 @@ pub(crate) fn raw_cpu_set_new() -> RawCpuSet { set } -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] pub(crate) const CPU_SETSIZE: usize = c::CPU_SETSIZE as usize; #[cfg(target_os = "dragonfly")] pub(crate) const CPU_SETSIZE: usize = 256; diff --git a/vendor/rustix/src/backend/libc/process/wait.rs b/vendor/rustix/src/backend/libc/process/wait.rs index c09ee1002..9a932cfab 100644 --- a/vendor/rustix/src/backend/libc/process/wait.rs +++ b/vendor/rustix/src/backend/libc/process/wait.rs @@ -1,4 +1,4 @@ -use super::super::c; +use crate::backend::c; pub(crate) use c::{ WCONTINUED, WEXITSTATUS, WIFCONTINUED, WIFEXITED, WIFSIGNALED, WIFSTOPPED, WNOHANG, WSTOPSIG, diff --git a/vendor/rustix/src/backend/libc/pty/mod.rs b/vendor/rustix/src/backend/libc/pty/mod.rs new file mode 100644 index 000000000..ef944f04d --- /dev/null +++ b/vendor/rustix/src/backend/libc/pty/mod.rs @@ -0,0 +1 @@ +pub(crate) mod syscalls; diff --git a/vendor/rustix/src/backend/libc/pty/syscalls.rs b/vendor/rustix/src/backend/libc/pty/syscalls.rs new file mode 100644 index 000000000..178201ead --- /dev/null +++ b/vendor/rustix/src/backend/libc/pty/syscalls.rs @@ -0,0 +1,86 @@ +//! libc syscalls supporting `rustix::pty`. + +use crate::backend::c; +use crate::backend::conv::{borrowed_fd, ret}; +use crate::fd::BorrowedFd; +use crate::io; +#[cfg(not(target_os = "android"))] +use {crate::backend::conv::ret_owned_fd, crate::fd::OwnedFd, crate::pty::OpenptFlags}; +#[cfg(any(apple, linux_like, target_os = "freebsd", target_os = "fuchsia"))] +use { + crate::ffi::{CStr, CString}, + crate::path::SMALL_PATH_BUFFER_SIZE, + alloc::borrow::ToOwned, + alloc::vec::Vec, +}; + +#[cfg(not(linux_kernel))] +#[inline] +pub(crate) fn openpt(flags: OpenptFlags) -> io::Result { + unsafe { ret_owned_fd(c::posix_openpt(flags.bits() as _)) } +} + +#[cfg(any(apple, linux_like, target_os = "freebsd", target_os = "fuchsia"))] +#[inline] +pub(crate) fn ptsname(fd: BorrowedFd, mut buffer: Vec) -> io::Result { + // This code would benefit from having a better way to read into + // uninitialized memory, but that requires `unsafe`. + buffer.clear(); + buffer.reserve(SMALL_PATH_BUFFER_SIZE); + buffer.resize(buffer.capacity(), 0_u8); + + loop { + // On platforms with `ptsname_r`, use it. + #[cfg(any(target_os = "freebsd", linux_like, target_os = "fuchsia"))] + let r = unsafe { c::ptsname_r(borrowed_fd(fd), buffer.as_mut_ptr().cast(), buffer.len()) }; + + // MacOS 10.13.4 has `ptsname_r`; use it if we have it, otherwise fall + // back to calling the underlying ioctl directly. + #[cfg(apple)] + let r = unsafe { + weak! { fn ptsname_r(c::c_int, *mut c::c_char, c::size_t) -> c::c_int } + + if let Some(libc_ptsname_r) = ptsname_r.get() { + libc_ptsname_r(borrowed_fd(fd), buffer.as_mut_ptr().cast(), buffer.len()) + } else { + // The size declared in the `TIOCPTYGNAME` macro in sys/ttycom.h is 128. + let mut name: [u8; 128] = [0_u8; 128]; + match c::ioctl(borrowed_fd(fd), c::TIOCPTYGNAME as u64, &mut name) { + 0 => { + let len = CStr::from_ptr(name.as_ptr().cast()).to_bytes().len(); + std::ptr::copy_nonoverlapping(name.as_ptr(), buffer.as_mut_ptr(), len + 1); + 0 + } + _ => libc_errno::errno().0, + } + } + }; + + if r == 0 { + return Ok(unsafe { CStr::from_ptr(buffer.as_ptr().cast()).to_owned() }); + } + if r != c::ERANGE { + return Err(io::Errno::from_raw_os_error(r)); + } + + buffer.reserve(1); // use `Vec` reallocation strategy to grow capacity exponentially + buffer.resize(buffer.capacity(), 0_u8); + } +} + +#[inline] +pub(crate) fn unlockpt(fd: BorrowedFd) -> io::Result<()> { + unsafe { ret(c::unlockpt(borrowed_fd(fd))) } +} + +#[cfg(not(linux_kernel))] +#[inline] +pub(crate) fn grantpt(fd: BorrowedFd) -> io::Result<()> { + unsafe { ret(c::grantpt(borrowed_fd(fd))) } +} + +#[cfg(target_os = "linux")] +#[inline] +pub(crate) fn ioctl_tiocgptpeer(fd: BorrowedFd, flags: OpenptFlags) -> io::Result { + unsafe { ret_owned_fd(c::ioctl(borrowed_fd(fd), c::TIOCGPTPEER, flags.bits())) } +} diff --git a/vendor/rustix/src/backend/libc/rand/syscalls.rs b/vendor/rustix/src/backend/libc/rand/syscalls.rs index 2dcff139e..8a995f2e6 100644 --- a/vendor/rustix/src/backend/libc/rand/syscalls.rs +++ b/vendor/rustix/src/backend/libc/rand/syscalls.rs @@ -1,9 +1,9 @@ //! libc syscalls supporting `rustix::rand`. -#[cfg(any(target_os = "android", target_os = "linux"))] -use {super::super::c, super::super::conv::ret_usize, crate::io, crate::rand::GetRandomFlags}; +#[cfg(linux_kernel)] +use {crate::backend::c, crate::backend::conv::ret_usize, crate::io, crate::rand::GetRandomFlags}; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub(crate) fn getrandom(buf: &mut [u8], flags: GetRandomFlags) -> io::Result { // `getrandom` wasn't supported in glibc until 2.25. weak_or_syscall! { diff --git a/vendor/rustix/src/backend/libc/rand/types.rs b/vendor/rustix/src/backend/libc/rand/types.rs index e12bd9cbd..730cf3a34 100644 --- a/vendor/rustix/src/backend/libc/rand/types.rs +++ b/vendor/rustix/src/backend/libc/rand/types.rs @@ -1,13 +1,15 @@ -#[cfg(any(target_os = "android", target_os = "linux"))] -use super::super::c; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] +use crate::backend::c; +#[cfg(linux_kernel)] use bitflags::bitflags; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] bitflags! { /// `GRND_*` flags for use with [`getrandom`]. /// /// [`getrandom`]: crate::rand::getrandom + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct GetRandomFlags: u32 { /// `GRND_RANDOM` const RANDOM = c::GRND_RANDOM; diff --git a/vendor/rustix/src/backend/libc/system/mod.rs b/vendor/rustix/src/backend/libc/system/mod.rs new file mode 100644 index 000000000..bff7fd564 --- /dev/null +++ b/vendor/rustix/src/backend/libc/system/mod.rs @@ -0,0 +1,3 @@ +#[cfg(not(windows))] +pub(crate) mod syscalls; +pub(crate) mod types; diff --git a/vendor/rustix/src/backend/libc/system/syscalls.rs b/vendor/rustix/src/backend/libc/system/syscalls.rs new file mode 100644 index 000000000..a731e9302 --- /dev/null +++ b/vendor/rustix/src/backend/libc/system/syscalls.rs @@ -0,0 +1,40 @@ +//! libc syscalls supporting `rustix::process`. + +use super::types::RawUname; +use crate::backend::c; +#[cfg(not(target_os = "wasi"))] +use crate::backend::conv::ret_infallible; +#[cfg(linux_kernel)] +use crate::system::Sysinfo; +use core::mem::MaybeUninit; +#[cfg(not(any(target_os = "emscripten", target_os = "redox", target_os = "wasi")))] +use {crate::backend::conv::ret, crate::io}; + +#[cfg(not(target_os = "wasi"))] +#[inline] +pub(crate) fn uname() -> RawUname { + let mut uname = MaybeUninit::::uninit(); + unsafe { + ret_infallible(c::uname(uname.as_mut_ptr())); + uname.assume_init() + } +} + +#[cfg(linux_kernel)] +pub(crate) fn sysinfo() -> Sysinfo { + let mut info = MaybeUninit::::uninit(); + unsafe { + ret_infallible(c::sysinfo(info.as_mut_ptr())); + info.assume_init() + } +} + +#[cfg(not(any(target_os = "emscripten", target_os = "redox", target_os = "wasi")))] +pub(crate) fn sethostname(name: &[u8]) -> io::Result<()> { + unsafe { + ret(c::sethostname( + name.as_ptr().cast(), + name.len().try_into().map_err(|_| io::Errno::INVAL)?, + )) + } +} diff --git a/vendor/rustix/src/backend/libc/system/types.rs b/vendor/rustix/src/backend/libc/system/types.rs new file mode 100644 index 000000000..731e89bed --- /dev/null +++ b/vendor/rustix/src/backend/libc/system/types.rs @@ -0,0 +1,8 @@ +use crate::backend::c; + +/// `sysinfo` +#[cfg(linux_kernel)] +pub type Sysinfo = c::sysinfo; + +#[cfg(not(target_os = "wasi"))] +pub(crate) type RawUname = c::utsname; diff --git a/vendor/rustix/src/backend/libc/termios/mod.rs b/vendor/rustix/src/backend/libc/termios/mod.rs index c82c95958..ef944f04d 100644 --- a/vendor/rustix/src/backend/libc/termios/mod.rs +++ b/vendor/rustix/src/backend/libc/termios/mod.rs @@ -1,3 +1 @@ pub(crate) mod syscalls; -#[cfg(not(target_os = "wasi"))] -pub(crate) mod types; diff --git a/vendor/rustix/src/backend/libc/termios/syscalls.rs b/vendor/rustix/src/backend/libc/termios/syscalls.rs index dba73c960..d4182f4fe 100644 --- a/vendor/rustix/src/backend/libc/termios/syscalls.rs +++ b/vendor/rustix/src/backend/libc/termios/syscalls.rs @@ -4,46 +4,62 @@ //! //! See the `rustix::backend::syscalls` module documentation for details. -use super::super::c; -use super::super::conv::{borrowed_fd, ret, ret_pid_t}; +use crate::backend::c; +use crate::backend::conv::{borrowed_fd, ret, ret_pid_t}; use crate::fd::BorrowedFd; #[cfg(feature = "procfs")] #[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] use crate::ffi::CStr; -#[cfg(not(target_os = "wasi"))] -use crate::io; -#[cfg(not(target_os = "wasi"))] -use crate::process::{Pid, RawNonZeroPid}; -#[cfg(not(target_os = "wasi"))] -use crate::termios::{Action, OptionalActions, QueueSelector, Speed, Termios, Winsize}; use core::mem::MaybeUninit; +#[cfg(not(target_os = "wasi"))] +use { + crate::io, + crate::pid::Pid, + crate::termios::{Action, OptionalActions, QueueSelector, Termios, Winsize}, + crate::utils::as_mut_ptr, +}; #[cfg(not(target_os = "wasi"))] pub(crate) fn tcgetattr(fd: BorrowedFd<'_>) -> io::Result { - let mut result = MaybeUninit::::uninit(); + // If we have `TCGETS2`, use it, so that we fill in the `c_ispeed` and + // `c_ospeed` fields. + #[cfg(linux_kernel)] unsafe { - ret(c::tcgetattr(borrowed_fd(fd), result.as_mut_ptr()))?; - Ok(result.assume_init()) + use crate::termios::{ControlModes, InputModes, LocalModes, OutputModes, SpecialCodes}; + use core::mem::zeroed; + + let mut termios2 = MaybeUninit::::uninit(); + + ret(c::ioctl( + borrowed_fd(fd), + c::TCGETS2.into(), + termios2.as_mut_ptr(), + ))?; + + let termios2 = termios2.assume_init(); + + // Convert from the Linux `termios2` to our `Termios`. + let mut result = Termios { + input_modes: InputModes::from_bits_retain(termios2.c_iflag), + output_modes: OutputModes::from_bits_retain(termios2.c_oflag), + control_modes: ControlModes::from_bits_retain(termios2.c_cflag), + local_modes: LocalModes::from_bits_retain(termios2.c_lflag), + line_discipline: termios2.c_line, + special_codes: SpecialCodes(zeroed()), + input_speed: termios2.c_ispeed, + output_speed: termios2.c_ospeed, + }; + result.special_codes.0[..termios2.c_cc.len()].copy_from_slice(&termios2.c_cc); + + Ok(result) } -} -#[cfg(all( - any(target_os = "android", target_os = "linux"), - any( - target_arch = "x86", - target_arch = "x86_64", - target_arch = "x32", - target_arch = "riscv64", - target_arch = "aarch64", - target_arch = "arm", - target_arch = "mips", - target_arch = "mips64", - ) -))] -pub(crate) fn tcgetattr2(fd: BorrowedFd<'_>) -> io::Result { - let mut result = MaybeUninit::::uninit(); + #[cfg(not(linux_kernel))] unsafe { - ret(c::ioctl(borrowed_fd(fd), c::TCGETS2, result.as_mut_ptr()))?; + let mut result = MaybeUninit::::uninit(); + + ret(c::tcgetattr(borrowed_fd(fd), result.as_mut_ptr().cast()))?; + Ok(result.assume_init()) } } @@ -52,8 +68,7 @@ pub(crate) fn tcgetattr2(fd: BorrowedFd<'_>) -> io::Result) -> io::Result { unsafe { let pid = ret_pid_t(c::tcgetpgrp(borrowed_fd(fd)))?; - debug_assert_ne!(pid, 0); - Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid))) + Ok(Pid::from_raw_unchecked(pid)) } } @@ -68,38 +83,65 @@ pub(crate) fn tcsetattr( optional_actions: OptionalActions, termios: &Termios, ) -> io::Result<()> { + // If we have `TCSETS2`, use it, so that we use the `c_ispeed` and + // `c_ospeed` fields. + #[cfg(linux_kernel)] unsafe { - ret(c::tcsetattr( - borrowed_fd(fd), - optional_actions as _, - termios, - )) + use crate::termios::speed; + use core::mem::zeroed; + use linux_raw_sys::general::{termios2, BOTHER, CBAUD, IBSHIFT}; + + #[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))] + use linux_raw_sys::ioctl::{TCSETS, TCSETS2}; + + // linux-raw-sys' ioctl-generation script for sparc isn't working yet, + // so as a temporary workaround, declare these manually. + #[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] + const TCSETS: u32 = 0x80245409; + #[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] + const TCSETS2: u32 = 0x802c540d; + + // Translate from `optional_actions` into an ioctl request code. On MIPS, + // `optional_actions` already has `TCGETS` added to it. + let request = TCSETS2 + + if cfg!(any(target_arch = "mips", target_arch = "mips64")) { + optional_actions as u32 - TCSETS + } else { + optional_actions as u32 + }; + + let input_speed = termios.input_speed(); + let output_speed = termios.output_speed(); + let mut termios2 = termios2 { + c_iflag: termios.input_modes.bits(), + c_oflag: termios.output_modes.bits(), + c_cflag: termios.control_modes.bits(), + c_lflag: termios.local_modes.bits(), + c_line: termios.line_discipline, + c_cc: zeroed(), + c_ispeed: input_speed, + c_ospeed: output_speed, + }; + // Ensure that our input and output speeds are set, as `libc` + // routines don't always support setting these separately. + termios2.c_cflag &= !CBAUD; + termios2.c_cflag |= speed::encode(output_speed).unwrap_or(BOTHER); + termios2.c_cflag &= !(CBAUD << IBSHIFT); + termios2.c_cflag |= speed::encode(input_speed).unwrap_or(BOTHER) << IBSHIFT; + let nccs = termios2.c_cc.len(); + termios2 + .c_cc + .copy_from_slice(&termios.special_codes.0[..nccs]); + + ret(c::ioctl(borrowed_fd(fd), request as _, &termios2)) } -} -#[cfg(all( - any(target_os = "android", target_os = "linux"), - any( - target_arch = "x86", - target_arch = "x86_64", - target_arch = "x32", - target_arch = "riscv64", - target_arch = "aarch64", - target_arch = "arm", - target_arch = "mips", - target_arch = "mips64", - ) -))] -pub(crate) fn tcsetattr2( - fd: BorrowedFd, - optional_actions: OptionalActions, - termios: &crate::termios::Termios2, -) -> io::Result<()> { + #[cfg(not(linux_kernel))] unsafe { - ret(c::ioctl( + ret(c::tcsetattr( borrowed_fd(fd), - (c::TCSETS2 as u32 + optional_actions as u32) as _, - termios, + optional_actions as _, + crate::utils::as_ptr(termios).cast(), )) } } @@ -128,8 +170,7 @@ pub(crate) fn tcflow(fd: BorrowedFd, action: Action) -> io::Result<()> { pub(crate) fn tcgetsid(fd: BorrowedFd) -> io::Result { unsafe { let pid = ret_pid_t(c::tcgetsid(borrowed_fd(fd)))?; - debug_assert_ne!(pid, 0); - Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid))) + Ok(Pid::from_raw_unchecked(pid)) } } @@ -151,42 +192,142 @@ pub(crate) fn tcgetwinsize(fd: BorrowedFd) -> io::Result { } } -#[cfg(not(target_os = "wasi"))] -#[inline] -#[must_use] -pub(crate) fn cfgetospeed(termios: &Termios) -> Speed { - unsafe { c::cfgetospeed(termios) } +#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] +pub(crate) fn ioctl_tiocexcl(fd: BorrowedFd) -> io::Result<()> { + unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCEXCL as _)) } } -#[cfg(not(target_os = "wasi"))] -#[inline] -#[must_use] -pub(crate) fn cfgetispeed(termios: &Termios) -> Speed { - unsafe { c::cfgetispeed(termios) } +#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] +pub(crate) fn ioctl_tiocnxcl(fd: BorrowedFd) -> io::Result<()> { + unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCNXCL as _)) } } #[cfg(not(target_os = "wasi"))] #[inline] -pub(crate) fn cfmakeraw(termios: &mut Termios) { - unsafe { c::cfmakeraw(termios) } +pub(crate) fn set_speed(termios: &mut Termios, arbitrary_speed: u32) -> io::Result<()> { + #[cfg(bsd)] + let encoded_speed = arbitrary_speed; + + #[cfg(not(bsd))] + let encoded_speed = match crate::termios::speed::encode(arbitrary_speed) { + Some(encoded_speed) => encoded_speed, + #[cfg(linux_kernel)] + None => c::BOTHER, + #[cfg(not(linux_kernel))] + None => return Err(io::Errno::INVAL), + }; + + #[cfg(not(linux_kernel))] + unsafe { + ret(c::cfsetspeed( + as_mut_ptr(termios).cast(), + encoded_speed.into(), + )) + } + + // Linux libc implementations don't support arbitrary speeds, so we encode + // the speed manually. + #[cfg(linux_kernel)] + { + use crate::termios::ControlModes; + + debug_assert_eq!(encoded_speed & !c::CBAUD, 0); + + termios.control_modes -= ControlModes::from_bits_retain(c::CBAUD | c::CIBAUD); + termios.control_modes |= + ControlModes::from_bits_retain(encoded_speed | (encoded_speed << c::IBSHIFT)); + + termios.input_speed = arbitrary_speed; + termios.output_speed = arbitrary_speed; + + Ok(()) + } } #[cfg(not(target_os = "wasi"))] #[inline] -pub(crate) fn cfsetospeed(termios: &mut Termios, speed: Speed) -> io::Result<()> { - unsafe { ret(c::cfsetospeed(termios, speed)) } +pub(crate) fn set_output_speed(termios: &mut Termios, arbitrary_speed: u32) -> io::Result<()> { + #[cfg(bsd)] + let encoded_speed = arbitrary_speed; + + #[cfg(not(bsd))] + let encoded_speed = match crate::termios::speed::encode(arbitrary_speed) { + Some(encoded_speed) => encoded_speed, + #[cfg(linux_kernel)] + None => c::BOTHER, + #[cfg(not(linux_kernel))] + None => return Err(io::Errno::INVAL), + }; + + #[cfg(not(linux_kernel))] + unsafe { + ret(c::cfsetospeed( + as_mut_ptr(termios).cast(), + encoded_speed.into(), + )) + } + + // Linux libc implementations don't support arbitrary speeds or setting the + // input and output speeds separately, so we encode the speed manually. + #[cfg(linux_kernel)] + { + use crate::termios::ControlModes; + + debug_assert_eq!(encoded_speed & !c::CBAUD, 0); + + termios.control_modes -= ControlModes::from_bits_retain(c::CBAUD); + termios.control_modes |= ControlModes::from_bits_retain(encoded_speed); + + termios.output_speed = arbitrary_speed; + + Ok(()) + } } #[cfg(not(target_os = "wasi"))] #[inline] -pub(crate) fn cfsetispeed(termios: &mut Termios, speed: Speed) -> io::Result<()> { - unsafe { ret(c::cfsetispeed(termios, speed)) } +pub(crate) fn set_input_speed(termios: &mut Termios, arbitrary_speed: u32) -> io::Result<()> { + #[cfg(bsd)] + let encoded_speed = arbitrary_speed; + + #[cfg(not(bsd))] + let encoded_speed = match crate::termios::speed::encode(arbitrary_speed) { + Some(encoded_speed) => encoded_speed, + #[cfg(linux_kernel)] + None => c::BOTHER, + #[cfg(not(linux_kernel))] + None => return Err(io::Errno::INVAL), + }; + + #[cfg(not(linux_kernel))] + unsafe { + ret(c::cfsetispeed( + as_mut_ptr(termios).cast(), + encoded_speed.into(), + )) + } + + // Linux libc implementations don't support arbitrary speeds or setting the + // input and output speeds separately, so we encode the speed manually. + #[cfg(linux_kernel)] + { + use crate::termios::ControlModes; + + debug_assert_eq!(encoded_speed & !c::CBAUD, 0); + + termios.control_modes -= ControlModes::from_bits_retain(c::CIBAUD); + termios.control_modes |= ControlModes::from_bits_retain(encoded_speed << c::IBSHIFT); + + termios.input_speed = arbitrary_speed; + + Ok(()) + } } #[cfg(not(target_os = "wasi"))] #[inline] -pub(crate) fn cfsetspeed(termios: &mut Termios, speed: Speed) -> io::Result<()> { - unsafe { ret(c::cfsetspeed(termios, speed)) } +pub(crate) fn cfmakeraw(termios: &mut Termios) { + unsafe { c::cfmakeraw(as_mut_ptr(termios).cast()) } } pub(crate) fn isatty(fd: BorrowedFd<'_>) -> bool { @@ -200,7 +341,7 @@ pub(crate) fn isatty(fd: BorrowedFd<'_>) -> bool { #[cfg(feature = "procfs")] #[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] -pub(crate) fn ttyname(dirfd: BorrowedFd<'_>, buf: &mut [u8]) -> io::Result { +pub(crate) fn ttyname(dirfd: BorrowedFd<'_>, buf: &mut [MaybeUninit]) -> io::Result { unsafe { // `ttyname_r` returns its error status rather than using `errno`. match c::ttyname_r(borrowed_fd(dirfd), buf.as_mut_ptr().cast(), buf.len()) { diff --git a/vendor/rustix/src/backend/libc/termios/types.rs b/vendor/rustix/src/backend/libc/termios/types.rs deleted file mode 100644 index fdb7fc644..000000000 --- a/vendor/rustix/src/backend/libc/termios/types.rs +++ /dev/null @@ -1,736 +0,0 @@ -use super::super::c; - -/// `TCSA*` values for use with [`tcsetattr`]. -/// -/// [`tcsetattr`]: crate::termios::tcsetattr -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[repr(i32)] -pub enum OptionalActions { - /// `TCSANOW`—Make the change immediately. - #[doc(alias = "TCSANOW")] - Now = c::TCSANOW, - - /// `TCSADRAIN`—Make the change after all output has been transmitted. - #[doc(alias = "TCSADRAIN")] - Drain = c::TCSADRAIN, - - /// `TCSAFLUSH`—Discard any pending input and then make the change - /// after all output has been transmitted. - #[doc(alias = "TCSAFLUSH")] - Flush = c::TCSAFLUSH, -} - -/// `TC*` values for use with [`tcflush`]. -/// -/// [`tcflush`]: crate::termios::tcflush -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[repr(i32)] -pub enum QueueSelector { - /// `TCIFLUSH`—Flush data received but not read. - #[doc(alias = "TCIFLUSH")] - IFlush = c::TCIFLUSH, - - /// `TCOFLUSH`—Flush data written but not transmitted. - #[doc(alias = "TCOFLUSH")] - OFlush = c::TCOFLUSH, - - /// `TCIOFLUSH`—`IFlush` and `OFlush` combined. - #[doc(alias = "TCIOFLUSH")] - IOFlush = c::TCIOFLUSH, -} - -/// `TC*` values for use with [`tcflow`]. -/// -/// [`tcflow`]: crate::termios::tcflow -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[repr(i32)] -pub enum Action { - /// `TCOOFF`—Suspend output. - #[doc(alias = "TCOOFF")] - OOff = c::TCOOFF, - - /// `TCOON`—Restart suspended output. - #[doc(alias = "TCOON")] - OOn = c::TCOON, - - /// `TCIOFF`—Transmits a STOP byte. - #[doc(alias = "TCIOFF")] - IOff = c::TCIOFF, - - /// `TCION`—Transmits a START byte. - #[doc(alias = "TCION")] - IOn = c::TCION, -} - -/// `struct termios` for use with [`tcgetattr`] and [`tcsetattr`]. -/// -/// [`tcgetattr`]: crate::termios::tcgetattr -/// [`tcsetattr`]: crate::termios::tcsetattr -#[doc(alias = "termios")] -pub type Termios = c::termios; - -/// `struct termios2` for use with [`tcgetattr2`] and [`tcsetattr2`]. -/// -/// [`tcgetattr2`]: crate::termios::tcgetattr2 -/// [`tcsetattr2`]: crate::termios::tcsetattr2 -#[cfg(all( - any(target_os = "android", target_os = "linux"), - any( - target_arch = "x86", - target_arch = "x86_64", - target_arch = "x32", - target_arch = "riscv64", - target_arch = "aarch64", - target_arch = "arm", - target_arch = "mips", - target_arch = "mips64", - ) -))] -#[doc(alias = "termios2")] -pub type Termios2 = c::termios2; - -/// `struct winsize` for use with [`tcgetwinsize`]. -/// -/// [`tcgetwinsize`]: crate::termios::tcgetwinsize -#[doc(alias = "winsize")] -pub type Winsize = c::winsize; - -/// `tcflag_t`—A type for the flags fields of [`Termios`]. -#[doc(alias = "tcflag_t")] -pub type Tcflag = c::tcflag_t; - -/// `speed_t`—A return type for [`cfsetspeed`] and similar. -/// -/// [`cfsetspeed`]: crate::termios::cfsetspeed -#[doc(alias = "speed_t")] -pub type Speed = c::speed_t; - -/// `VINTR` -pub const VINTR: usize = c::VINTR as usize; - -/// `VQUIT` -pub const VQUIT: usize = c::VQUIT as usize; - -/// `VERASE` -pub const VERASE: usize = c::VERASE as usize; - -/// `VKILL` -pub const VKILL: usize = c::VKILL as usize; - -/// `VEOF` -pub const VEOF: usize = c::VEOF as usize; - -/// `VTIME` -pub const VTIME: usize = c::VTIME as usize; - -/// `VMIN` -pub const VMIN: usize = c::VMIN as usize; - -/// `VSWTC` -#[cfg(not(any( - apple, - solarish, - target_os = "aix", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "haiku", - target_os = "netbsd", - target_os = "openbsd", -)))] -pub const VSWTC: usize = c::VSWTC as usize; - -/// `VSTART` -pub const VSTART: usize = c::VSTART as usize; - -/// `VSTOP` -pub const VSTOP: usize = c::VSTOP as usize; - -/// `VSUSP` -pub const VSUSP: usize = c::VSUSP as usize; - -/// `VEOL` -pub const VEOL: usize = c::VEOL as usize; - -/// `VREPRINT` -#[cfg(not(target_os = "haiku"))] -pub const VREPRINT: usize = c::VREPRINT as usize; - -/// `VDISCARD` -#[cfg(not(any(target_os = "aix", target_os = "haiku")))] -pub const VDISCARD: usize = c::VDISCARD as usize; - -/// `VWERASE` -#[cfg(not(any(target_os = "aix", target_os = "haiku")))] -pub const VWERASE: usize = c::VWERASE as usize; - -/// `VLNEXT` -#[cfg(not(target_os = "haiku"))] -pub const VLNEXT: usize = c::VLNEXT as usize; - -/// `VEOL2` -pub const VEOL2: usize = c::VEOL2 as usize; - -/// `IGNBRK` -pub const IGNBRK: Tcflag = c::IGNBRK; - -/// `BRKINT` -pub const BRKINT: Tcflag = c::BRKINT; - -/// `IGNPAR` -pub const IGNPAR: Tcflag = c::IGNPAR; - -/// `PARMRK` -pub const PARMRK: Tcflag = c::PARMRK; - -/// `INPCK` -pub const INPCK: Tcflag = c::INPCK; - -/// `ISTRIP` -pub const ISTRIP: Tcflag = c::ISTRIP; - -/// `INLCR` -pub const INLCR: Tcflag = c::INLCR; - -/// `IGNCR` -pub const IGNCR: Tcflag = c::IGNCR; - -/// `ICRNL` -pub const ICRNL: Tcflag = c::ICRNL; - -/// `IUCLC` -#[cfg(any(solarish, target_os = "haiku"))] -pub const IUCLC: Tcflag = c::IUCLC; - -/// `IXON` -pub const IXON: Tcflag = c::IXON; - -/// `IXANY` -#[cfg(not(target_os = "redox"))] -pub const IXANY: Tcflag = c::IXANY; - -/// `IXOFF` -pub const IXOFF: Tcflag = c::IXOFF; - -/// `IMAXBEL` -#[cfg(not(any(target_os = "haiku", target_os = "redox")))] -pub const IMAXBEL: Tcflag = c::IMAXBEL; - -/// `IUTF8` -#[cfg(not(any( - solarish, - target_os = "aix", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "haiku", - target_os = "netbsd", - target_os = "openbsd", - target_os = "redox", -)))] -pub const IUTF8: Tcflag = c::IUTF8; - -/// `OPOST` -pub const OPOST: Tcflag = c::OPOST; - -/// `OLCUC` -#[cfg(not(any( - apple, - target_os = "aix", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "netbsd", - target_os = "redox", -)))] -pub const OLCUC: Tcflag = c::OLCUC; - -/// `ONLCR` -pub const ONLCR: Tcflag = c::ONLCR; - -/// `OCRNL` -pub const OCRNL: Tcflag = c::OCRNL; - -/// `ONOCR` -pub const ONOCR: Tcflag = c::ONOCR; - -/// `ONLRET` -pub const ONLRET: Tcflag = c::ONLRET; - -/// `OFILL` -#[cfg(not(bsd))] -pub const OFILL: Tcflag = c::OFILL; - -/// `OFDEL` -#[cfg(not(bsd))] -pub const OFDEL: Tcflag = c::OFDEL; - -/// `NLDLY` -#[cfg(not(any(bsd, solarish, target_os = "redox")))] -pub const NLDLY: Tcflag = c::NLDLY; - -/// `NL0` -#[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] -pub const NL0: Tcflag = c::NL0; - -/// `NL1` -#[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] -pub const NL1: Tcflag = c::NL1; - -/// `CRDLY` -#[cfg(not(any(bsd, solarish, target_os = "redox")))] -pub const CRDLY: Tcflag = c::CRDLY; - -/// `CR0` -#[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] -pub const CR0: Tcflag = c::CR0; - -/// `CR1` -#[cfg(not(any( - target_env = "musl", - bsd, - solarish, - target_os = "emscripten", - target_os = "fuchsia", - target_os = "redox", -)))] -pub const CR1: Tcflag = c::CR1; - -/// `CR2` -#[cfg(not(any( - target_env = "musl", - bsd, - solarish, - target_os = "emscripten", - target_os = "fuchsia", - target_os = "redox", -)))] -pub const CR2: Tcflag = c::CR2; - -/// `CR3` -#[cfg(not(any( - target_env = "musl", - bsd, - solarish, - target_os = "emscripten", - target_os = "fuchsia", - target_os = "redox", -)))] -pub const CR3: Tcflag = c::CR3; - -/// `TABDLY` -#[cfg(not(any(netbsdlike, solarish, target_os = "dragonfly", target_os = "redox",)))] -pub const TABDLY: Tcflag = c::TABDLY; - -/// `TAB0` -#[cfg(not(any( - netbsdlike, - solarish, - target_os = "dragonfly", - target_os = "fuchsia", - target_os = "redox", -)))] -pub const TAB0: Tcflag = c::TAB0; - -/// `TAB1` -#[cfg(not(any( - target_env = "musl", - bsd, - solarish, - target_os = "emscripten", - target_os = "fuchsia", - target_os = "redox", -)))] -pub const TAB1: Tcflag = c::TAB1; - -/// `TAB2` -#[cfg(not(any( - target_env = "musl", - bsd, - solarish, - target_os = "emscripten", - target_os = "fuchsia", - target_os = "redox", -)))] -pub const TAB2: Tcflag = c::TAB2; - -/// `TAB3` -#[cfg(not(any( - target_env = "musl", - bsd, - solarish, - target_os = "emscripten", - target_os = "fuchsia", - target_os = "redox", -)))] -pub const TAB3: Tcflag = c::TAB3; - -/// `BSDLY` -#[cfg(not(any(bsd, solarish, target_os = "redox")))] -pub const BSDLY: Tcflag = c::BSDLY; - -/// `BS0` -#[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] -pub const BS0: Tcflag = c::BS0; - -/// `BS1` -#[cfg(not(any( - target_env = "musl", - bsd, - solarish, - target_os = "emscripten", - target_os = "fuchsia", - target_os = "redox", -)))] -pub const BS1: Tcflag = c::BS1; - -/// `FFDLY` -#[cfg(not(any(target_env = "musl", bsd, solarish, target_os = "redox")))] -pub const FFDLY: Tcflag = c::FFDLY; - -/// `FF0` -#[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] -pub const FF0: Tcflag = c::FF0; - -/// `FF1` -#[cfg(not(any( - target_env = "musl", - bsd, - solarish, - target_os = "emscripten", - target_os = "fuchsia", - target_os = "redox", -)))] -pub const FF1: Tcflag = c::FF1; - -/// `VTDLY` -#[cfg(not(any(target_env = "musl", bsd, solarish, target_os = "redox")))] -pub const VTDLY: Tcflag = c::VTDLY; - -/// `VT0` -#[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] -pub const VT0: Tcflag = c::VT0; - -/// `VT1` -#[cfg(not(any( - target_env = "musl", - bsd, - solarish, - target_os = "emscripten", - target_os = "fuchsia", - target_os = "redox", -)))] -pub const VT1: Tcflag = c::VT1; - -/// `B0` -pub const B0: Speed = c::B0; - -/// `B50` -pub const B50: Speed = c::B50; - -/// `B75` -pub const B75: Speed = c::B75; - -/// `B110` -pub const B110: Speed = c::B110; - -/// `B134` -pub const B134: Speed = c::B134; - -/// `B150` -pub const B150: Speed = c::B150; - -/// `B200` -pub const B200: Speed = c::B200; - -/// `B300` -pub const B300: Speed = c::B300; - -/// `B600` -pub const B600: Speed = c::B600; - -/// `B1200` -pub const B1200: Speed = c::B1200; - -/// `B1800` -pub const B1800: Speed = c::B1800; - -/// `B2400` -pub const B2400: Speed = c::B2400; - -/// `B4800` -pub const B4800: Speed = c::B4800; - -/// `B9600` -pub const B9600: Speed = c::B9600; - -/// `B19200` -pub const B19200: Speed = c::B19200; - -/// `B38400` -pub const B38400: Speed = c::B38400; - -/// `B57600` -#[cfg(not(target_os = "aix"))] -pub const B57600: Speed = c::B57600; - -/// `B115200` -#[cfg(not(target_os = "aix"))] -pub const B115200: Speed = c::B115200; - -/// `B230400` -#[cfg(not(target_os = "aix"))] -pub const B230400: Speed = c::B230400; - -/// `B460800` -#[cfg(not(any( - apple, - target_os = "aix", - target_os = "dragonfly", - target_os = "haiku", - target_os = "openbsd" -)))] -pub const B460800: Speed = c::B460800; - -/// `B500000` -#[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] -pub const B500000: Speed = c::B500000; - -/// `B576000` -#[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] -pub const B576000: Speed = c::B576000; - -/// `B921600` -#[cfg(not(any( - apple, - target_os = "aix", - target_os = "dragonfly", - target_os = "haiku", - target_os = "openbsd" -)))] -pub const B921600: Speed = c::B921600; - -/// `B1000000` -#[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] -pub const B1000000: Speed = c::B1000000; - -/// `B1152000` -#[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] -pub const B1152000: Speed = c::B1152000; - -/// `B1500000` -#[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] -pub const B1500000: Speed = c::B1500000; - -/// `B2000000` -#[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] -pub const B2000000: Speed = c::B2000000; - -/// `B2500000` -#[cfg(not(any( - target_arch = "sparc", - target_arch = "sparc64", - bsd, - target_os = "aix", - target_os = "haiku", - target_os = "solaris", -)))] -pub const B2500000: Speed = c::B2500000; - -/// `B3000000` -#[cfg(not(any( - target_arch = "sparc", - target_arch = "sparc64", - bsd, - target_os = "aix", - target_os = "haiku", - target_os = "solaris", -)))] -pub const B3000000: Speed = c::B3000000; - -/// `B3500000` -#[cfg(not(any( - target_arch = "sparc", - target_arch = "sparc64", - bsd, - target_os = "aix", - target_os = "haiku", - target_os = "solaris", -)))] -pub const B3500000: Speed = c::B3500000; - -/// `B4000000` -#[cfg(not(any( - target_arch = "sparc", - target_arch = "sparc64", - bsd, - target_os = "aix", - target_os = "haiku", - target_os = "solaris", -)))] -pub const B4000000: Speed = c::B4000000; - -/// `BOTHER` -#[cfg(any(target_os = "android", target_os = "linux"))] -pub const BOTHER: Speed = c::BOTHER; - -/// `CSIZE` -pub const CSIZE: Tcflag = c::CSIZE; - -/// `CS5` -pub const CS5: Tcflag = c::CS5; - -/// `CS6` -pub const CS6: Tcflag = c::CS6; - -/// `CS7` -pub const CS7: Tcflag = c::CS7; - -/// `CS8` -pub const CS8: Tcflag = c::CS8; - -/// `CSTOPB` -pub const CSTOPB: Tcflag = c::CSTOPB; - -/// `CREAD` -pub const CREAD: Tcflag = c::CREAD; - -/// `PARENB` -pub const PARENB: Tcflag = c::PARENB; - -/// `PARODD` -pub const PARODD: Tcflag = c::PARODD; - -/// `HUPCL` -pub const HUPCL: Tcflag = c::HUPCL; - -/// `CLOCAL` -pub const CLOCAL: Tcflag = c::CLOCAL; - -/// `ISIG` -pub const ISIG: Tcflag = c::ISIG; - -/// `ICANON`—A flag for the `c_lflag` field of [`Termios`] indicating -/// canonical mode. -pub const ICANON: Tcflag = c::ICANON; - -/// `ECHO` -pub const ECHO: Tcflag = c::ECHO; - -/// `ECHOE` -pub const ECHOE: Tcflag = c::ECHOE; - -/// `ECHOK` -pub const ECHOK: Tcflag = c::ECHOK; - -/// `ECHONL` -pub const ECHONL: Tcflag = c::ECHONL; - -/// `NOFLSH` -pub const NOFLSH: Tcflag = c::NOFLSH; - -/// `TOSTOP` -pub const TOSTOP: Tcflag = c::TOSTOP; - -/// `IEXTEN` -pub const IEXTEN: Tcflag = c::IEXTEN; - -/// `EXTA` -#[cfg(not(any( - solarish, - target_os = "emscripten", - target_os = "haiku", - target_os = "redox", -)))] -pub const EXTA: Speed = c::EXTA; - -/// `EXTB` -#[cfg(not(any( - solarish, - target_os = "emscripten", - target_os = "haiku", - target_os = "redox", -)))] -pub const EXTB: Speed = c::EXTB; - -/// `CBAUD` -#[cfg(not(any(bsd, target_os = "haiku", target_os = "redox")))] -pub const CBAUD: Tcflag = c::CBAUD; - -/// `CBAUDEX` -#[cfg(not(any( - bsd, - solarish, - target_os = "aix", - target_os = "haiku", - target_os = "redox", -)))] -pub const CBAUDEX: Tcflag = c::CBAUDEX; - -/// `CIBAUD` -#[cfg(not(any( - target_arch = "powerpc", - target_arch = "powerpc64", - bsd, - target_os = "emscripten", - target_os = "haiku", - target_os = "redox", -)))] -pub const CIBAUD: Tcflag = c::CIBAUD; - -/// `CIBAUD` -// glibc on powerpc lacks a definition for `CIBAUD`, even though the Linux -// headers and Musl on powerpc both have one. So define it manually. -#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] -pub const CIBAUD: Tcflag = 0o77600000; - -/// `CMSPAR` -#[cfg(not(any( - bsd, - solarish, - target_os = "aix", - target_os = "emscripten", - target_os = "haiku", - target_os = "redox", -)))] -pub const CMSPAR: Tcflag = c::CMSPAR; - -/// `CRTSCTS` -#[cfg(not(any(target_os = "aix", target_os = "redox")))] -pub const CRTSCTS: Tcflag = c::CRTSCTS; - -/// `XCASE` -#[cfg(any(target_arch = "s390x", target_os = "haiku"))] -pub const XCASE: Tcflag = c::XCASE; - -/// `ECHOCTL` -#[cfg(not(any(target_os = "redox")))] -pub const ECHOCTL: Tcflag = c::ECHOCTL; - -/// `ECHOPRT` -#[cfg(not(any(target_os = "redox")))] -pub const ECHOPRT: Tcflag = c::ECHOPRT; - -/// `ECHOKE` -#[cfg(not(any(target_os = "redox")))] -pub const ECHOKE: Tcflag = c::ECHOKE; - -/// `FLUSHO` -#[cfg(not(any(target_os = "redox")))] -pub const FLUSHO: Tcflag = c::FLUSHO; - -/// `PENDIN` -#[cfg(not(any(target_os = "redox")))] -pub const PENDIN: Tcflag = c::PENDIN; - -/// `EXTPROC` -#[cfg(not(any(target_os = "aix", target_os = "haiku", target_os = "redox")))] -pub const EXTPROC: Tcflag = c::EXTPROC; - -/// `XTABS` -#[cfg(not(any( - bsd, - solarish, - target_os = "aix", - target_os = "haiku", - target_os = "redox", -)))] -pub const XTABS: Tcflag = c::XTABS; diff --git a/vendor/rustix/src/backend/libc/thread/syscalls.rs b/vendor/rustix/src/backend/libc/thread/syscalls.rs index adf4bb700..6066fd0d4 100644 --- a/vendor/rustix/src/backend/libc/thread/syscalls.rs +++ b/vendor/rustix/src/backend/libc/thread/syscalls.rs @@ -1,18 +1,23 @@ //! libc syscalls supporting `rustix::thread`. -use super::super::c; -use super::super::conv::ret; -#[cfg(any(target_os = "android", target_os = "linux"))] -use super::super::conv::{borrowed_fd, ret_c_int, syscall_ret}; -use super::super::time::types::LibcTimespec; -#[cfg(any(target_os = "android", target_os = "linux"))] -use crate::fd::BorrowedFd; +use crate::backend::c; +use crate::backend::conv::ret; use crate::io; -#[cfg(any(target_os = "android", target_os = "linux"))] -use crate::process::{Pid, RawNonZeroPid}; #[cfg(not(target_os = "redox"))] use crate::thread::{NanosleepRelativeResult, Timespec}; +#[cfg(all( + any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), + target_env = "gnu", +))] +use crate::timespec::LibcTimespec; use core::mem::MaybeUninit; +#[cfg(linux_kernel)] +use { + crate::backend::conv::{borrowed_fd, ret_c_int}, + crate::fd::BorrowedFd, + crate::pid::Pid, + crate::utils::as_mut_ptr, +}; #[cfg(not(any( apple, freebsdlike, @@ -47,16 +52,17 @@ weak!(fn __nanosleep64(*const LibcTimespec, *mut LibcTimespec) -> c::c_int); )))] #[inline] pub(crate) fn clock_nanosleep_relative(id: ClockId, request: &Timespec) -> NanosleepRelativeResult { - let mut remain = MaybeUninit::::uninit(); let flags = 0; - // 32-bit gnu version: libc has `clock_nanosleep` but it is not y2038 safe by - // default. + // 32-bit gnu version: libc has `clock_nanosleep` but it is not y2038 safe + // by default. #[cfg(all( any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), target_env = "gnu", ))] unsafe { + let mut remain = MaybeUninit::::uninit(); + if let Some(libc_clock_nanosleep) = __clock_nanosleep_time64.get() { match libc_clock_nanosleep( id as c::clockid_t, @@ -81,6 +87,8 @@ pub(crate) fn clock_nanosleep_relative(id: ClockId, request: &Timespec) -> Nanos target_env = "gnu", )))] unsafe { + let mut remain = MaybeUninit::::uninit(); + match c::clock_nanosleep(id as c::clockid_t, flags, request, remain.as_mut_ptr()) { 0 => NanosleepRelativeResult::Ok, err if err == io::Errno::INTR.0 => { @@ -96,7 +104,6 @@ pub(crate) fn clock_nanosleep_relative(id: ClockId, request: &Timespec) -> Nanos target_env = "gnu", ))] unsafe fn clock_nanosleep_relative_old(id: ClockId, request: &Timespec) -> NanosleepRelativeResult { - use core::convert::TryInto; let tv_sec = match request.tv_sec.try_into() { Ok(tv_sec) => tv_sec, Err(_) => return NanosleepRelativeResult::Err(io::Errno::OVERFLOW), @@ -142,8 +149,8 @@ unsafe fn clock_nanosleep_relative_old(id: ClockId, request: &Timespec) -> Nanos pub(crate) fn clock_nanosleep_absolute(id: ClockId, request: &Timespec) -> io::Result<()> { let flags = c::TIMER_ABSTIME; - // 32-bit gnu version: libc has `clock_nanosleep` but it is not y2038 safe by - // default. + // 32-bit gnu version: libc has `clock_nanosleep` but it is not y2038 safe + // by default. #[cfg(all( any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), target_env = "gnu", @@ -182,8 +189,6 @@ pub(crate) fn clock_nanosleep_absolute(id: ClockId, request: &Timespec) -> io::R target_env = "gnu", ))] fn clock_nanosleep_absolute_old(id: ClockId, request: &Timespec) -> io::Result<()> { - use core::convert::TryInto; - let flags = c::TIMER_ABSTIME; let old_request = c::timespec { @@ -199,8 +204,6 @@ fn clock_nanosleep_absolute_old(id: ClockId, request: &Timespec) -> io::Result<( #[cfg(not(target_os = "redox"))] #[inline] pub(crate) fn nanosleep(request: &Timespec) -> NanosleepRelativeResult { - let mut remain = MaybeUninit::::uninit(); - // 32-bit gnu version: libc has `nanosleep` but it is not y2038 safe by // default. #[cfg(all( @@ -208,6 +211,8 @@ pub(crate) fn nanosleep(request: &Timespec) -> NanosleepRelativeResult { target_env = "gnu", ))] unsafe { + let mut remain = MaybeUninit::::uninit(); + if let Some(libc_nanosleep) = __nanosleep64.get() { match ret(libc_nanosleep(&request.clone().into(), remain.as_mut_ptr())) { Ok(()) => NanosleepRelativeResult::Ok, @@ -227,6 +232,8 @@ pub(crate) fn nanosleep(request: &Timespec) -> NanosleepRelativeResult { target_env = "gnu", )))] unsafe { + let mut remain = MaybeUninit::::uninit(); + match ret(c::nanosleep(request, remain.as_mut_ptr())) { Ok(()) => NanosleepRelativeResult::Ok, Err(io::Errno::INTR) => NanosleepRelativeResult::Interrupted(remain.assume_init()), @@ -240,7 +247,6 @@ pub(crate) fn nanosleep(request: &Timespec) -> NanosleepRelativeResult { target_env = "gnu", ))] unsafe fn nanosleep_old(request: &Timespec) -> NanosleepRelativeResult { - use core::convert::TryInto; let tv_sec = match request.tv_sec.try_into() { Ok(tv_sec) => tv_sec, Err(_) => return NanosleepRelativeResult::Err(io::Errno::OVERFLOW), @@ -266,7 +272,7 @@ unsafe fn nanosleep_old(request: &Timespec) -> NanosleepRelativeResult { } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] #[must_use] pub(crate) fn gettid() -> Pid { @@ -279,12 +285,11 @@ pub(crate) fn gettid() -> Pid { unsafe { let tid = gettid(); - debug_assert_ne!(tid, 0); - Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(tid)) + Pid::from_raw_unchecked(tid) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] pub(crate) fn setns(fd: BorrowedFd, nstype: c::c_int) -> io::Result { // `setns` wasn't supported in glibc until 2.14, and musl until 0.9.5, @@ -296,68 +301,104 @@ pub(crate) fn setns(fd: BorrowedFd, nstype: c::c_int) -> io::Result { unsafe { ret_c_int(setns(borrowed_fd(fd), nstype)) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] pub(crate) fn unshare(flags: crate::thread::UnshareFlags) -> io::Result<()> { unsafe { ret(c::unshare(flags.bits() as i32)) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] pub(crate) fn capget( header: &mut linux_raw_sys::general::__user_cap_header_struct, data: &mut [MaybeUninit], ) -> io::Result<()> { - let header: *mut _ = header; - unsafe { syscall_ret(c::syscall(c::SYS_capget, header, data.as_mut_ptr())) } + syscall! { + fn capget( + hdrp: *mut linux_raw_sys::general::__user_cap_header_struct, + data: *mut linux_raw_sys::general::__user_cap_data_struct + ) via SYS_capget -> c::c_int + } + + unsafe { + ret(capget( + as_mut_ptr(header), + data.as_mut_ptr() + .cast::(), + )) + } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] pub(crate) fn capset( header: &mut linux_raw_sys::general::__user_cap_header_struct, data: &[linux_raw_sys::general::__user_cap_data_struct], ) -> io::Result<()> { - let header: *mut _ = header; - unsafe { syscall_ret(c::syscall(c::SYS_capset, header, data.as_ptr())) } + syscall! { + fn capset( + hdrp: *mut linux_raw_sys::general::__user_cap_header_struct, + data: *const linux_raw_sys::general::__user_cap_data_struct + ) via SYS_capset -> c::c_int + } + + unsafe { ret(capset(as_mut_ptr(header), data.as_ptr())) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] -pub(crate) fn setuid_thread(uid: crate::process::Uid) -> io::Result<()> { - unsafe { syscall_ret(c::syscall(c::SYS_setuid, uid.as_raw())) } +pub(crate) fn setuid_thread(uid: crate::ugid::Uid) -> io::Result<()> { + syscall! { + fn setuid(uid: c::uid_t) via SYS_setuid -> c::c_int + } + + unsafe { ret(setuid(uid.as_raw())) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] pub(crate) fn setresuid_thread( - ruid: crate::process::Uid, - euid: crate::process::Uid, - suid: crate::process::Uid, + ruid: crate::ugid::Uid, + euid: crate::ugid::Uid, + suid: crate::ugid::Uid, ) -> io::Result<()> { #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc"))] const SYS: c::c_long = c::SYS_setresuid32 as c::c_long; #[cfg(not(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc")))] const SYS: c::c_long = c::SYS_setresuid as c::c_long; - unsafe { syscall_ret(c::syscall(SYS, ruid.as_raw(), euid.as_raw(), suid.as_raw())) } + + syscall! { + fn setresuid(ruid: c::uid_t, euid: c::uid_t, suid: c::uid_t) via SYS -> c::c_int + } + + unsafe { ret(setresuid(ruid.as_raw(), euid.as_raw(), suid.as_raw())) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] -pub(crate) fn setgid_thread(gid: crate::process::Gid) -> io::Result<()> { - unsafe { syscall_ret(c::syscall(c::SYS_setgid, gid.as_raw())) } +pub(crate) fn setgid_thread(gid: crate::ugid::Gid) -> io::Result<()> { + syscall! { + fn setgid(gid: c::gid_t) via SYS_setgid -> c::c_int + } + + unsafe { ret(setgid(gid.as_raw())) } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] pub(crate) fn setresgid_thread( - rgid: crate::process::Gid, - egid: crate::process::Gid, - sgid: crate::process::Gid, + rgid: crate::ugid::Gid, + egid: crate::ugid::Gid, + sgid: crate::ugid::Gid, ) -> io::Result<()> { #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc"))] const SYS: c::c_long = c::SYS_setresgid32 as c::c_long; #[cfg(not(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc")))] const SYS: c::c_long = c::SYS_setresgid as c::c_long; - unsafe { syscall_ret(c::syscall(SYS, rgid.as_raw(), egid.as_raw(), sgid.as_raw())) } + + syscall! { + fn setresgid(rgid: c::gid_t, egid: c::gid_t, sgid: c::gid_t) via SYS -> c::c_int + } + + unsafe { ret(setresgid(rgid.as_raw(), egid.as_raw(), sgid.as_raw())) } } diff --git a/vendor/rustix/src/backend/libc/time/syscalls.rs b/vendor/rustix/src/backend/libc/time/syscalls.rs index 9d341d886..14ca22b2d 100644 --- a/vendor/rustix/src/backend/libc/time/syscalls.rs +++ b/vendor/rustix/src/backend/libc/time/syscalls.rs @@ -1,20 +1,22 @@ //! libc syscalls supporting `rustix::time`. -use super::super::c; -use super::super::conv::ret; -#[cfg(feature = "time")] -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] -use super::super::time::types::LibcItimerspec; -use super::super::time::types::LibcTimespec; -use super::types::Timespec; +use crate::backend::c; +use crate::backend::conv::ret; #[cfg(not(target_os = "wasi"))] -use super::types::{ClockId, DynamicClockId}; +use crate::clockid::{ClockId, DynamicClockId}; use crate::io; +#[cfg(all( + any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), + target_env = "gnu", +))] +use crate::timespec::LibcTimespec; +use crate::timespec::Timespec; use core::mem::MaybeUninit; -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] #[cfg(feature = "time")] use { - super::super::conv::{borrowed_fd, ret_owned_fd}, + crate::backend::conv::{borrowed_fd, ret_owned_fd}, + crate::backend::time::types::LibcItimerspec, crate::fd::{BorrowedFd, OwnedFd}, crate::time::{Itimerspec, TimerfdClockId, TimerfdFlags, TimerfdTimerFlags}, }; @@ -51,8 +53,6 @@ weak!(fn __timerfd_settime64(c::c_int, c::c_int, *const LibcItimerspec, *mut Lib #[inline] #[must_use] pub(crate) fn clock_getres(id: ClockId) -> Timespec { - let mut timespec = MaybeUninit::::uninit(); - // 32-bit gnu version: libc has `clock_getres` but it is not y2038 safe by // default. #[cfg(all( @@ -60,6 +60,8 @@ pub(crate) fn clock_getres(id: ClockId) -> Timespec { target_env = "gnu", ))] unsafe { + let mut timespec = MaybeUninit::::uninit(); + if let Some(libc_clock_getres) = __clock_getres64.get() { ret(libc_clock_getres(id as c::clockid_t, timespec.as_mut_ptr())).unwrap(); timespec.assume_init().into() @@ -74,6 +76,7 @@ pub(crate) fn clock_getres(id: ClockId) -> Timespec { target_env = "gnu", )))] unsafe { + let mut timespec = MaybeUninit::::uninit(); let _ = c::clock_getres(id as c::clockid_t, timespec.as_mut_ptr()); timespec.assume_init() } @@ -102,13 +105,13 @@ unsafe fn clock_getres_old(id: ClockId) -> Timespec { #[inline] #[must_use] pub(crate) fn clock_gettime(id: ClockId) -> Timespec { - let mut timespec = MaybeUninit::::uninit(); - #[cfg(all( any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), target_env = "gnu", ))] unsafe { + let mut timespec = MaybeUninit::::uninit(); + if let Some(libc_clock_gettime) = __clock_gettime64.get() { ret(libc_clock_gettime( id as c::clockid_t, @@ -130,6 +133,7 @@ pub(crate) fn clock_gettime(id: ClockId) -> Timespec { target_env = "gnu", )))] unsafe { + let mut timespec = MaybeUninit::::uninit(); ret(c::clock_gettime(id as c::clockid_t, timespec.as_mut_ptr())).unwrap(); timespec.assume_init() } @@ -157,34 +161,33 @@ unsafe fn clock_gettime_old(id: ClockId) -> Timespec { #[cfg(not(target_os = "wasi"))] #[inline] pub(crate) fn clock_gettime_dynamic(id: DynamicClockId<'_>) -> io::Result { - let mut timespec = MaybeUninit::::uninit(); unsafe { let id: c::clockid_t = match id { DynamicClockId::Known(id) => id as c::clockid_t, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_kernel)] DynamicClockId::Dynamic(fd) => { use crate::fd::AsRawFd; const CLOCKFD: i32 = 3; (!fd.as_raw_fd() << 3) | CLOCKFD } - #[cfg(not(any(target_os = "android", target_os = "linux")))] + #[cfg(not(linux_kernel))] DynamicClockId::Dynamic(_fd) => { // Dynamic clocks are not supported on this platform. return Err(io::Errno::INVAL); } - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_kernel)] DynamicClockId::RealtimeAlarm => c::CLOCK_REALTIME_ALARM, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_kernel)] DynamicClockId::Tai => c::CLOCK_TAI, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(any(linux_kernel, target_os = "openbsd"))] DynamicClockId::Boottime => c::CLOCK_BOOTTIME, - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_kernel)] DynamicClockId::BoottimeAlarm => c::CLOCK_BOOTTIME_ALARM, }; @@ -193,6 +196,8 @@ pub(crate) fn clock_gettime_dynamic(id: DynamicClockId<'_>) -> io::Result::uninit(); + if let Some(libc_clock_gettime) = __clock_gettime64.get() { ret(libc_clock_gettime( id as c::clockid_t, @@ -210,6 +215,8 @@ pub(crate) fn clock_gettime_dynamic(id: DynamicClockId<'_>) -> io::Result::uninit(); + ret(c::clock_gettime(id as c::clockid_t, timespec.as_mut_ptr()))?; Ok(timespec.assume_init()) @@ -277,9 +284,7 @@ pub(crate) fn clock_settime(id: ClockId, timespec: Timespec) -> io::Result<()> { any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), target_env = "gnu", ))] -#[must_use] unsafe fn clock_settime_old(id: ClockId, timespec: Timespec) -> io::Result<()> { - use core::convert::TryInto; let old_timespec = c::timespec { tv_sec: timespec .tv_sec @@ -290,13 +295,13 @@ unsafe fn clock_settime_old(id: ClockId, timespec: Timespec) -> io::Result<()> { ret(c::clock_settime(id as c::clockid_t, &old_timespec)) } -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] #[cfg(feature = "time")] pub(crate) fn timerfd_create(id: TimerfdClockId, flags: TimerfdFlags) -> io::Result { - unsafe { ret_owned_fd(c::timerfd_create(id as c::clockid_t, flags.bits())) } + unsafe { ret_owned_fd(c::timerfd_create(id as c::clockid_t, bitflags_bits!(flags))) } } -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] #[cfg(feature = "time")] pub(crate) fn timerfd_settime( fd: BorrowedFd<'_>, @@ -313,7 +318,7 @@ pub(crate) fn timerfd_settime( if let Some(libc_timerfd_settime) = __timerfd_settime64.get() { ret(libc_timerfd_settime( borrowed_fd(fd), - flags.bits(), + bitflags_bits!(flags), &new_value.clone().into(), result.as_mut_ptr(), ))?; @@ -330,7 +335,7 @@ pub(crate) fn timerfd_settime( unsafe { ret(c::timerfd_settime( borrowed_fd(fd), - flags.bits(), + bitflags_bits!(flags), new_value, result.as_mut_ptr(), ))?; @@ -338,7 +343,7 @@ pub(crate) fn timerfd_settime( } } -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] #[cfg(all( any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), target_env = "gnu", @@ -349,8 +354,6 @@ unsafe fn timerfd_settime_old( flags: TimerfdTimerFlags, new_value: &Itimerspec, ) -> io::Result { - use core::convert::TryInto; - let mut old_result = MaybeUninit::::uninit(); // Convert `new_value` to the old `itimerspec` format. @@ -383,7 +386,7 @@ unsafe fn timerfd_settime_old( ret(c::timerfd_settime( borrowed_fd(fd), - flags.bits(), + bitflags_bits!(flags), &old_new_value, old_result.as_mut_ptr(), ))?; @@ -409,7 +412,7 @@ unsafe fn timerfd_settime_old( }) } -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] #[cfg(feature = "time")] pub(crate) fn timerfd_gettime(fd: BorrowedFd<'_>) -> io::Result { let mut result = MaybeUninit::::uninit(); @@ -437,15 +440,13 @@ pub(crate) fn timerfd_gettime(fd: BorrowedFd<'_>) -> io::Result { } } -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] #[cfg(all( any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), target_env = "gnu", ))] #[cfg(feature = "time")] unsafe fn timerfd_gettime_old(fd: BorrowedFd<'_>) -> io::Result { - use core::convert::TryInto; - let mut old_result = MaybeUninit::::uninit(); ret(c::timerfd_gettime(borrowed_fd(fd), old_result.as_mut_ptr()))?; diff --git a/vendor/rustix/src/backend/libc/time/types.rs b/vendor/rustix/src/backend/libc/time/types.rs index c78aeb21a..e1d4a8736 100644 --- a/vendor/rustix/src/backend/libc/time/types.rs +++ b/vendor/rustix/src/backend/libc/time/types.rs @@ -1,220 +1,25 @@ -use super::super::c; -#[cfg(not(target_os = "wasi"))] -use crate::fd::BorrowedFd; -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] -use bitflags::bitflags; - -/// `struct timespec` -#[cfg(not(all( - any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), - target_env = "gnu", -)))] -pub type Timespec = c::timespec; - -/// `struct timespec` +#[cfg(any(linux_kernel, target_os = "fuchsia"))] +use crate::backend::c; #[cfg(all( any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), target_env = "gnu", ))] -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub struct Timespec { - /// Seconds. - pub tv_sec: Secs, - - /// Nanoseconds. Must be less than 1_000_000_000. - pub tv_nsec: Nsecs, -} - -/// A type for the `tv_sec` field of [`Timespec`]. -#[cfg(not(all( - any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), - target_env = "gnu", -)))] -#[allow(deprecated)] -pub type Secs = c::time_t; - -/// A type for the `tv_sec` field of [`Timespec`]. -#[cfg(all( - any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), - target_env = "gnu", -))] -pub type Secs = i64; - -/// A type for the `tv_nsec` field of [`Timespec`]. -#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] -pub type Nsecs = i64; - -/// A type for the `tv_nsec` field of [`Timespec`]. -#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] -pub type Nsecs = c::c_long; - -/// On most platforms, `LibcTimespec` is just `Timespec`. -#[cfg(not(all( - any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), - target_env = "gnu", -)))] -pub(crate) type LibcTimespec = Timespec; - -/// On 32-bit glibc platforms, `timespec` has anonymous padding fields, which -/// Rust doesn't support yet (see `unnamed_fields`), so we define our own -/// struct with explicit padding, with bidirectional `From` impls. -#[cfg(all( - any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), - target_env = "gnu", -))] -#[repr(C)] -#[derive(Debug, Clone)] -pub(crate) struct LibcTimespec { - pub(crate) tv_sec: Secs, - - #[cfg(target_endian = "big")] - padding: core::mem::MaybeUninit, - - pub(crate) tv_nsec: Nsecs, - - #[cfg(target_endian = "little")] - padding: core::mem::MaybeUninit, -} - -#[cfg(all( - any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), - target_env = "gnu", -))] -impl From for Timespec { - #[inline] - fn from(t: LibcTimespec) -> Self { - Self { - tv_sec: t.tv_sec, - tv_nsec: t.tv_nsec, - } - } -} - +use crate::timespec::LibcTimespec; +#[cfg(any(linux_kernel, target_os = "fuchsia"))] #[cfg(all( any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), target_env = "gnu", ))] -impl From for LibcTimespec { - #[inline] - fn from(t: Timespec) -> Self { - Self { - tv_sec: t.tv_sec, - tv_nsec: t.tv_nsec, - padding: core::mem::MaybeUninit::uninit(), - } - } -} - -/// `CLOCK_*` constants for use with [`clock_gettime`]. -/// -/// These constants are always supported at runtime, so `clock_gettime` never -/// has to fail with `INVAL` due to an unsupported clock. See -/// [`DynamicClockId`] for a greater set of clocks, with the caveat that not -/// all of them are always supported. -/// -/// [`clock_gettime`]: crate::time::clock_gettime -#[cfg(not(any(apple, target_os = "wasi")))] -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -#[cfg_attr(not(target_os = "dragonfly"), repr(i32))] -#[cfg_attr(target_os = "dragonfly", repr(u64))] -#[non_exhaustive] -pub enum ClockId { - /// `CLOCK_REALTIME` - Realtime = c::CLOCK_REALTIME, - - /// `CLOCK_MONOTONIC` - Monotonic = c::CLOCK_MONOTONIC, - - /// `CLOCK_UPTIME` - #[cfg(any(freebsdlike))] - Uptime = c::CLOCK_UPTIME, - - /// `CLOCK_PROCESS_CPUTIME_ID` - #[cfg(not(any(netbsdlike, solarish, target_os = "redox")))] - ProcessCPUTime = c::CLOCK_PROCESS_CPUTIME_ID, - - /// `CLOCK_THREAD_CPUTIME_ID` - #[cfg(not(any(netbsdlike, solarish, target_os = "redox")))] - ThreadCPUTime = c::CLOCK_THREAD_CPUTIME_ID, - - /// `CLOCK_REALTIME_COARSE` - #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))] - RealtimeCoarse = c::CLOCK_REALTIME_COARSE, - - /// `CLOCK_MONOTONIC_COARSE` - #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))] - MonotonicCoarse = c::CLOCK_MONOTONIC_COARSE, - - /// `CLOCK_MONOTONIC_RAW` - #[cfg(any(target_os = "android", target_os = "linux"))] - MonotonicRaw = c::CLOCK_MONOTONIC_RAW, -} - -/// `CLOCK_*` constants for use with [`clock_gettime`]. -/// -/// These constants are always supported at runtime, so `clock_gettime` never -/// has to fail with `INVAL` due to an unsupported clock. See -/// [`DynamicClockId`] for a greater set of clocks, with the caveat that not -/// all of them are always supported. -#[cfg(apple)] -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -#[repr(u32)] -#[non_exhaustive] -pub enum ClockId { - /// `CLOCK_REALTIME` - Realtime = c::CLOCK_REALTIME, - - /// `CLOCK_MONOTONIC` - Monotonic = c::CLOCK_MONOTONIC, - - /// `CLOCK_PROCESS_CPUTIME_ID` - ProcessCPUTime = c::CLOCK_PROCESS_CPUTIME_ID, - - /// `CLOCK_THREAD_CPUTIME_ID` - ThreadCPUTime = c::CLOCK_THREAD_CPUTIME_ID, -} - -/// `CLOCK_*` constants for use with [`clock_gettime_dynamic`]. -/// -/// These constants may be unsupported at runtime, depending on the OS version, -/// and `clock_gettime_dynamic` may fail with `INVAL`. See [`ClockId`] for -/// clocks which are always supported at runtime. -/// -/// [`clock_gettime_dynamic`]: crate::time::clock_gettime_dynamic -#[cfg(not(target_os = "wasi"))] -#[derive(Debug, Copy, Clone)] -#[non_exhaustive] -pub enum DynamicClockId<'a> { - /// `ClockId` values that are always supported at runtime. - Known(ClockId), - - /// Linux dynamic clocks. - Dynamic(BorrowedFd<'a>), - - /// `CLOCK_REALTIME_ALARM`, available on Linux >= 3.0 - #[cfg(any(target_os = "android", target_os = "linux"))] - RealtimeAlarm, - - /// `CLOCK_TAI`, available on Linux >= 3.10 - #[cfg(any(target_os = "android", target_os = "linux"))] - Tai, - - /// `CLOCK_BOOTTIME`, available on Linux >= 2.6.39 - #[cfg(any(target_os = "android", target_os = "linux"))] - Boottime, - - /// `CLOCK_BOOTTIME_ALARM`, available on Linux >= 2.6.39 - #[cfg(any(target_os = "android", target_os = "linux"))] - BoottimeAlarm, -} +use crate::timespec::Timespec; +#[cfg(any(linux_kernel, target_os = "fuchsia"))] +use bitflags::bitflags; /// `struct itimerspec` for use with [`timerfd_gettime`] and /// [`timerfd_settime`]. /// /// [`timerfd_gettime`]: crate::time::timerfd_gettime /// [`timerfd_settime`]: crate::time::timerfd_settime -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] #[cfg(not(all( any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), target_env = "gnu", @@ -226,7 +31,7 @@ pub type Itimerspec = c::itimerspec; /// /// [`timerfd_gettime`]: crate::time::timerfd_gettime /// [`timerfd_settime`]: crate::time::timerfd_settime -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] #[cfg(all( any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), target_env = "gnu", @@ -240,7 +45,7 @@ pub struct Itimerspec { } /// On most platforms, `LibcItimerspec` is just `Itimerspec`. -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] #[cfg(not(all( any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), target_env = "gnu", @@ -249,7 +54,7 @@ pub(crate) type LibcItimerspec = Itimerspec; /// On 32-bit glibc platforms, `LibcTimespec` differs from `Timespec`, so we /// define our own struct, with bidirectional `From` impls. -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] #[cfg(all( any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), target_env = "gnu", @@ -261,7 +66,7 @@ pub(crate) struct LibcItimerspec { pub it_value: LibcTimespec, } -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] #[cfg(all( any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), target_env = "gnu", @@ -276,7 +81,7 @@ impl From for Itimerspec { } } -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] #[cfg(all( any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), target_env = "gnu", @@ -291,41 +96,45 @@ impl From for LibcItimerspec { } } -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] bitflags! { /// `TFD_*` flags for use with [`timerfd_create`]. /// /// [`timerfd_create`]: crate::time::timerfd_create - pub struct TimerfdFlags: c::c_int { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct TimerfdFlags: u32 { /// `TFD_NONBLOCK` - const NONBLOCK = c::TFD_NONBLOCK; + const NONBLOCK = bitcast!(c::TFD_NONBLOCK); /// `TFD_CLOEXEC` - const CLOEXEC = c::TFD_CLOEXEC; + const CLOEXEC = bitcast!(c::TFD_CLOEXEC); } } -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] bitflags! { /// `TFD_TIMER_*` flags for use with [`timerfd_settime`]. /// /// [`timerfd_settime`]: crate::time::timerfd_settime - pub struct TimerfdTimerFlags: c::c_int { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct TimerfdTimerFlags: u32 { /// `TFD_TIMER_ABSTIME` - const ABSTIME = c::TFD_TIMER_ABSTIME; + const ABSTIME = bitcast!(c::TFD_TIMER_ABSTIME); /// `TFD_TIMER_CANCEL_ON_SET` - #[cfg(any(target_os = "android", target_os = "linux"))] - const CANCEL_ON_SET = c::TFD_TIMER_CANCEL_ON_SET; + #[cfg(linux_kernel)] + const CANCEL_ON_SET = bitcast!(c::TFD_TIMER_CANCEL_ON_SET); } } /// `CLOCK_*` constants for use with [`timerfd_create`]. /// /// [`timerfd_create`]: crate::time::timerfd_create -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -#[repr(i32)] +#[repr(u32)] #[non_exhaustive] pub enum TimerfdClockId { /// `CLOCK_REALTIME`—A clock that tells the “real” time. @@ -334,7 +143,7 @@ pub enum TimerfdClockId { /// Unix epoch, 1970-01-01T00:00:00Z. The clock is externally settable, so /// it is not monotonic. Successive reads may see decreasing times, so it /// isn't reliable for measuring durations. - Realtime = c::CLOCK_REALTIME, + Realtime = bitcast!(c::CLOCK_REALTIME), /// `CLOCK_MONOTONIC`—A clock that tells an abstract time. /// @@ -344,25 +153,33 @@ pub enum TimerfdClockId { /// /// This clock does not advance while the system is suspended; see /// `Boottime` for a clock that does. - Monotonic = c::CLOCK_MONOTONIC, + Monotonic = bitcast!(c::CLOCK_MONOTONIC), /// `CLOCK_BOOTTIME`—Like `Monotonic`, but advances while suspended. /// /// This clock is similar to `Monotonic`, but does advance while the system /// is suspended. - Boottime = c::CLOCK_BOOTTIME, + Boottime = bitcast!(c::CLOCK_BOOTTIME), /// `CLOCK_REALTIME_ALARM`—Like `Realtime`, but wakes a suspended system. /// /// This clock is like `Realtime`, but can wake up a suspended system. /// /// Use of this clock requires the `CAP_WAKE_ALARM` Linux capability. - RealtimeAlarm = c::CLOCK_REALTIME_ALARM, + RealtimeAlarm = bitcast!(c::CLOCK_REALTIME_ALARM), /// `CLOCK_BOOTTIME_ALARM`—Like `Boottime`, but wakes a suspended system. /// /// This clock is like `Boottime`, but can wake up a suspended system. /// /// Use of this clock requires the `CAP_WAKE_ALARM` Linux capability. - BoottimeAlarm = c::CLOCK_BOOTTIME_ALARM, + BoottimeAlarm = bitcast!(c::CLOCK_BOOTTIME_ALARM), +} + +#[cfg(any(linux_kernel, target_os = "fuchsia"))] +#[test] +fn test_types() { + use core::mem::size_of; + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); } diff --git a/vendor/rustix/src/backend/libc/ugid/mod.rs b/vendor/rustix/src/backend/libc/ugid/mod.rs new file mode 100644 index 000000000..ef944f04d --- /dev/null +++ b/vendor/rustix/src/backend/libc/ugid/mod.rs @@ -0,0 +1 @@ +pub(crate) mod syscalls; diff --git a/vendor/rustix/src/backend/libc/ugid/syscalls.rs b/vendor/rustix/src/backend/libc/ugid/syscalls.rs new file mode 100644 index 000000000..0d3f622dc --- /dev/null +++ b/vendor/rustix/src/backend/libc/ugid/syscalls.rs @@ -0,0 +1,42 @@ +use crate::backend::c; +use crate::ugid::{Gid, Uid}; + +#[cfg(not(target_os = "wasi"))] +#[inline] +#[must_use] +pub(crate) fn getuid() -> Uid { + unsafe { + let uid = c::getuid(); + Uid::from_raw(uid) + } +} + +#[cfg(not(target_os = "wasi"))] +#[inline] +#[must_use] +pub(crate) fn geteuid() -> Uid { + unsafe { + let uid = c::geteuid(); + Uid::from_raw(uid) + } +} + +#[cfg(not(target_os = "wasi"))] +#[inline] +#[must_use] +pub(crate) fn getgid() -> Gid { + unsafe { + let gid = c::getgid(); + Gid::from_raw(gid) + } +} + +#[cfg(not(target_os = "wasi"))] +#[inline] +#[must_use] +pub(crate) fn getegid() -> Gid { + unsafe { + let gid = c::getegid(); + Gid::from_raw(gid) + } +} diff --git a/vendor/rustix/src/backend/libc/winsock_c.rs b/vendor/rustix/src/backend/libc/winsock_c.rs index a30f2c86f..0a1554a86 100644 --- a/vendor/rustix/src/backend/libc/winsock_c.rs +++ b/vendor/rustix/src/backend/libc/winsock_c.rs @@ -2,6 +2,7 @@ #![allow(unused_imports)] #![allow(non_camel_case_types)] +#![allow(dead_code)] use windows_sys::Win32::Networking::WinSock; @@ -32,16 +33,12 @@ pub(crate) const AF_UNSPEC: i32 = WinSock::AF_UNSPEC as _; // `WSAECANCELLED` will be removed in the future. // pub(crate) use WinSock::{ - closesocket as close, ioctlsocket as ioctl, socklen_t, WSAPoll as poll, - ADDRESS_FAMILY as sa_family_t, ADDRINFOA as addrinfo, IN6_ADDR as in6_addr, IN_ADDR as in_addr, - IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MREQ as ipv6_mreq, IPV6_MULTICAST_LOOP, - IPV6_V6ONLY, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_MREQ as ip_mreq, IP_MULTICAST_LOOP, - IP_MULTICAST_TTL, IP_TTL, LINGER as linger, POLLERR, POLLHUP, POLLIN, POLLNVAL, POLLOUT, - POLLPRI, POLLRDBAND, POLLRDNORM, POLLWRBAND, POLLWRNORM, SD_BOTH as SHUT_RDWR, - SD_RECEIVE as SHUT_RD, SD_SEND as SHUT_WR, SOCKADDR as sockaddr, SOCKADDR_IN as sockaddr_in, - SOCKADDR_IN6 as sockaddr_in6, SOCKADDR_STORAGE as sockaddr_storage, SOL_SOCKET, SO_BROADCAST, - SO_ERROR, SO_LINGER, SO_RCVTIMEO, SO_REUSEADDR, SO_SNDTIMEO, SO_TYPE, TCP_NODELAY, - WSAEACCES as EACCES, WSAEADDRINUSE as EADDRINUSE, WSAEADDRNOTAVAIL as EADDRNOTAVAIL, + closesocket as close, ioctlsocket as ioctl, WSAPoll as poll, ADDRESS_FAMILY as sa_family_t, + ADDRINFOA as addrinfo, IN6_ADDR as in6_addr, IN_ADDR as in_addr, IPV6_MREQ as ipv6_mreq, + IP_MREQ as ip_mreq, LINGER as linger, SD_BOTH as SHUT_RDWR, SD_RECEIVE as SHUT_RD, + SD_SEND as SHUT_WR, SOCKADDR as sockaddr, SOCKADDR_IN as sockaddr_in, + SOCKADDR_IN6 as sockaddr_in6, SOCKADDR_STORAGE as sockaddr_storage, WSAEACCES as EACCES, + WSAEADDRINUSE as EADDRINUSE, WSAEADDRNOTAVAIL as EADDRNOTAVAIL, WSAEAFNOSUPPORT as EAFNOSUPPORT, WSAEALREADY as EALREADY, WSAEBADF as EBADF, WSAECONNABORTED as ECONNABORTED, WSAECONNREFUSED as ECONNREFUSED, WSAECONNRESET as ECONNRESET, WSAEDESTADDRREQ as EDESTADDRREQ, WSAEDISCON as EDISCON, WSAEDQUOT as EDQUOT, diff --git a/vendor/rustix/src/backend/linux_raw/arch/inline/mod.rs b/vendor/rustix/src/backend/linux_raw/arch/inline/mod.rs index 4783747ac..7c26e23a4 100644 --- a/vendor/rustix/src/backend/linux_raw/arch/inline/mod.rs +++ b/vendor/rustix/src/backend/linux_raw/arch/inline/mod.rs @@ -19,4 +19,4 @@ #[cfg_attr(target_arch = "x86_64", path = "x86_64.rs")] mod target_arch; -pub(in crate::backend) use self::target_arch::*; +pub(in crate::backend) use target_arch::*; diff --git a/vendor/rustix/src/backend/linux_raw/arch/inline/x86.rs b/vendor/rustix/src/backend/linux_raw/arch/inline/x86.rs index 8e115148d..62947cb04 100644 --- a/vendor/rustix/src/backend/linux_raw/arch/inline/x86.rs +++ b/vendor/rustix/src/backend/linux_raw/arch/inline/x86.rs @@ -113,7 +113,7 @@ pub(in crate::backend) unsafe fn indirect_syscall4( ) -> RetReg { let r0; // a3 should go in esi, but `asm!` won't let us use it as an operand. - // temporarily swap it into place, and then swap it back afterward. + // Temporarily swap it into place, and then swap it back afterward. // // We hard-code the callee operand to use edi instead of `in(reg)` because // even though we can't name esi as an operand, the compiler can use esi to diff --git a/vendor/rustix/src/backend/linux_raw/arch/mod.rs b/vendor/rustix/src/backend/linux_raw/arch/mod.rs index e13f675fd..cc93fc2c4 100644 --- a/vendor/rustix/src/backend/linux_raw/arch/mod.rs +++ b/vendor/rustix/src/backend/linux_raw/arch/mod.rs @@ -1,8 +1,8 @@ //! Architecture-specific syscall code. //! //! `rustix` has inline assembly sequences using `asm!`, but that requires -//! nightly Rust, so it also has out-of-line ("outline") assembly sequences -//! in .s files. And 32-bit x86 is special (see comments below). +//! Rust 1.59, so it also has out-of-line ("outline") assembly sequences in .s +//! files. And 32-bit x86 is special (see comments below). //! //! This module also has a `choose` submodule which chooses a scheme and is //! what most of the `rustix` syscalls use. @@ -133,6 +133,87 @@ macro_rules! syscall { }; } +// Macro to invoke a syscall that always uses direct assembly, rather than the +// vDSO. Useful when still finding the vDSO. +#[allow(unused_macros)] +macro_rules! syscall_always_asm { + ($nr:ident) => { + $crate::backend::arch::asm::syscall0($crate::backend::reg::nr(linux_raw_sys::general::$nr)) + }; + + ($nr:ident, $a0:expr) => { + $crate::backend::arch::asm::syscall1( + $crate::backend::reg::nr(linux_raw_sys::general::$nr), + $a0.into(), + ) + }; + + ($nr:ident, $a0:expr, $a1:expr) => { + $crate::backend::arch::asm::syscall2( + $crate::backend::reg::nr(linux_raw_sys::general::$nr), + $a0.into(), + $a1.into(), + ) + }; + + ($nr:ident, $a0:expr, $a1:expr, $a2:expr) => { + $crate::backend::arch::asm::syscall3( + $crate::backend::reg::nr(linux_raw_sys::general::$nr), + $a0.into(), + $a1.into(), + $a2.into(), + ) + }; + + ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => { + $crate::backend::arch::asm::syscall4( + $crate::backend::reg::nr(linux_raw_sys::general::$nr), + $a0.into(), + $a1.into(), + $a2.into(), + $a3.into(), + ) + }; + + ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => { + $crate::backend::arch::asm::syscall5( + $crate::backend::reg::nr(linux_raw_sys::general::$nr), + $a0.into(), + $a1.into(), + $a2.into(), + $a3.into(), + $a4.into(), + ) + }; + + ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr) => { + $crate::backend::arch::asm::syscall6( + $crate::backend::reg::nr(linux_raw_sys::general::$nr), + $a0.into(), + $a1.into(), + $a2.into(), + $a3.into(), + $a4.into(), + $a5.into(), + ) + }; + + ($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr) => { + $crate::backend::arch::asm::syscall7( + $crate::backend::reg::nr(linux_raw_sys::general::$nr), + $a0.into(), + $a1.into(), + $a2.into(), + $a3.into(), + $a4.into(), + $a5.into(), + $a6.into(), + ) + }; +} + +/// Like `syscall`, but adds the `readonly` attribute to the inline asm, which +/// indicates that the syscall does not mutate any memory. macro_rules! syscall_readonly { ($nr:ident) => { $crate::backend::arch::choose::syscall0_readonly($crate::backend::reg::nr( @@ -211,6 +292,7 @@ macro_rules! syscall_readonly { }; } +/// Like `syscall`, but indicates that the syscall does not return. #[cfg(feature = "runtime")] macro_rules! syscall_noreturn { ($nr:ident, $a0:expr) => { diff --git a/vendor/rustix/src/backend/linux_raw/arch/outline/aarch64.s b/vendor/rustix/src/backend/linux_raw/arch/outline/aarch64.s deleted file mode 100644 index 1fad2fa6d..000000000 --- a/vendor/rustix/src/backend/linux_raw/arch/outline/aarch64.s +++ /dev/null @@ -1,119 +0,0 @@ -// Assembly code for making aarch64 syscalls. -// -// aarch64 syscall argument register ordering is the same as the aarch64 -// userspace argument register ordering except that the syscall number -// (nr) is passed in w8. -// -// outline.rs takes care of reordering the nr argument to the end for us, -// so we only need to move nr into w8. -// -// arm64-ilp32 is not yet supported. - - .file "aarch64.s" - .arch armv8-a - - .section .text.rustix_syscall0_nr_last,"ax",@progbits - .p2align 2 - .weak rustix_syscall0_nr_last - .hidden rustix_syscall0_nr_last - .type rustix_syscall0_nr_last, @function -rustix_syscall0_nr_last: - .cfi_startproc - mov w8, w0 - svc #0 - ret - .cfi_endproc - .size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last - - .section .text.rustix_syscall1_nr_last,"ax",@progbits - .p2align 2 - .weak rustix_syscall1_nr_last - .hidden rustix_syscall1_nr_last - .type rustix_syscall1_nr_last, @function -rustix_syscall1_nr_last: - .cfi_startproc - mov w8, w1 - svc #0 - ret - .cfi_endproc - .size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last - - .section .text.rustix_syscall1_noreturn_nr_last,"ax",@progbits - .p2align 2 - .weak rustix_syscall1_noreturn_nr_last - .hidden rustix_syscall1_noreturn_nr_last - .type rustix_syscall1_noreturn_nr_last, @function -rustix_syscall1_noreturn_nr_last: - .cfi_startproc - mov w8, w1 - svc #0 - brk #0x1 - .cfi_endproc - .size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last - - .section .text.rustix_syscall2_nr_last,"ax",@progbits - .p2align 2 - .weak rustix_syscall2_nr_last - .hidden rustix_syscall2_nr_last - .type rustix_syscall2_nr_last, @function -rustix_syscall2_nr_last: - .cfi_startproc - mov w8, w2 - svc #0 - ret - .cfi_endproc - .size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last - - .section .text.rustix_syscall3_nr_last,"ax",@progbits - .p2align 2 - .weak rustix_syscall3_nr_last - .hidden rustix_syscall3_nr_last - .type rustix_syscall3_nr_last, @function -rustix_syscall3_nr_last: - .cfi_startproc - mov w8, w3 - svc #0 - ret - .cfi_endproc - .size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last - - .section .text.rustix_syscall4_nr_last,"ax",@progbits - .p2align 2 - .weak rustix_syscall4_nr_last - .hidden rustix_syscall4_nr_last - .type rustix_syscall4_nr_last, @function -rustix_syscall4_nr_last: - .cfi_startproc - mov w8, w4 - svc #0 - ret - .cfi_endproc - .size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last - - .section .text.rustix_syscall5_nr_last,"ax",@progbits - .p2align 2 - .weak rustix_syscall5_nr_last - .hidden rustix_syscall5_nr_last - .type rustix_syscall5_nr_last, @function -rustix_syscall5_nr_last: - .cfi_startproc - mov w8, w5 - svc #0 - ret - .cfi_endproc - .size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last - - .section .text.rustix_syscall6_nr_last,"ax",@progbits - .p2align 2 - .weak rustix_syscall6_nr_last - .hidden rustix_syscall6_nr_last - .type rustix_syscall6_nr_last, @function -rustix_syscall6_nr_last: - .cfi_startproc - mov w8, w6 - svc #0 - ret - .cfi_endproc - .size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last - - .section .note.GNU-stack,"",@progbits diff --git a/vendor/rustix/src/backend/linux_raw/arch/outline/arm.s b/vendor/rustix/src/backend/linux_raw/arch/outline/arm.s deleted file mode 100644 index 7001686f1..000000000 --- a/vendor/rustix/src/backend/linux_raw/arch/outline/arm.s +++ /dev/null @@ -1,135 +0,0 @@ -// Assembly code for making arm syscalls. -// -// arm syscall argument register ordering is the similar to the arm -// userspace argument register ordering except that the syscall number -// (nr) is passed in r7. -// -// nr_last.rs takes care of reordering the nr argument to the end for us, -// so we only need to move nr into r7 and take care of r4 and r5 if needed. - - .file "arm.s" - .arch armv5t - - .section .text.rustix_syscall0_nr_last,"ax",%progbits - .p2align 4 - .weak rustix_syscall0_nr_last - .hidden rustix_syscall0_nr_last - .type rustix_syscall0_nr_last, %function -rustix_syscall0_nr_last: - .fnstart - .cantunwind - push {r7, lr} - mov r7, r0 - svc #0 - pop {r7, pc} - .fnend - .size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last - - .section .text.rustix_syscall1_nr_last,"ax",%progbits - .p2align 4 - .weak rustix_syscall1_nr_last - .hidden rustix_syscall1_nr_last - .type rustix_syscall1_nr_last, %function -rustix_syscall1_nr_last: - .fnstart - .cantunwind - push {r7, lr} - mov r7, r1 - svc #0 - pop {r7, pc} - .fnend - .size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last - - .section .text.rustix_syscall1_noreturn_nr_last,"ax",%progbits - .p2align 4 - .weak rustix_syscall1_noreturn_nr_last - .hidden rustix_syscall1_noreturn_nr_last - .type rustix_syscall1_noreturn_nr_last, %function -rustix_syscall1_noreturn_nr_last: - .fnstart - .cantunwind - // Don't save r7 and lr; this is noreturn, so we'll never restore them. - mov r7, r1 - svc #0 - udf #16 // Trap instruction - .fnend - .size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last - - .section .text.rustix_syscall2_nr_last,"ax",%progbits - .p2align 4 - .weak rustix_syscall2_nr_last - .hidden rustix_syscall2_nr_last - .type rustix_syscall2_nr_last, %function -rustix_syscall2_nr_last: - .fnstart - .cantunwind - push {r7, lr} - mov r7, r2 - svc #0 - pop {r7, pc} - .fnend - .size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last - - .section .text.rustix_syscall3_nr_last,"ax",%progbits - .p2align 4 - .weak rustix_syscall3_nr_last - .hidden rustix_syscall3_nr_last - .type rustix_syscall3_nr_last, %function -rustix_syscall3_nr_last: - .fnstart - .cantunwind - push {r7, lr} - mov r7, r3 - svc #0 - pop {r7, pc} - .fnend - .size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last - - .section .text.rustix_syscall4_nr_last,"ax",%progbits - .p2align 4 - .weak rustix_syscall4_nr_last - .hidden rustix_syscall4_nr_last - .type rustix_syscall4_nr_last, %function -rustix_syscall4_nr_last: - .fnstart - .cantunwind - push {r7, lr} - ldr r7, [sp, #8] - svc #0 - pop {r7, pc} - .fnend - .size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last - - .section .text.rustix_syscall5_nr_last,"ax",%progbits - .p2align 4 - .weak rustix_syscall5_nr_last - .hidden rustix_syscall5_nr_last - .type rustix_syscall5_nr_last, %function -rustix_syscall5_nr_last: - .fnstart - .cantunwind - push {r4, r7, r11, lr} - ldr r7, [sp, #20] - ldr r4, [sp, #16] - svc #0 - pop {r4, r7, r11, pc} - .fnend - .size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last - - .section .text.rustix_syscall6_nr_last,"ax",%progbits - .p2align 4 - .weak rustix_syscall6_nr_last - .hidden rustix_syscall6_nr_last - .type rustix_syscall6_nr_last, %function -rustix_syscall6_nr_last: - .fnstart - .cantunwind - push {r4, r5, r7, lr} - add r7, sp, #16 - ldm r7, {r4, r5, r7} - svc #0 - pop {r4, r5, r7, pc} - .fnend - .size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last - - .section .note.GNU-stack,"",%progbits diff --git a/vendor/rustix/src/backend/linux_raw/arch/outline/mips.s b/vendor/rustix/src/backend/linux_raw/arch/outline/mips.s index ab1bbfa2d..b016ae124 100644 --- a/vendor/rustix/src/backend/linux_raw/arch/outline/mips.s +++ b/vendor/rustix/src/backend/linux_raw/arch/outline/mips.s @@ -186,8 +186,6 @@ rustix_syscall6_nr_last: .end rustix_syscall6_nr_last .size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last - .section .note.GNU-stack,"",@progbits - .section .text.rustix_syscall7_nr_last,"ax",@progbits .p2align 2 .weak rustix_syscall7_nr_last diff --git a/vendor/rustix/src/backend/linux_raw/arch/outline/mips64.s b/vendor/rustix/src/backend/linux_raw/arch/outline/mips64.s index 3c5e76e36..a6473990e 100644 --- a/vendor/rustix/src/backend/linux_raw/arch/outline/mips64.s +++ b/vendor/rustix/src/backend/linux_raw/arch/outline/mips64.s @@ -7,7 +7,7 @@ # outline.rs takes care of reordering the nr argument to the end for us, # so we only need to move nr into v0. - .file "mips.s" + .file "mips64.s" .section .mdebug.abi64 .previous .abicalls diff --git a/vendor/rustix/src/backend/linux_raw/arch/outline/mod.rs b/vendor/rustix/src/backend/linux_raw/arch/outline/mod.rs index 5e6f5e1f5..202a2cce9 100644 --- a/vendor/rustix/src/backend/linux_raw/arch/outline/mod.rs +++ b/vendor/rustix/src/backend/linux_raw/arch/outline/mod.rs @@ -5,32 +5,23 @@ //! they match with the kernel convention as closely as possible, to minimize //! the amount of out-of-line code we need. //! -//! This is needed in order to support our MSRV of 1.48, which doesn't support -//! inline asm. When using newer Rust versions, inline asm code is used instead -//! and these outline libraries are unused. +//! This is needed because as of our MSRV of 1.63, inline asm and naked +//! functions are experimental. #[cfg(target_arch = "x86")] mod x86; // For these architectures, pass the `nr` argument last. #[cfg(any( - target_arch = "arm", - target_arch = "aarch64", target_arch = "mips", target_arch = "mips64", target_arch = "powerpc64", - target_arch = "riscv64", - target_arch = "x86_64", ))] mod nr_last; #[cfg(any( - target_arch = "arm", - target_arch = "aarch64", target_arch = "mips", target_arch = "mips64", target_arch = "powerpc64", - target_arch = "riscv64", - target_arch = "x86_64", ))] pub(in crate::backend) use nr_last::*; #[cfg(target_arch = "x86")] diff --git a/vendor/rustix/src/backend/linux_raw/arch/outline/riscv64.s b/vendor/rustix/src/backend/linux_raw/arch/outline/riscv64.s deleted file mode 100644 index 28d692f7c..000000000 --- a/vendor/rustix/src/backend/linux_raw/arch/outline/riscv64.s +++ /dev/null @@ -1,116 +0,0 @@ -# Assembly code for making riscv64 syscalls. -# -# riscv64 syscall argument register ordering is the same as the riscv64 -# userspace argument register ordering except that the syscall number -# (nr) is passed in a7. -# -# nr_last.rs takes care of reordering the nr argument to the end for us, -# so we only need to move nr into a7. - - .file "riscv64.s" - - .section .text.rustix_syscall0_nr_last,"ax",@progbits - .p2align 4 - .weak rustix_syscall0_nr_last - .hidden rustix_syscall0_nr_last - .type rustix_syscall0_nr_last, @function -rustix_syscall0_nr_last: - .cfi_startproc - mv a7, a0 - ecall - ret - .cfi_endproc - .size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last - - .section .text.rustix_syscall1_nr_last,"ax",@progbits - .p2align 4 - .weak rustix_syscall1_nr_last - .hidden rustix_syscall1_nr_last - .type rustix_syscall1_nr_last, @function -rustix_syscall1_nr_last: - .cfi_startproc - mv a7, a1 - ecall - ret - .cfi_endproc - .size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last - - .section .text.rustix_syscall1_noreturn_nr_last,"ax",@progbits - .p2align 4 - .weak rustix_syscall1_noreturn_nr_last - .hidden rustix_syscall1_noreturn_nr_last - .type rustix_syscall1_noreturn_nr_last, @function -rustix_syscall1_noreturn_nr_last: - .cfi_startproc - mv a7, a1 - ecall - unimp - .cfi_endproc - .size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last - - .section .text.rustix_syscall2_nr_last,"ax",@progbits - .p2align 4 - .weak rustix_syscall2_nr_last - .hidden rustix_syscall2_nr_last - .type rustix_syscall2_nr_last, @function -rustix_syscall2_nr_last: - .cfi_startproc - mv a7, a2 - ecall - ret - .cfi_endproc - .size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last - - .section .text.rustix_syscall3_nr_last,"ax",@progbits - .p2align 4 - .weak rustix_syscall3_nr_last - .hidden rustix_syscall3_nr_last - .type rustix_syscall3_nr_last, @function -rustix_syscall3_nr_last: - .cfi_startproc - mv a7, a3 - ecall - ret - .cfi_endproc - .size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last - - .section .text.rustix_syscall4_nr_last,"ax",@progbits - .p2align 4 - .weak rustix_syscall4_nr_last - .hidden rustix_syscall4_nr_last - .type rustix_syscall4_nr_last, @function -rustix_syscall4_nr_last: - .cfi_startproc - mv a7, a4 - ecall - ret - .cfi_endproc - .size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last - - .section .text.rustix_syscall5_nr_last,"ax",@progbits - .p2align 4 - .weak rustix_syscall5_nr_last - .hidden rustix_syscall5_nr_last - .type rustix_syscall5_nr_last, @function -rustix_syscall5_nr_last: - .cfi_startproc - mv a7, a5 - ecall - ret - .cfi_endproc - .size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last - - .section .text.rustix_syscall6_nr_last,"ax",@progbits - .p2align 4 - .weak rustix_syscall6_nr_last - .hidden rustix_syscall6_nr_last - .type rustix_syscall6_nr_last, @function -rustix_syscall6_nr_last: - .cfi_startproc - mv a7, a6 - ecall - ret - .cfi_endproc - .size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last - - .section .note.GNU-stack,"",@progbits diff --git a/vendor/rustix/src/backend/linux_raw/arch/outline/x86_64.s b/vendor/rustix/src/backend/linux_raw/arch/outline/x86_64.s deleted file mode 100644 index 2beda323b..000000000 --- a/vendor/rustix/src/backend/linux_raw/arch/outline/x86_64.s +++ /dev/null @@ -1,122 +0,0 @@ -// Assembly code for making x86-64 syscalls. -// -// x86-64 syscall argument register ordering is the same as the x86-64 -// userspace argument register ordering except that a3 is passed in r10 -// instead of rcx, and the syscall number (nr) is passed in eax. -// -// outline.rs takes care of reordering the nr argument to the end for us, -// so we only need to move nr into eax and move rcx into r10 as needed. -// -// x32 is not yet supported. - - .file "x86_64.s" - .intel_syntax noprefix - - .section .text.rustix_syscall0_nr_last,"ax",@progbits - .p2align 4 - .weak rustix_syscall0_nr_last - .hidden rustix_syscall0_nr_last - .type rustix_syscall0_nr_last, @function -rustix_syscall0_nr_last: - .cfi_startproc - mov eax,edi - syscall - ret - .cfi_endproc - .size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last - - .section .text.rustix_syscall1_nr_last,"ax",@progbits - .p2align 4 - .weak rustix_syscall1_nr_last - .hidden rustix_syscall1_nr_last - .type rustix_syscall1_nr_last, @function -rustix_syscall1_nr_last: - .cfi_startproc - mov eax,esi - syscall - ret - .cfi_endproc - .size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last - - .section .text.rustix_syscall1_noreturn_nr_last,"ax",@progbits - .p2align 4 - .weak rustix_syscall1_noreturn_nr_last - .hidden rustix_syscall1_noreturn_nr_last - .type rustix_syscall1_noreturn_nr_last, @function -rustix_syscall1_noreturn_nr_last: - .cfi_startproc - mov eax,esi - syscall - ud2 - .cfi_endproc - .size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last - - .section .text.rustix_syscall2_nr_last,"ax",@progbits - .p2align 4 - .weak rustix_syscall2_nr_last - .hidden rustix_syscall2_nr_last - .type rustix_syscall2_nr_last, @function -rustix_syscall2_nr_last: - .cfi_startproc - mov eax,edx - syscall - ret - .cfi_endproc - .size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last - - .section .text.rustix_syscall3_nr_last,"ax",@progbits - .p2align 4 - .weak rustix_syscall3_nr_last - .hidden rustix_syscall3_nr_last - .type rustix_syscall3_nr_last, @function -rustix_syscall3_nr_last: - .cfi_startproc - mov eax,ecx - syscall - ret - .cfi_endproc - .size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last - - .section .text.rustix_syscall4_nr_last,"ax",@progbits - .p2align 4 - .weak rustix_syscall4_nr_last - .hidden rustix_syscall4_nr_last - .type rustix_syscall4_nr_last, @function -rustix_syscall4_nr_last: - .cfi_startproc - mov eax,r8d - mov r10,rcx - syscall - ret - .cfi_endproc - .size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last - - .section .text.rustix_syscall5_nr_last,"ax",@progbits - .p2align 4 - .weak rustix_syscall5_nr_last - .hidden rustix_syscall5_nr_last - .type rustix_syscall5_nr_last, @function -rustix_syscall5_nr_last: - .cfi_startproc - mov eax,r9d - mov r10,rcx - syscall - ret - .cfi_endproc - .size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last - - .section .text.rustix_syscall6_nr_last,"ax",@progbits - .p2align 4 - .weak rustix_syscall6_nr_last - .hidden rustix_syscall6_nr_last - .type rustix_syscall6_nr_last, @function -rustix_syscall6_nr_last: - .cfi_startproc - mov eax,DWORD PTR [rsp+0x8] - mov r10,rcx - syscall - ret - .cfi_endproc - .size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last - - .section .note.GNU-stack,"",@progbits diff --git a/vendor/rustix/src/backend/linux_raw/c.rs b/vendor/rustix/src/backend/linux_raw/c.rs index 89fee82f9..8e77c82d7 100644 --- a/vendor/rustix/src/backend/linux_raw/c.rs +++ b/vendor/rustix/src/backend/linux_raw/c.rs @@ -4,30 +4,180 @@ //! types that are convenient to have defined. #![allow(unused_imports)] +#![allow(non_camel_case_types)] +pub type size_t = usize; pub(crate) use linux_raw_sys::ctypes::*; pub(crate) use linux_raw_sys::errno::EINVAL; +// Import the kernel's `uid_t` and `gid_t` if they're 32-bit. +#[cfg(not(any(target_arch = "arm", target_arch = "sparc", target_arch = "x86")))] +pub(crate) use linux_raw_sys::general::{__kernel_gid_t as gid_t, __kernel_uid_t as uid_t}; pub(crate) use linux_raw_sys::general::{ - AF_DECnet, __kernel_sa_family_t as sa_family_t, __kernel_sockaddr_storage as sockaddr_storage, - in6_addr, in_addr, iovec, ip_mreq, ipv6_mreq, linger, siginfo_t, sockaddr, sockaddr_in, - sockaddr_in6, sockaddr_un, socklen_t, AF_APPLETALK, AF_ASH, AF_ATMPVC, AF_ATMSVC, AF_AX25, - AF_BLUETOOTH, AF_BRIDGE, AF_CAN, AF_ECONET, AF_IEEE802154, AF_INET, AF_INET6, AF_IPX, AF_IRDA, - AF_ISDN, AF_IUCV, AF_KEY, AF_LLC, AF_NETBEUI, AF_NETLINK, AF_NETROM, AF_PACKET, AF_PHONET, - AF_PPPOX, AF_RDS, AF_ROSE, AF_RXRPC, AF_SECURITY, AF_SNA, AF_TIPC, AF_UNIX, AF_UNSPEC, - AF_WANPIPE, AF_X25, CLD_CONTINUED, CLD_DUMPED, CLD_EXITED, CLD_KILLED, CLD_STOPPED, - CLD_TRAPPED, IPPROTO_AH, IPPROTO_BEETPH, IPPROTO_COMP, IPPROTO_DCCP, IPPROTO_EGP, - IPPROTO_ENCAP, IPPROTO_ESP, IPPROTO_ETHERNET, IPPROTO_FRAGMENT, IPPROTO_GRE, IPPROTO_ICMP, - IPPROTO_ICMPV6, IPPROTO_IDP, IPPROTO_IGMP, IPPROTO_IP, IPPROTO_IPIP, IPPROTO_IPV6, IPPROTO_MH, - IPPROTO_MPLS, IPPROTO_MPTCP, IPPROTO_MTP, IPPROTO_PIM, IPPROTO_PUP, IPPROTO_RAW, - IPPROTO_ROUTING, IPPROTO_RSVP, IPPROTO_SCTP, IPPROTO_TCP, IPPROTO_TP, IPPROTO_UDP, - IPPROTO_UDPLITE, IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MULTICAST_LOOP, - IPV6_UNICAST_HOPS, IPV6_V6ONLY, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_MULTICAST_LOOP, - IP_MULTICAST_TTL, IP_TTL, MSG_CMSG_CLOEXEC, MSG_CONFIRM, MSG_DONTROUTE, MSG_DONTWAIT, MSG_EOR, - MSG_ERRQUEUE, MSG_MORE, MSG_NOSIGNAL, MSG_OOB, MSG_PEEK, MSG_TRUNC, MSG_WAITALL, O_CLOEXEC, - O_NONBLOCK, O_NONBLOCK as PIDFD_NONBLOCK, P_ALL, P_PID, P_PIDFD, SHUT_RD, SHUT_RDWR, SHUT_WR, - SOCK_DGRAM, SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET, SOCK_STREAM, SOL_SOCKET, SO_BROADCAST, - SO_ERROR, SO_KEEPALIVE, SO_LINGER, SO_PASSCRED, SO_RCVBUF, SO_RCVTIMEO_NEW, SO_RCVTIMEO_OLD, - SO_REUSEADDR, SO_SNDBUF, SO_SNDTIMEO_NEW, SO_SNDTIMEO_OLD, SO_TYPE, TCP_NODELAY, + __kernel_pid_t as pid_t, __kernel_time64_t as time_t, __kernel_timespec as timespec, iovec, + O_CLOEXEC, O_NOCTTY, O_NONBLOCK, O_RDWR, }; -pub(crate) use linux_raw_sys::general::{NFS_SUPER_MAGIC, PROC_SUPER_MAGIC, UTIME_NOW, UTIME_OMIT}; -pub(crate) use linux_raw_sys::general::{XATTR_CREATE, XATTR_REPLACE}; + +#[cfg(feature = "event")] +#[cfg(test)] +pub(crate) use linux_raw_sys::general::epoll_event; + +#[cfg(any( + feature = "fs", + all( + not(feature = "use-libc-auxv"), + not(target_vendor = "mustang"), + any( + feature = "param", + feature = "runtime", + feature = "time", + target_arch = "x86", + ) + ) +))] +pub(crate) use linux_raw_sys::general::{ + AT_FDCWD, NFS_SUPER_MAGIC, O_LARGEFILE, PROC_SUPER_MAGIC, UTIME_NOW, UTIME_OMIT, XATTR_CREATE, + XATTR_REPLACE, +}; + +#[cfg(feature = "io_uring")] +pub(crate) use linux_raw_sys::{general::open_how, io_uring::*}; + +#[cfg(feature = "net")] +pub(crate) use linux_raw_sys::{ + cmsg_macros::*, + general::{O_CLOEXEC as SOCK_CLOEXEC, O_NONBLOCK as SOCK_NONBLOCK}, + if_ether::*, + net::{ + AF_DECnet, __kernel_sa_family_t as sa_family_t, + __kernel_sockaddr_storage as sockaddr_storage, cmsghdr, in6_addr, in_addr, ip_mreq, + ipv6_mreq, linger, msghdr, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_un, socklen_t, + AF_APPLETALK, AF_ASH, AF_ATMPVC, AF_ATMSVC, AF_AX25, AF_BLUETOOTH, AF_BRIDGE, AF_CAN, + AF_ECONET, AF_IEEE802154, AF_INET, AF_INET6, AF_IPX, AF_IRDA, AF_ISDN, AF_IUCV, AF_KEY, + AF_LLC, AF_NETBEUI, AF_NETLINK, AF_NETROM, AF_PACKET, AF_PHONET, AF_PPPOX, AF_RDS, AF_ROSE, + AF_RXRPC, AF_SECURITY, AF_SNA, AF_TIPC, AF_UNIX, AF_UNSPEC, AF_WANPIPE, AF_X25, IPPROTO_AH, + IPPROTO_BEETPH, IPPROTO_COMP, IPPROTO_DCCP, IPPROTO_EGP, IPPROTO_ENCAP, IPPROTO_ESP, + IPPROTO_ETHERNET, IPPROTO_FRAGMENT, IPPROTO_GRE, IPPROTO_ICMP, IPPROTO_ICMPV6, IPPROTO_IDP, + IPPROTO_IGMP, IPPROTO_IP, IPPROTO_IPIP, IPPROTO_IPV6, IPPROTO_MH, IPPROTO_MPLS, + IPPROTO_MPTCP, IPPROTO_MTP, IPPROTO_PIM, IPPROTO_PUP, IPPROTO_RAW, IPPROTO_ROUTING, + IPPROTO_RSVP, IPPROTO_SCTP, IPPROTO_TCP, IPPROTO_TP, IPPROTO_UDP, IPPROTO_UDPLITE, + IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MULTICAST_HOPS, IPV6_MULTICAST_LOOP, + IPV6_UNICAST_HOPS, IPV6_V6ONLY, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_MULTICAST_LOOP, + IP_MULTICAST_TTL, IP_TTL, MSG_CMSG_CLOEXEC, MSG_CONFIRM, MSG_DONTROUTE, MSG_DONTWAIT, + MSG_EOR, MSG_ERRQUEUE, MSG_MORE, MSG_NOSIGNAL, MSG_OOB, MSG_PEEK, MSG_TRUNC, MSG_WAITALL, + SCM_CREDENTIALS, SCM_RIGHTS, SHUT_RD, SHUT_RDWR, SHUT_WR, SOCK_DGRAM, SOCK_RAW, SOCK_RDM, + SOCK_SEQPACKET, SOCK_STREAM, SOL_SOCKET, SO_BROADCAST, SO_ERROR, SO_KEEPALIVE, SO_LINGER, + SO_PASSCRED, SO_RCVBUF, SO_RCVTIMEO_NEW, SO_RCVTIMEO_NEW as SO_RCVTIMEO, SO_RCVTIMEO_OLD, + SO_REUSEADDR, SO_SNDBUF, SO_SNDTIMEO_NEW, SO_SNDTIMEO_NEW as SO_SNDTIMEO, SO_SNDTIMEO_OLD, + SO_TYPE, TCP_NODELAY, + }, + netlink::*, +}; + +#[cfg(any(feature = "process", feature = "runtime"))] +pub(crate) use linux_raw_sys::general::siginfo_t; + +#[cfg(feature = "process")] +pub(crate) use linux_raw_sys::general::{ + CLD_CONTINUED, CLD_DUMPED, CLD_EXITED, CLD_KILLED, CLD_STOPPED, CLD_TRAPPED, + O_NONBLOCK as PIDFD_NONBLOCK, P_ALL, P_PID, P_PIDFD, +}; + +#[cfg(feature = "termios")] +pub(crate) use linux_raw_sys::{ + general::{ + cc_t, speed_t, tcflag_t, termios, termios2, winsize, B0, B1000000, B110, B115200, B1152000, + B1200, B134, B150, B1500000, B1800, B19200, B200, B2000000, B230400, B2400, B2500000, B300, + B3000000, B3500000, B38400, B4000000, B460800, B4800, B50, B500000, B57600, B576000, B600, + B75, B921600, B9600, BOTHER, BRKINT, BS0, BS1, BSDLY, CBAUD, CBAUDEX, CIBAUD, CLOCAL, + CMSPAR, CR0, CR1, CR2, CR3, CRDLY, CREAD, CRTSCTS, CS5, CS6, CS7, CS8, CSIZE, CSTOPB, ECHO, + ECHOCTL, ECHOE, ECHOK, ECHOKE, ECHONL, ECHOPRT, EXTA, EXTB, EXTPROC, FF0, FF1, FFDLY, + FLUSHO, HUPCL, IBSHIFT, ICANON, ICRNL, IEXTEN, IGNBRK, IGNCR, IGNPAR, IMAXBEL, INLCR, + INPCK, ISIG, ISTRIP, IUCLC, IUTF8, IXANY, IXOFF, IXON, NCCS, NL0, NL1, NLDLY, NOFLSH, + OCRNL, OFDEL, OFILL, OLCUC, ONLCR, ONLRET, ONOCR, OPOST, PARENB, PARMRK, PARODD, PENDIN, + TAB0, TAB1, TAB2, TAB3, TABDLY, TCIFLUSH, TCIOFF, TCIOFLUSH, TCION, TCOFLUSH, TCOOFF, + TCOON, TCSADRAIN, TCSAFLUSH, TCSANOW, TOSTOP, VDISCARD, VEOF, VEOL, VEOL2, VERASE, VINTR, + VKILL, VLNEXT, VMIN, VQUIT, VREPRINT, VSTART, VSTOP, VSUSP, VSWTC, VT0, VT1, VTDLY, VTIME, + VWERASE, XCASE, XTABS, + }, + ioctl::{TCGETS2, TCSETS2, TCSETSF2, TCSETSW2}, +}; + +// On MIPS, `TCSANOW` et al have `TCSETS` added to them, so we need it to +// subtract it out. +#[cfg(all(feature = "termios", any(target_arch = "mips", target_arch = "mips64")))] +pub(crate) use linux_raw_sys::ioctl::TCSETS; + +// Define our own `uid_t` and `gid_t` if the kernel's versions are not 32-bit. +#[cfg(any(target_arch = "arm", target_arch = "sparc", target_arch = "x86"))] +pub(crate) type uid_t = u32; +#[cfg(any(target_arch = "arm", target_arch = "sparc", target_arch = "x86"))] +pub(crate) type gid_t = u32; + +// Bindgen infers `u32` for many of these macro types which meant to be +// used with `c_int` in the C APIs, so cast them to `c_int`. + +// Convert the signal constants from `u32` to `c_int`. +pub(crate) const SIGHUP: c_int = linux_raw_sys::general::SIGHUP as _; +pub(crate) const SIGINT: c_int = linux_raw_sys::general::SIGINT as _; +pub(crate) const SIGQUIT: c_int = linux_raw_sys::general::SIGQUIT as _; +pub(crate) const SIGILL: c_int = linux_raw_sys::general::SIGILL as _; +pub(crate) const SIGTRAP: c_int = linux_raw_sys::general::SIGTRAP as _; +pub(crate) const SIGABRT: c_int = linux_raw_sys::general::SIGABRT as _; +pub(crate) const SIGBUS: c_int = linux_raw_sys::general::SIGBUS as _; +pub(crate) const SIGFPE: c_int = linux_raw_sys::general::SIGFPE as _; +pub(crate) const SIGKILL: c_int = linux_raw_sys::general::SIGKILL as _; +pub(crate) const SIGUSR1: c_int = linux_raw_sys::general::SIGUSR1 as _; +pub(crate) const SIGSEGV: c_int = linux_raw_sys::general::SIGSEGV as _; +pub(crate) const SIGUSR2: c_int = linux_raw_sys::general::SIGUSR2 as _; +pub(crate) const SIGPIPE: c_int = linux_raw_sys::general::SIGPIPE as _; +pub(crate) const SIGALRM: c_int = linux_raw_sys::general::SIGALRM as _; +pub(crate) const SIGTERM: c_int = linux_raw_sys::general::SIGTERM as _; +#[cfg(not(any( + target_arch = "mips", + target_arch = "mips64", + target_arch = "sparc", + target_arch = "sparc64" +)))] +pub(crate) const SIGSTKFLT: c_int = linux_raw_sys::general::SIGSTKFLT as _; +pub(crate) const SIGCHLD: c_int = linux_raw_sys::general::SIGCHLD as _; +pub(crate) const SIGCONT: c_int = linux_raw_sys::general::SIGCONT as _; +pub(crate) const SIGSTOP: c_int = linux_raw_sys::general::SIGSTOP as _; +pub(crate) const SIGTSTP: c_int = linux_raw_sys::general::SIGTSTP as _; +pub(crate) const SIGTTIN: c_int = linux_raw_sys::general::SIGTTIN as _; +pub(crate) const SIGTTOU: c_int = linux_raw_sys::general::SIGTTOU as _; +pub(crate) const SIGURG: c_int = linux_raw_sys::general::SIGURG as _; +pub(crate) const SIGXCPU: c_int = linux_raw_sys::general::SIGXCPU as _; +pub(crate) const SIGXFSZ: c_int = linux_raw_sys::general::SIGXFSZ as _; +pub(crate) const SIGVTALRM: c_int = linux_raw_sys::general::SIGVTALRM as _; +pub(crate) const SIGPROF: c_int = linux_raw_sys::general::SIGPROF as _; +pub(crate) const SIGWINCH: c_int = linux_raw_sys::general::SIGWINCH as _; +pub(crate) const SIGIO: c_int = linux_raw_sys::general::SIGIO as _; +pub(crate) const SIGPWR: c_int = linux_raw_sys::general::SIGPWR as _; +pub(crate) const SIGSYS: c_int = linux_raw_sys::general::SIGSYS as _; +#[cfg(any( + target_arch = "mips", + target_arch = "mips64", + target_arch = "sparc", + target_arch = "sparc64" +))] +pub(crate) const SIGEMT: c_int = linux_raw_sys::general::SIGEMT as _; + +#[cfg(feature = "stdio")] +pub(crate) const STDIN_FILENO: c_int = linux_raw_sys::general::STDIN_FILENO as _; +#[cfg(feature = "stdio")] +pub(crate) const STDOUT_FILENO: c_int = linux_raw_sys::general::STDOUT_FILENO as _; +#[cfg(feature = "stdio")] +pub(crate) const STDERR_FILENO: c_int = linux_raw_sys::general::STDERR_FILENO as _; + +pub(crate) const PIPE_BUF: usize = linux_raw_sys::general::PIPE_BUF as _; + +pub(crate) const CLOCK_MONOTONIC: c_int = linux_raw_sys::general::CLOCK_MONOTONIC as _; +pub(crate) const CLOCK_REALTIME: c_int = linux_raw_sys::general::CLOCK_REALTIME as _; +pub(crate) const CLOCK_MONOTONIC_RAW: c_int = linux_raw_sys::general::CLOCK_MONOTONIC_RAW as _; +pub(crate) const CLOCK_MONOTONIC_COARSE: c_int = + linux_raw_sys::general::CLOCK_MONOTONIC_COARSE as _; +pub(crate) const CLOCK_REALTIME_COARSE: c_int = linux_raw_sys::general::CLOCK_REALTIME_COARSE as _; +pub(crate) const CLOCK_THREAD_CPUTIME_ID: c_int = + linux_raw_sys::general::CLOCK_THREAD_CPUTIME_ID as _; +pub(crate) const CLOCK_PROCESS_CPUTIME_ID: c_int = + linux_raw_sys::general::CLOCK_PROCESS_CPUTIME_ID as _; diff --git a/vendor/rustix/src/backend/linux_raw/conv.rs b/vendor/rustix/src/backend/linux_raw/conv.rs index f02b5c046..05d040204 100644 --- a/vendor/rustix/src/backend/linux_raw/conv.rs +++ b/vendor/rustix/src/backend/linux_raw/conv.rs @@ -20,22 +20,27 @@ use super::io::errno::try_decode_error; #[cfg(target_pointer_width = "64")] use super::io::errno::try_decode_u64; #[cfg(not(debug_assertions))] -use super::io::errno::{decode_c_uint_infallible, decode_usize_infallible}; +use super::io::errno::{ + decode_c_int_infallible, decode_c_uint_infallible, decode_usize_infallible, +}; use super::io::errno::{ try_decode_c_int, try_decode_c_uint, try_decode_raw_fd, try_decode_usize, try_decode_void, try_decode_void_star, }; use super::reg::{raw_arg, ArgNumber, ArgReg, RetReg, R0}; -#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))] -use super::time::types::ClockId; #[cfg(feature = "time")] use super::time::types::TimerfdClockId; +#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))] +use crate::clockid::ClockId; use crate::fd::OwnedFd; use crate::ffi::CStr; -#[cfg(feature = "fs")] -use crate::fs::{FileType, Mode, OFlags}; use crate::io; -use crate::process::{Pid, Resource, Signal}; +#[cfg(any(feature = "process", feature = "runtime", feature = "termios"))] +use crate::pid::Pid; +#[cfg(feature = "process")] +use crate::process::Resource; +#[cfg(any(feature = "process", feature = "runtime"))] +use crate::signal::Signal; use crate::utils::{as_mut_ptr, as_ptr}; use core::mem::MaybeUninit; use core::ptr::null_mut; @@ -44,10 +49,7 @@ use linux_raw_sys::general::__kernel_clockid_t; #[cfg(target_pointer_width = "64")] use linux_raw_sys::general::__kernel_loff_t; #[cfg(feature = "net")] -use linux_raw_sys::general::socklen_t; -#[cfg(target_pointer_width = "32")] -#[cfg(feature = "fs")] -use linux_raw_sys::general::O_LARGEFILE; +use linux_raw_sys::net::socklen_t; /// Convert `SYS_*` constants for socketcall. #[cfg(target_arch = "x86")] @@ -143,9 +145,9 @@ impl<'a, Num: ArgNumber> From> for ArgReg<'a, Num> { impl<'a, Num: ArgNumber> From> for ArgReg<'a, Num> { #[inline] fn from(fd: BorrowedFd<'a>) -> Self { - // SAFETY: `BorrowedFd` ensures that the file descriptor is valid, and the - // lifetime parameter on the resulting `ArgReg` ensures that the result is - // bounded by the `BorrowedFd`'s lifetime. + // SAFETY: `BorrowedFd` ensures that the file descriptor is valid, and + // the lifetime parameter on the resulting `ArgReg` ensures that the + // result is bounded by the `BorrowedFd`'s lifetime. unsafe { raw_fd(fd.as_raw_fd()) } } } @@ -160,7 +162,7 @@ impl<'a, Num: ArgNumber> From> for ArgReg<'a, Num> { pub(super) unsafe fn raw_fd<'a, Num: ArgNumber>(fd: RawFd) -> ArgReg<'a, Num> { // Use `no_fd` when passing `-1` is intended. #[cfg(feature = "fs")] - debug_assert!(fd == crate::fs::cwd().as_raw_fd() || fd >= 0); + debug_assert!(fd == crate::fs::CWD.as_raw_fd() || fd >= 0); // Don't pass the `io_uring_register_files_skip` sentry value this way. #[cfg(feature = "io_uring")] @@ -294,116 +296,235 @@ pub(super) fn socklen_t<'a, Num: ArgNumber>(i: socklen_t) -> ArgReg<'a, Num> { pass_usize(i as usize) } -#[cfg(feature = "fs")] -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { - #[inline] - fn from(mode: Mode) -> Self { - pass_usize(mode.bits() as usize) +#[cfg(any( + feature = "fs", + all( + not(feature = "use-libc-auxv"), + not(target_vendor = "mustang"), + any( + feature = "param", + feature = "runtime", + feature = "time", + target_arch = "x86", + ) + ) +))] +pub(crate) mod fs { + use super::*; + use crate::fs::{FileType, Mode, OFlags}; + #[cfg(target_pointer_width = "32")] + use linux_raw_sys::general::O_LARGEFILE; + + impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + #[inline] + fn from(mode: Mode) -> Self { + pass_usize(mode.bits() as usize) + } } -} -#[cfg(feature = "fs")] -impl<'a, Num: ArgNumber> From<(Mode, FileType)> for ArgReg<'a, Num> { - #[inline] - fn from(pair: (Mode, FileType)) -> Self { - pass_usize(pair.0.as_raw_mode() as usize | pair.1.as_raw_mode() as usize) + impl<'a, Num: ArgNumber> From<(Mode, FileType)> for ArgReg<'a, Num> { + #[inline] + fn from(pair: (Mode, FileType)) -> Self { + pass_usize(pair.0.as_raw_mode() as usize | pair.1.as_raw_mode() as usize) + } + } + + impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::fs::AtFlags) -> Self { + c_uint(flags.bits()) + } } -} -#[cfg(feature = "fs")] -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::fs::XattrFlags) -> Self { + c_uint(flags.bits()) + } + } + + impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::fs::inotify::CreateFlags) -> Self { + c_uint(flags.bits()) + } + } + + impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::fs::inotify::WatchFlags) -> Self { + c_uint(flags.bits()) + } + } + + impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::fs::MemfdFlags) -> Self { + c_uint(flags.bits()) + } + } + + impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::fs::RenameFlags) -> Self { + c_uint(flags.bits()) + } + } + + impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::fs::StatxFlags) -> Self { + c_uint(flags.bits()) + } + } + + #[cfg(target_pointer_width = "32")] #[inline] - fn from(flags: crate::fs::AtFlags) -> Self { - c_uint(flags.bits()) + fn oflags_bits(oflags: OFlags) -> c::c_uint { + let mut bits = oflags.bits(); + // Add `O_LARGEFILE`, unless `O_PATH` is set, as Linux returns `EINVAL` + // when both are set. + if !oflags.contains(OFlags::PATH) { + bits |= O_LARGEFILE; + } + bits } -} -#[cfg(feature = "fs")] -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + #[cfg(target_pointer_width = "64")] #[inline] - fn from(flags: crate::fs::XattrFlags) -> Self { - c_uint(flags.bits()) + const fn oflags_bits(oflags: OFlags) -> c::c_uint { + oflags.bits() } -} -#[cfg(feature = "fs")] -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + #[inline] + fn from(oflags: OFlags) -> Self { + pass_usize(oflags_bits(oflags) as usize) + } + } + + /// Convert an `OFlags` into a `u64` for use in the `open_how` struct. #[inline] - fn from(flags: crate::fs::inotify::CreateFlags) -> Self { - c_uint(flags.bits()) + pub(crate) fn oflags_for_open_how(oflags: OFlags) -> u64 { + u64::from(oflags_bits(oflags)) + } + + impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::fs::FallocateFlags) -> Self { + c_uint(flags.bits()) + } + } + + impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + #[inline] + fn from(advice: crate::fs::Advice) -> Self { + c_uint(advice as c::c_uint) + } + } + + impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::fs::SealFlags) -> Self { + c_uint(flags.bits()) + } + } + + impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + #[inline] + fn from(access: crate::fs::Access) -> Self { + c_uint(access.bits()) + } + } + + impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::backend::fs::types::MountFlagsArg) -> Self { + c_uint(flags.0) + } + } + + impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { + #[inline] + fn from(flags: crate::backend::fs::types::UnmountFlags) -> Self { + c_uint(flags.bits()) + } } } -#[cfg(feature = "fs")] -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { +impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] - fn from(flags: crate::fs::inotify::WatchFlags) -> Self { + fn from(flags: crate::io::FdFlags) -> Self { c_uint(flags.bits()) } } -#[cfg(feature = "fs")] -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { +#[cfg(feature = "pipe")] +impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] - fn from(flags: crate::fs::MemfdFlags) -> Self { + fn from(flags: crate::pipe::PipeFlags) -> Self { c_uint(flags.bits()) } } -#[cfg(feature = "fs")] -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { +#[cfg(feature = "pipe")] +impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] - fn from(flags: crate::fs::RenameFlags) -> Self { + fn from(flags: crate::pipe::SpliceFlags) -> Self { c_uint(flags.bits()) } } -#[cfg(feature = "fs")] -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { +impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] - fn from(flags: crate::fs::StatxFlags) -> Self { + fn from(flags: crate::io::DupFlags) -> Self { c_uint(flags.bits()) } } -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { +impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] - fn from(flags: crate::io::FdFlags) -> Self { + fn from(flags: crate::io::ReadWriteFlags) -> Self { c_uint(flags.bits()) } } -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { +#[cfg(feature = "process")] +impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] - fn from(flags: crate::io::PipeFlags) -> Self { + fn from(flags: crate::process::PidfdFlags) -> Self { c_uint(flags.bits()) } } -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { +#[cfg(feature = "pty")] +impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] - fn from(flags: crate::io::DupFlags) -> Self { + fn from(flags: crate::pty::OpenptFlags) -> Self { c_uint(flags.bits()) } } -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { +#[cfg(feature = "thread")] +impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] - fn from(flags: crate::io::ReadWriteFlags) -> Self { + fn from(flags: crate::thread::UnshareFlags) -> Self { c_uint(flags.bits()) } } -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { +#[cfg(feature = "event")] +impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] - fn from(flags: crate::io::EventfdFlags) -> Self { + fn from(flags: crate::event::EventfdFlags) -> Self { c_uint(flags.bits()) } } -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { +#[cfg(feature = "event")] +impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] - fn from(flags: crate::io::epoll::CreateFlags) -> Self { + fn from(flags: crate::event::epoll::CreateFlags) -> Self { c_uint(flags.bits()) } } @@ -464,6 +585,7 @@ impl<'a, Num: ArgNumber> From for A } } +#[cfg(feature = "process")] impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { @@ -473,6 +595,7 @@ impl<'a, Num: ArgNumber> From } } +#[cfg(feature = "process")] impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] fn from(cpuid: crate::process::Cpuid) -> Self { @@ -489,54 +612,11 @@ pub(super) fn dev_t<'a, Num: ArgNumber>(dev: u64) -> ArgReg<'a, Num> { #[cfg(target_pointer_width = "32")] #[inline] pub(super) fn dev_t<'a, Num: ArgNumber>(dev: u64) -> io::Result> { - use core::convert::TryInto; Ok(pass_usize(dev.try_into().map_err(|_err| io::Errno::INVAL)?)) } -#[cfg(target_pointer_width = "32")] -#[cfg(feature = "fs")] -#[inline] -fn oflags_bits(oflags: OFlags) -> c::c_uint { - let mut bits = oflags.bits(); - // Add `O_LARGEFILE`, unless `O_PATH` is set, as Linux returns `EINVAL` - // when both are set. - if !oflags.contains(OFlags::PATH) { - bits |= O_LARGEFILE; - } - bits -} - -#[cfg(target_pointer_width = "64")] -#[cfg(feature = "fs")] -#[inline] -const fn oflags_bits(oflags: OFlags) -> c::c_uint { - oflags.bits() -} - -#[cfg(feature = "fs")] -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { - #[inline] - fn from(oflags: OFlags) -> Self { - pass_usize(oflags_bits(oflags) as usize) - } -} - -/// Convert an `OFlags` into a `u64` for use in the `open_how` struct. -#[cfg(feature = "fs")] -#[inline] -pub(super) fn oflags_for_open_how(oflags: OFlags) -> u64 { - u64::from(oflags_bits(oflags)) -} - -#[cfg(feature = "fs")] -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { - #[inline] - fn from(flags: crate::fs::FallocateFlags) -> Self { - c_uint(flags.bits()) - } -} - /// Convert a `Resource` into a syscall argument. +#[cfg(feature = "process")] impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] fn from(resource: Resource) -> Self { @@ -544,6 +624,7 @@ impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { } } +#[cfg(any(feature = "process", feature = "runtime", feature = "termios"))] impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] fn from(pid: Pid) -> Self { @@ -551,11 +632,13 @@ impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { } } +#[cfg(feature = "process")] #[inline] pub(super) fn negative_pid<'a, Num: ArgNumber>(pid: Pid) -> ArgReg<'a, Num> { pass_usize(pid.as_raw_nonzero().get().wrapping_neg() as usize) } +#[cfg(any(feature = "process", feature = "runtime"))] impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] fn from(sig: Signal) -> Self { @@ -563,22 +646,6 @@ impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { } } -#[cfg(feature = "fs")] -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { - #[inline] - fn from(advice: crate::fs::Advice) -> Self { - c_uint(advice as c::c_uint) - } -} - -#[cfg(feature = "fs")] -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { - #[inline] - fn from(flags: crate::fs::SealFlags) -> Self { - c_uint(flags.bits()) - } -} - #[cfg(feature = "io_uring")] impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] @@ -663,14 +730,6 @@ impl<'a, Num: ArgNumber> From<(crate::thread::FutexOperation, crate::thread::Fut } } -#[cfg(feature = "fs")] -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { - #[inline] - fn from(access: crate::fs::Access) -> Self { - c_uint(access.bits()) - } -} - #[cfg(feature = "net")] impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] @@ -680,10 +739,13 @@ impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { } #[cfg(feature = "net")] -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { +impl<'a, Num: ArgNumber> From> for ArgReg<'a, Num> { #[inline] - fn from(protocol: crate::net::Protocol) -> Self { - c_uint(protocol.0) + fn from(protocol: Option) -> Self { + c_uint(match protocol { + Some(p) => p.0.get(), + None => 0, + }) } } @@ -701,34 +763,18 @@ impl<'a, Num: ArgNumber, T> From<&'a mut [MaybeUninit]> for ArgReg<'a, Num> { } } -#[cfg(feature = "fs")] -#[cfg(any(target_os = "android", target_os = "linux"))] -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { - #[inline] - fn from(flags: crate::backend::fs::types::MountFlagsArg) -> Self { - c_uint(flags.0) - } -} - -#[cfg(feature = "fs")] -#[cfg(any(target_os = "android", target_os = "linux"))] -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { - #[inline] - fn from(flags: crate::backend::fs::types::UnmountFlags) -> Self { - c_uint(flags.bits()) - } -} - -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { +#[cfg(any(feature = "process", feature = "thread"))] +impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] - fn from(t: crate::process::Uid) -> Self { + fn from(t: crate::ugid::Uid) -> Self { c_uint(t.as_raw()) } } -impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { +#[cfg(any(feature = "process", feature = "thread"))] +impl<'a, Num: ArgNumber> From for ArgReg<'a, Num> { #[inline] - fn from(t: crate::process::Gid) -> Self { + fn from(t: crate::ugid::Gid) -> Self { c_uint(t.as_raw()) } } @@ -830,6 +876,25 @@ pub(super) unsafe fn ret_usize_infallible(raw: RetReg) -> usize { } } +/// Convert a `c_int` returned from a syscall that effectively always +/// returns a `c_int`. +/// +/// # Safety +/// +/// This function must only be used with return values from infallible +/// syscalls. +#[inline] +pub(super) unsafe fn ret_c_int_infallible(raw: RetReg) -> c::c_int { + #[cfg(debug_assertions)] + { + try_decode_c_int(raw).unwrap() + } + #[cfg(not(debug_assertions))] + { + decode_c_int_infallible(raw) + } +} + /// Convert a `c_uint` returned from a syscall that effectively always /// returns a `c_uint`. /// diff --git a/vendor/rustix/src/backend/linux_raw/elf.rs b/vendor/rustix/src/backend/linux_raw/elf.rs index 87fb5fa0f..7797f4e21 100644 --- a/vendor/rustix/src/backend/linux_raw/elf.rs +++ b/vendor/rustix/src/backend/linux_raw/elf.rs @@ -1,4 +1,4 @@ -//! The ELF ABI. +//! The ELF ABI. 🧝 #![allow(non_snake_case)] #![cfg_attr( diff --git a/vendor/rustix/src/backend/linux_raw/event/epoll.rs b/vendor/rustix/src/backend/linux_raw/event/epoll.rs new file mode 100644 index 000000000..6577feb51 --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/event/epoll.rs @@ -0,0 +1,462 @@ +//! epoll support. +//! +//! This is an experiment, and it isn't yet clear whether epoll is the right +//! level of abstraction at which to introduce safety. But it works fairly well +//! in simple examples 🙂. +//! +//! # Examples +//! +//! ```no_run +//! # #[cfg(feature = "net")] +//! # fn main() -> std::io::Result<()> { +//! use rustix::event::epoll; +//! use rustix::fd::AsFd; +//! use rustix::io::{ioctl_fionbio, read, write}; +//! use rustix::net::{ +//! accept, bind_v4, listen, socket, AddressFamily, Ipv4Addr, SocketAddrV4, SocketType, +//! }; +//! use std::collections::HashMap; +//! use std::os::unix::io::AsRawFd; +//! +//! // Create a socket and listen on it. +//! let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, None)?; +//! bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0))?; +//! listen(&listen_sock, 1)?; +//! +//! // Create an epoll object. Using `Owning` here means the epoll object will +//! // take ownership of the file descriptors registered with it. +//! let epoll = epoll::create(epoll::CreateFlags::CLOEXEC)?; +//! +//! // Register the socket with the epoll object. +//! epoll::add( +//! &epoll, +//! &listen_sock, +//! epoll::EventData::new_u64(1), +//! epoll::EventFlags::IN, +//! )?; +//! +//! // Keep track of the sockets we've opened. +//! let mut next_id = epoll::EventData::new_u64(2); +//! let mut sockets = HashMap::new(); +//! +//! // Process events. +//! let mut event_list = epoll::EventVec::with_capacity(4); +//! loop { +//! epoll::wait(&epoll, &mut event_list, -1)?; +//! for event in &event_list { +//! let target = event.data; +//! if target.u64() == 1 { +//! // Accept a new connection, set it to non-blocking, and +//! // register to be notified when it's ready to write to. +//! let conn_sock = accept(&listen_sock)?; +//! ioctl_fionbio(&conn_sock, true)?; +//! epoll::add( +//! &epoll, +//! &conn_sock, +//! next_id, +//! epoll::EventFlags::OUT | epoll::EventFlags::ET, +//! )?; +//! +//! // Keep track of the socket. +//! sockets.insert(next_id, conn_sock); +//! next_id = epoll::EventData::new_u64(next_id.u64() + 1); +//! } else { +//! // Write a message to the stream and then unregister it. +//! let target = sockets.remove(&target).unwrap(); +//! write(&target, b"hello\n")?; +//! let _ = epoll::delete(&epoll, &target)?; +//! } +//! } +//! } +//! # } +//! # #[cfg(not(feature = "net"))] +//! # fn main() {} +//! ``` + +#![allow(unsafe_code)] + +use crate::backend::c; +use crate::backend::event::syscalls; +use crate::fd::{AsFd, AsRawFd, OwnedFd}; +use crate::io; +use alloc::vec::Vec; +use bitflags::bitflags; +use core::ffi::c_void; +use core::hash::{Hash, Hasher}; +use core::slice; + +bitflags! { + /// `EPOLL_*` for use with [`new`]. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct CreateFlags: c::c_uint { + /// `EPOLL_CLOEXEC` + const CLOEXEC = linux_raw_sys::general::EPOLL_CLOEXEC; + } +} + +bitflags! { + /// `EPOLL*` for use with [`add`]. + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct EventFlags: u32 { + /// `EPOLLIN` + const IN = linux_raw_sys::general::EPOLLIN as u32; + + /// `EPOLLOUT` + const OUT = linux_raw_sys::general::EPOLLOUT as u32; + + /// `EPOLLPRI` + const PRI = linux_raw_sys::general::EPOLLPRI as u32; + + /// `EPOLLERR` + const ERR = linux_raw_sys::general::EPOLLERR as u32; + + /// `EPOLLHUP` + const HUP = linux_raw_sys::general::EPOLLHUP as u32; + + /// `EPOLLRDNORM` + const RDNORM = linux_raw_sys::general::EPOLLRDNORM as u32; + + /// `EPOLLRDBAND` + const RDBAND = linux_raw_sys::general::EPOLLRDBAND as u32; + + /// `EPOLLWRNORM` + const WRNORM = linux_raw_sys::general::EPOLLWRNORM as u32; + + /// `EPOLLWRBAND` + const WRBAND = linux_raw_sys::general::EPOLLWRBAND as u32; + + /// `EPOLLMSG` + const MSG = linux_raw_sys::general::EPOLLMSG as u32; + + /// `EPOLLRDHUP` + const RDHUP = linux_raw_sys::general::EPOLLRDHUP as u32; + + /// `EPOLLET` + const ET = linux_raw_sys::general::EPOLLET as u32; + + /// `EPOLLONESHOT` + const ONESHOT = linux_raw_sys::general::EPOLLONESHOT as u32; + + /// `EPOLLWAKEUP` + const WAKEUP = linux_raw_sys::general::EPOLLWAKEUP as u32; + + /// `EPOLLEXCLUSIVE` + const EXCLUSIVE = linux_raw_sys::general::EPOLLEXCLUSIVE as u32; + } +} + +/// `epoll_create1(flags)`—Creates a new epoll object. +/// +/// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file +/// descriptor from being implicitly passed across `exec` boundaries. +#[inline] +#[doc(alias = "epoll_create1")] +pub fn create(flags: CreateFlags) -> io::Result { + syscalls::epoll_create(flags) +} + +/// `epoll_ctl(self, EPOLL_CTL_ADD, data, event)`—Adds an element to an +/// epoll object. +/// +/// This registers interest in any of the events set in `events` occurring +/// on the file descriptor associated with `data`. +/// +/// If [`delete`] is not called on the I/O source passed into this function +/// before the I/O source is `close`d, then the `epoll` will act as if the I/O +/// source is still registered with it. This can lead to spurious events being +/// returned from [`wait`]. If a file descriptor is an +/// `Arc`, then `epoll` can be thought to maintain a +/// `Weak` to the file descriptor. +#[doc(alias = "epoll_ctl")] +#[inline] +pub fn add( + epoll: impl AsFd, + source: impl AsFd, + data: EventData, + event_flags: EventFlags, +) -> io::Result<()> { + // SAFETY: We're calling `epoll_ctl` via FFI and we know how it + // behaves. + unsafe { + syscalls::epoll_add( + epoll.as_fd(), + source.as_fd().as_raw_fd(), + &Event { + flags: event_flags, + data, + }, + ) + } +} + +/// `epoll_ctl(self, EPOLL_CTL_MOD, target, event)`—Modifies an element in +/// a given epoll object. +/// +/// This sets the events of interest with `target` to `events`. +#[doc(alias = "epoll_ctl")] +#[inline] +pub fn modify( + epoll: impl AsFd, + source: impl AsFd, + data: EventData, + event_flags: EventFlags, +) -> io::Result<()> { + // SAFETY: We're calling `epoll_ctl` via FFI and we know how it + // behaves. + unsafe { + let raw_fd = source.as_fd().as_raw_fd(); + syscalls::epoll_mod( + epoll.as_fd(), + raw_fd, + &Event { + flags: event_flags, + data, + }, + ) + } +} + +/// `epoll_ctl(self, EPOLL_CTL_DEL, target, NULL)`—Removes an element in +/// a given epoll object. +#[doc(alias = "epoll_ctl")] +#[inline] +pub fn delete(epoll: impl AsFd, source: impl AsFd) -> io::Result<()> { + // SAFETY: We're calling `epoll_ctl` via FFI and we know how it + // behaves. + unsafe { + let raw_fd = source.as_fd().as_raw_fd(); + syscalls::epoll_del(epoll.as_fd(), raw_fd) + } +} + +/// `epoll_wait(self, events, timeout)`—Waits for registered events of +/// interest. +/// +/// For each event of interest, an element is written to `events`. On +/// success, this returns the number of written elements. +#[inline] +pub fn wait(epoll: impl AsFd, event_list: &mut EventVec, timeout: c::c_int) -> io::Result<()> { + // SAFETY: We're calling `epoll_wait` via FFI and we know how it + // behaves. + unsafe { + event_list.events.set_len(0); + let nfds = syscalls::epoll_wait( + epoll.as_fd(), + event_list.events[..].as_mut_ptr().cast(), + event_list.events.capacity(), + timeout, + )?; + event_list.events.set_len(nfds); + } + + Ok(()) +} + +/// An iterator over the `Event`s in an `EventVec`. +pub struct Iter<'a> { + /// Use `Copied` to copy the struct, since `Event` is `packed` on some + /// platforms, and it's common for users to directly destructure it, + /// which would lead to errors about forming references to packed fields. + iter: core::iter::Copied>, +} + +impl<'a> Iterator for Iter<'a> { + type Item = Event; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next() + } +} + +/// A record of an event that occurred. +#[repr(C)] +#[cfg_attr(target_arch = "x86_64", repr(packed))] +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +pub struct Event { + /// Which specific event(s) occurred. + pub flags: EventFlags, + /// User data. + pub data: EventData, +} + +/// Data assocated with an [`Event`]. This can either be a 64-bit integer value +/// or a pointer which preserves pointer provenance. +#[repr(C)] +#[derive(Copy, Clone)] +pub union EventData { + /// A 64-bit integer value. + as_u64: u64, + + /// A `*mut c_void` which preserves pointer provenance, extended to be + /// 64-bit so that if we read the value as a `u64` union field, we don't + /// get uninitialized memory. + sixty_four_bit_pointer: SixtyFourBitPointer, +} + +impl EventData { + /// Construct a new value containing a `u64`. + #[inline] + pub const fn new_u64(value: u64) -> Self { + Self { as_u64: value } + } + + /// Construct a new value containing a `*mut c_void`. + #[inline] + pub const fn new_ptr(value: *mut c_void) -> Self { + Self { + sixty_four_bit_pointer: SixtyFourBitPointer { + pointer: value, + #[cfg(target_pointer_width = "32")] + _padding: 0, + }, + } + } + + /// Return the value as a `u64`. + /// + /// If the stored value was a pointer, the pointer is zero-extended to + /// a `u64`. + #[inline] + pub fn u64(self) -> u64 { + unsafe { self.as_u64 } + } + + /// Return the value as a `*mut c_void`. + /// + /// If the stored value was a `u64`, the least-significant bits of the + /// `u64` are returned as a pointer value. + #[inline] + pub fn ptr(self) -> *mut c_void { + unsafe { self.sixty_four_bit_pointer.pointer } + } +} + +impl PartialEq for EventData { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.u64() == other.u64() + } +} + +impl Eq for EventData {} + +impl Hash for EventData { + #[inline] + fn hash(&self, state: &mut H) { + self.u64().hash(state) + } +} + +#[repr(C)] +#[derive(Copy, Clone)] +struct SixtyFourBitPointer { + #[cfg(target_endian = "big")] + #[cfg(target_pointer_width = "32")] + _padding: u32, + + pointer: *mut c_void, + + #[cfg(target_endian = "little")] + #[cfg(target_pointer_width = "32")] + _padding: u32, +} + +/// A vector of `Event`s, plus context for interpreting them. +pub struct EventVec { + events: Vec, +} + +impl EventVec { + /// Constructs an `EventVec` from raw pointer, length, and capacity. + /// + /// # Safety + /// + /// This function calls [`Vec::from_raw_parts`] with its arguments. + /// + /// [`Vec::from_raw_parts`]: https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.from_raw_parts + #[inline] + pub unsafe fn from_raw_parts(ptr: *mut Event, len: usize, capacity: usize) -> Self { + Self { + events: Vec::from_raw_parts(ptr, len, capacity), + } + } + + /// Constructs an `EventVec` with memory for `capacity` `Event`s. + #[inline] + pub fn with_capacity(capacity: usize) -> Self { + Self { + events: Vec::with_capacity(capacity), + } + } + + /// Returns the current `Event` capacity of this `EventVec`. + #[inline] + pub fn capacity(&self) -> usize { + self.events.capacity() + } + + /// Reserves enough memory for at least `additional` more `Event`s. + #[inline] + pub fn reserve(&mut self, additional: usize) { + self.events.reserve(additional); + } + + /// Reserves enough memory for exactly `additional` more `Event`s. + #[inline] + pub fn reserve_exact(&mut self, additional: usize) { + self.events.reserve_exact(additional); + } + + /// Clears all the `Events` out of this `EventVec`. + #[inline] + pub fn clear(&mut self) { + self.events.clear(); + } + + /// Shrinks the capacity of this `EventVec` as much as possible. + #[inline] + pub fn shrink_to_fit(&mut self) { + self.events.shrink_to_fit(); + } + + /// Returns an iterator over the `Event`s in this `EventVec`. + #[inline] + pub fn iter(&self) -> Iter<'_> { + Iter { + iter: self.events.iter().copied(), + } + } + + /// Returns the number of `Event`s logically contained in this `EventVec`. + #[inline] + pub fn len(&mut self) -> usize { + self.events.len() + } + + /// Tests whether this `EventVec` is logically empty. + #[inline] + pub fn is_empty(&mut self) -> bool { + self.events.is_empty() + } +} + +impl<'a> IntoIterator for &'a EventVec { + type IntoIter = Iter<'a>; + type Item = Event; + + #[inline] + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +#[test] +fn test_epoll_layouts() { + check_renamed_type!(Event, epoll_event); + check_renamed_type!(Event, epoll_event); + check_renamed_struct_renamed_field!(Event, epoll_event, flags, events); + check_renamed_struct_renamed_field!(Event, epoll_event, data, data); +} diff --git a/vendor/rustix/src/backend/linux_raw/event/mod.rs b/vendor/rustix/src/backend/linux_raw/event/mod.rs new file mode 100644 index 000000000..605de2538 --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/event/mod.rs @@ -0,0 +1,4 @@ +pub mod epoll; +pub(crate) mod poll_fd; +pub(crate) mod syscalls; +pub(crate) mod types; diff --git a/vendor/rustix/src/backend/linux_raw/event/poll_fd.rs b/vendor/rustix/src/backend/linux_raw/event/poll_fd.rs new file mode 100644 index 000000000..906efe0ef --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/event/poll_fd.rs @@ -0,0 +1,95 @@ +use crate::fd::{AsFd, BorrowedFd}; +use bitflags::bitflags; + +bitflags! { + /// `POLL*` flags for use with [`poll`]. + /// + /// [`poll`]: crate::io::poll + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct PollFlags: u16 { + /// `POLLIN` + const IN = linux_raw_sys::general::POLLIN as u16; + /// `POLLPRI` + const PRI = linux_raw_sys::general::POLLPRI as u16; + /// `POLLOUT` + const OUT = linux_raw_sys::general::POLLOUT as u16; + /// `POLLRDNORM` + const RDNORM = linux_raw_sys::general::POLLRDNORM as u16; + /// `POLLWRNORM` + const WRNORM = linux_raw_sys::general::POLLWRNORM as u16; + /// `POLLRDBAND` + const RDBAND = linux_raw_sys::general::POLLRDBAND as u16; + /// `POLLWRBAND` + const WRBAND = linux_raw_sys::general::POLLWRBAND as u16; + /// `POLLERR` + const ERR = linux_raw_sys::general::POLLERR as u16; + /// `POLLHUP` + const HUP = linux_raw_sys::general::POLLHUP as u16; + /// `POLLNVAL` + const NVAL = linux_raw_sys::general::POLLNVAL as u16; + /// `POLLRDHUP` + const RDHUP = linux_raw_sys::general::POLLRDHUP as u16; + } +} + +/// `struct pollfd`—File descriptor and flags for use with [`poll`]. +/// +/// [`poll`]: crate::event::poll +#[doc(alias = "pollfd")] +#[repr(C)] +#[derive(Debug, Clone)] +pub struct PollFd<'fd> { + pub(crate) fd: BorrowedFd<'fd>, + pub(crate) events: u16, + pub(crate) revents: u16, +} + +impl<'fd> PollFd<'fd> { + /// Constructs a new `PollFd` holding `fd` and `events`. + #[inline] + pub fn new(fd: &'fd Fd, events: PollFlags) -> Self { + Self::from_borrowed_fd(fd.as_fd(), events) + } + + /// Sets the contained file descriptor to `fd`. + #[inline] + pub fn set_fd(&mut self, fd: &'fd Fd) { + self.fd = fd.as_fd(); + } + + /// Clears the ready events. + #[inline] + pub fn clear_revents(&mut self) { + self.revents = 0; + } + + /// Constructs a new `PollFd` holding `fd` and `events`. + /// + /// This is the same as `new`, but can be used to avoid borrowing the + /// `BorrowedFd`, which can be tricky in situations where the `BorrowedFd` + /// is a temporary. + #[inline] + pub fn from_borrowed_fd(fd: BorrowedFd<'fd>, events: PollFlags) -> Self { + Self { + fd, + events: events.bits(), + revents: 0, + } + } + + /// Returns the ready events. + #[inline] + pub fn revents(&self) -> PollFlags { + // Use `unwrap()` here because in theory we know we know all the bits + // the OS might set here, but OS's have added extensions in the past. + PollFlags::from_bits(self.revents).unwrap() + } +} + +impl<'fd> AsFd for PollFd<'fd> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + self.fd.as_fd() + } +} diff --git a/vendor/rustix/src/backend/linux_raw/event/syscalls.rs b/vendor/rustix/src/backend/linux_raw/event/syscalls.rs new file mode 100644 index 000000000..6d6b35d75 --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/event/syscalls.rs @@ -0,0 +1,131 @@ +//! linux_raw syscalls supporting `rustix::event`. +//! +//! # Safety +//! +//! See the `rustix::backend` module documentation for details. +#![allow(unsafe_code)] +#![allow(clippy::undocumented_unsafe_blocks)] + +use crate::backend::c; +use crate::backend::conv::{ + by_ref, c_int, c_uint, pass_usize, raw_fd, ret, ret_owned_fd, ret_usize, slice_mut, zero, +}; +use crate::event::{epoll, EventfdFlags, PollFd}; +use crate::fd::{BorrowedFd, OwnedFd}; +use crate::io; +use linux_raw_sys::general::{EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD}; +#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] +use { + crate::backend::conv::{opt_ref, size_of}, + linux_raw_sys::general::{__kernel_timespec, kernel_sigset_t}, +}; + +#[inline] +pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result { + let (fds_addr_mut, fds_len) = slice_mut(fds); + + #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] + unsafe { + let timeout = if timeout >= 0 { + Some(__kernel_timespec { + tv_sec: (timeout as i64) / 1000, + tv_nsec: (timeout as i64) % 1000 * 1_000_000, + }) + } else { + None + }; + ret_usize(syscall!( + __NR_ppoll, + fds_addr_mut, + fds_len, + opt_ref(timeout.as_ref()), + zero(), + size_of::() + )) + } + #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))] + unsafe { + ret_usize(syscall!(__NR_poll, fds_addr_mut, fds_len, c_int(timeout))) + } +} + +#[inline] +pub(crate) fn epoll_create(flags: epoll::CreateFlags) -> io::Result { + unsafe { ret_owned_fd(syscall_readonly!(__NR_epoll_create1, flags)) } +} + +#[inline] +pub(crate) unsafe fn epoll_add( + epfd: BorrowedFd<'_>, + fd: c::c_int, + event: &epoll::Event, +) -> io::Result<()> { + ret(syscall_readonly!( + __NR_epoll_ctl, + epfd, + c_uint(EPOLL_CTL_ADD), + raw_fd(fd), + by_ref(event) + )) +} + +#[inline] +pub(crate) unsafe fn epoll_mod( + epfd: BorrowedFd<'_>, + fd: c::c_int, + event: &epoll::Event, +) -> io::Result<()> { + ret(syscall_readonly!( + __NR_epoll_ctl, + epfd, + c_uint(EPOLL_CTL_MOD), + raw_fd(fd), + by_ref(event) + )) +} + +#[inline] +pub(crate) unsafe fn epoll_del(epfd: BorrowedFd<'_>, fd: c::c_int) -> io::Result<()> { + ret(syscall_readonly!( + __NR_epoll_ctl, + epfd, + c_uint(EPOLL_CTL_DEL), + raw_fd(fd), + zero() + )) +} + +#[inline] +pub(crate) fn epoll_wait( + epfd: BorrowedFd<'_>, + events: *mut epoll::Event, + num_events: usize, + timeout: c::c_int, +) -> io::Result { + #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))] + unsafe { + ret_usize(syscall!( + __NR_epoll_wait, + epfd, + events, + pass_usize(num_events), + c_int(timeout) + )) + } + #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] + unsafe { + ret_usize(syscall!( + __NR_epoll_pwait, + epfd, + events, + pass_usize(num_events), + c_int(timeout), + zero() + )) + } +} + +#[inline] +pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result { + unsafe { ret_owned_fd(syscall_readonly!(__NR_eventfd2, c_uint(initval), flags)) } +} diff --git a/vendor/rustix/src/backend/linux_raw/event/types.rs b/vendor/rustix/src/backend/linux_raw/event/types.rs new file mode 100644 index 000000000..e6273959c --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/event/types.rs @@ -0,0 +1,18 @@ +use crate::backend::c; +use bitflags::bitflags; + +bitflags! { + /// `EFD_*` flags for use with [`eventfd`]. + /// + /// [`eventfd`]: crate::io::eventfd + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct EventfdFlags: c::c_uint { + /// `EFD_CLOEXEC` + const CLOEXEC = linux_raw_sys::general::EFD_CLOEXEC; + /// `EFD_NONBLOCK` + const NONBLOCK = linux_raw_sys::general::EFD_NONBLOCK; + /// `EFD_SEMAPHORE` + const SEMAPHORE = linux_raw_sys::general::EFD_SEMAPHORE; + } +} diff --git a/vendor/rustix/src/backend/linux_raw/fs/dir.rs b/vendor/rustix/src/backend/linux_raw/fs/dir.rs index cfa347d03..4df589af5 100644 --- a/vendor/rustix/src/backend/linux_raw/fs/dir.rs +++ b/vendor/rustix/src/backend/linux_raw/fs/dir.rs @@ -4,6 +4,7 @@ use crate::fs::{ fcntl_getfl, fstat, fstatfs, fstatvfs, openat, FileType, Mode, OFlags, Stat, StatFs, StatVfs, }; use crate::io; +#[cfg(feature = "process")] use crate::process::fchdir; use crate::utils::as_ptr; use alloc::borrow::ToOwned; @@ -100,8 +101,7 @@ impl Dir { .iter() .position(|x| *x == b'\0') .unwrap(); - let name = - CStr::from_bytes_with_nul(&self.buf[name_start..name_start + name_len + 1]).unwrap(); + let name = CStr::from_bytes_with_nul(&self.buf[name_start..][..=name_len]).unwrap(); let name = name.to_owned(); assert!(name.as_bytes().len() <= self.buf.len() - name_start); @@ -175,6 +175,8 @@ impl Dir { } /// `fchdir(self)` + #[cfg(feature = "process")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "process")))] #[inline] pub fn chdir(&self) -> io::Result<()> { fchdir(&self.fd) diff --git a/vendor/rustix/src/backend/linux_raw/fs/inotify.rs b/vendor/rustix/src/backend/linux_raw/fs/inotify.rs index a3c274741..cb9d87b82 100644 --- a/vendor/rustix/src/backend/linux_raw/fs/inotify.rs +++ b/vendor/rustix/src/backend/linux_raw/fs/inotify.rs @@ -1,6 +1,6 @@ //! inotify support for working with inotifies -use super::super::c; +use crate::backend::c; use crate::backend::fs::syscalls; use crate::fd::{BorrowedFd, OwnedFd}; use crate::io; @@ -10,6 +10,8 @@ bitflags! { /// `IN_*` for use with [`inotify_init`]. /// /// [`inotify_init`]: crate::fs::inotify::inotify_init + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct CreateFlags: c::c_uint { /// `IN_CLOEXEC` const CLOEXEC = linux_raw_sys::general::IN_CLOEXEC; @@ -22,7 +24,8 @@ bitflags! { /// `IN*` for use with [`inotify_add_watch`]. /// /// [`inotify_add_watch`]: crate::fs::inotify::inotify_add_watch - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct WatchFlags: c::c_uint { /// `IN_ACCESS` const ACCESS = linux_raw_sys::general::IN_ACCESS; @@ -76,6 +79,7 @@ bitflags! { /// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file /// descriptor from being implicitly passed across `exec` boundaries. #[doc(alias = "inotify_init1")] +#[inline] pub fn inotify_init(flags: CreateFlags) -> io::Result { syscalls::inotify_init1(flags) } @@ -89,6 +93,7 @@ pub fn inotify_init(flags: CreateFlags) -> io::Result { /// different paths to this method may result in it returning /// the same watch descriptor. An application should keep track of this /// externally to avoid logic errors. +#[inline] pub fn inotify_add_watch( inot: BorrowedFd<'_>, path: P, @@ -103,6 +108,7 @@ pub fn inotify_add_watch( /// The watch descriptor provided should have previously been returned /// by [`inotify_add_watch`] and not previously have been removed. #[doc(alias = "inotify_rm_watch")] +#[inline] pub fn inotify_remove_watch(inot: BorrowedFd<'_>, wd: i32) -> io::Result<()> { syscalls::inotify_rm_watch(inot, wd) } diff --git a/vendor/rustix/src/backend/linux_raw/fs/syscalls.rs b/vendor/rustix/src/backend/linux_raw/fs/syscalls.rs index d0d855cc1..78a2088b2 100644 --- a/vendor/rustix/src/backend/linux_raw/fs/syscalls.rs +++ b/vendor/rustix/src/backend/linux_raw/fs/syscalls.rs @@ -4,16 +4,16 @@ //! //! See the `rustix::backend` module documentation for details. #![allow(unsafe_code)] -#![allow(dead_code)] #![allow(clippy::undocumented_unsafe_blocks)] -use super::super::c; -use super::super::conv::{ - by_ref, c_int, c_uint, dev_t, oflags_for_open_how, opt_mut, pass_usize, raw_fd, ret, ret_c_int, - ret_c_uint, ret_infallible, ret_owned_fd, ret_usize, size_of, slice, slice_mut, zero, +use crate::backend::c; +use crate::backend::conv::fs::oflags_for_open_how; +use crate::backend::conv::{ + by_ref, c_int, c_uint, dev_t, opt_mut, pass_usize, raw_fd, ret, ret_c_int, ret_c_uint, + ret_infallible, ret_owned_fd, ret_usize, size_of, slice, slice_mut, zero, }; #[cfg(target_pointer_width = "64")] -use super::super::conv::{loff_t, loff_t_from_u64, ret_u64}; +use crate::backend::conv::{loff_t, loff_t_from_u64, ret_u64}; #[cfg(any( target_arch = "aarch64", target_arch = "riscv64", @@ -23,98 +23,77 @@ use super::super::conv::{loff_t, loff_t_from_u64, ret_u64}; use crate::fd::AsFd; use crate::fd::{BorrowedFd, OwnedFd}; use crate::ffi::CStr; +#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] +use crate::fs::CWD; use crate::fs::{ - inotify, Access, Advice, AtFlags, FallocateFlags, FileType, FlockOperation, MemfdFlags, Mode, - OFlags, RenameFlags, ResolveFlags, SealFlags, Stat, StatFs, StatVfs, StatVfsMountFlags, - StatxFlags, Timestamps, XattrFlags, + inotify, Access, Advice, AtFlags, FallocateFlags, FileType, FlockOperation, Gid, MemfdFlags, + Mode, OFlags, RenameFlags, ResolveFlags, SealFlags, SeekFrom, Stat, StatFs, StatVfs, + StatVfsMountFlags, StatxFlags, Timestamps, Uid, XattrFlags, }; -use crate::io::{self, SeekFrom}; -use crate::process::{Gid, Uid}; -#[cfg(any(target_pointer_width = "32", target_arch = "mips64"))] -use core::convert::TryInto; -use core::mem::MaybeUninit; +use crate::io; +use core::mem::{transmute, zeroed, MaybeUninit}; #[cfg(target_arch = "mips64")] use linux_raw_sys::general::stat as linux_stat64; use linux_raw_sys::general::{ __kernel_fsid_t, __kernel_timespec, open_how, statx, AT_EACCESS, AT_FDCWD, AT_REMOVEDIR, - AT_SYMLINK_NOFOLLOW, F_ADD_SEALS, F_GETFL, F_GETLEASE, F_GETOWN, F_GETPIPE_SZ, F_GETSIG, - F_GET_SEALS, F_SETFL, F_SETPIPE_SZ, SEEK_CUR, SEEK_DATA, SEEK_END, SEEK_HOLE, SEEK_SET, - STATX__RESERVED, + AT_SYMLINK_NOFOLLOW, F_ADD_SEALS, F_GETFL, F_GET_SEALS, F_SETFL, SEEK_CUR, SEEK_DATA, SEEK_END, + SEEK_HOLE, SEEK_SET, STATX__RESERVED, }; +use linux_raw_sys::ioctl::{BLKPBSZGET, BLKSSZGET, EXT4_IOC_RESIZE_FS, FICLONE}; #[cfg(target_pointer_width = "32")] use { - super::super::conv::{hi, lo, slice_just_addr}, + crate::backend::conv::{hi, lo, slice_just_addr}, linux_raw_sys::general::stat64 as linux_stat64, linux_raw_sys::general::timespec as __kernel_old_timespec, }; #[inline] -pub(crate) fn open(filename: &CStr, flags: OFlags, mode: Mode) -> io::Result { +pub(crate) fn open(path: &CStr, flags: OFlags, mode: Mode) -> io::Result { + // Always enable support for large files. + let flags = flags | OFlags::from_bits_retain(c::O_LARGEFILE); + #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] { - openat(crate::fs::cwd().as_fd(), filename, flags, mode) + openat(CWD.as_fd(), path, flags, mode) } - #[cfg(all( - target_pointer_width = "32", - not(any(target_arch = "aarch64", target_arch = "riscv64")), - ))] + #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))] unsafe { - ret_owned_fd(syscall_readonly!(__NR_open, filename, flags, mode)) - } - #[cfg(all( - target_pointer_width = "64", - not(any(target_arch = "aarch64", target_arch = "riscv64")), - ))] - unsafe { - ret_owned_fd(syscall_readonly!(__NR_open, filename, flags, mode)) + ret_owned_fd(syscall_readonly!(__NR_open, path, flags, mode)) } } #[inline] pub(crate) fn openat( dirfd: BorrowedFd<'_>, - filename: &CStr, + path: &CStr, flags: OFlags, mode: Mode, ) -> io::Result { - #[cfg(target_pointer_width = "32")] - unsafe { - ret_owned_fd(syscall_readonly!(__NR_openat, dirfd, filename, flags, mode)) - } - #[cfg(target_pointer_width = "64")] - unsafe { - ret_owned_fd(syscall_readonly!(__NR_openat, dirfd, filename, flags, mode)) - } + // Always enable support for large files. + let flags = flags | OFlags::from_bits_retain(c::O_LARGEFILE); + + unsafe { ret_owned_fd(syscall_readonly!(__NR_openat, dirfd, path, flags, mode)) } } #[inline] pub(crate) fn openat2( dirfd: BorrowedFd<'_>, - pathname: &CStr, - flags: OFlags, + path: &CStr, + mut flags: OFlags, mode: Mode, resolve: ResolveFlags, ) -> io::Result { - #[cfg(target_pointer_width = "32")] - unsafe { - ret_owned_fd(syscall_readonly!( - __NR_openat2, - dirfd, - pathname, - by_ref(&open_how { - flags: oflags_for_open_how(flags), - mode: u64::from(mode.bits()), - resolve: resolve.bits(), - }), - size_of::() - )) + // Enable support for large files, but not with `O_PATH` because + // `openat2` doesn't like those flags together. + if !flags.contains(OFlags::PATH) { + flags |= OFlags::from_bits_retain(c::O_LARGEFILE); } - #[cfg(target_pointer_width = "64")] + unsafe { ret_owned_fd(syscall_readonly!( __NR_openat2, dirfd, - pathname, + path, by_ref(&open_how { flags: oflags_for_open_how(flags), mode: u64::from(mode.bits()), @@ -126,12 +105,12 @@ pub(crate) fn openat2( } #[inline] -pub(crate) fn chmod(filename: &CStr, mode: Mode) -> io::Result<()> { +pub(crate) fn chmod(path: &CStr, mode: Mode) -> io::Result<()> { unsafe { ret(syscall_readonly!( __NR_fchmodat, raw_fd(AT_FDCWD), - filename, + path, mode )) } @@ -140,7 +119,7 @@ pub(crate) fn chmod(filename: &CStr, mode: Mode) -> io::Result<()> { #[inline] pub(crate) fn chmodat( dirfd: BorrowedFd<'_>, - filename: &CStr, + path: &CStr, mode: Mode, flags: AtFlags, ) -> io::Result<()> { @@ -150,7 +129,7 @@ pub(crate) fn chmodat( if !flags.is_empty() { return Err(io::Errno::INVAL); } - unsafe { ret(syscall_readonly!(__NR_fchmodat, dirfd, filename, mode)) } + unsafe { ret(syscall_readonly!(__NR_fchmodat, dirfd, path, mode)) } } #[inline] @@ -161,17 +140,17 @@ pub(crate) fn fchmod(fd: BorrowedFd<'_>, mode: Mode) -> io::Result<()> { #[inline] pub(crate) fn chownat( dirfd: BorrowedFd<'_>, - filename: &CStr, + path: &CStr, owner: Option, group: Option, flags: AtFlags, ) -> io::Result<()> { unsafe { - let (ow, gr) = crate::process::translate_fchown_args(owner, group); + let (ow, gr) = crate::ugid::translate_fchown_args(owner, group); ret(syscall_readonly!( __NR_fchownat, dirfd, - filename, + path, c_uint(ow), c_uint(gr), flags @@ -182,7 +161,7 @@ pub(crate) fn chownat( #[inline] pub(crate) fn fchown(fd: BorrowedFd<'_>, owner: Option, group: Option) -> io::Result<()> { unsafe { - let (ow, gr) = crate::process::translate_fchown_args(owner, group); + let (ow, gr) = crate::ugid::translate_fchown_args(owner, group); ret(syscall_readonly!(__NR_fchown, fd, c_uint(ow), c_uint(gr))) } } @@ -190,7 +169,7 @@ pub(crate) fn fchown(fd: BorrowedFd<'_>, owner: Option, group: Option) #[inline] pub(crate) fn mknodat( dirfd: BorrowedFd<'_>, - filename: &CStr, + path: &CStr, file_type: FileType, mode: Mode, dev: u64, @@ -200,7 +179,7 @@ pub(crate) fn mknodat( ret(syscall_readonly!( __NR_mknodat, dirfd, - filename, + path, (mode, file_type), dev_t(dev)? )) @@ -210,7 +189,7 @@ pub(crate) fn mknodat( ret(syscall_readonly!( __NR_mknodat, dirfd, - filename, + path, (mode, file_type), dev_t(dev) )) @@ -442,9 +421,15 @@ pub(crate) fn sync() { #[inline] pub(crate) fn fstat(fd: BorrowedFd<'_>) -> io::Result { + // 32-bit and mips64 Linux: `struct stat64` is not y2038 compatible; use + // `statx`. + // + // And, some old platforms don't support `statx`, and some fail with a + // confusing error code, so we call `crate::fs::statx` to handle that. If + // `statx` isn't available, fall back to the buggy system call. #[cfg(any(target_pointer_width = "32", target_arch = "mips64"))] { - match statx(fd, cstr!(""), AtFlags::EMPTY_PATH, StatxFlags::BASIC_STATS) { + match crate::fs::statx(fd, cstr!(""), AtFlags::EMPTY_PATH, StatxFlags::BASIC_STATS) { Ok(x) => statx_to_stat(x), Err(io::Errno::NOSYS) => fstat_old(fd), Err(err) => Err(err), @@ -477,17 +462,18 @@ fn fstat_old(fd: BorrowedFd<'_>) -> io::Result { } #[inline] -pub(crate) fn stat(filename: &CStr) -> io::Result { +pub(crate) fn stat(path: &CStr) -> io::Result { + // See the comments in `fstat` about using `crate::fs::statx` here. #[cfg(any(target_pointer_width = "32", target_arch = "mips64"))] { - match statx( - crate::fs::cwd().as_fd(), - filename, + match crate::fs::statx( + crate::fs::CWD.as_fd(), + path, AtFlags::empty(), StatxFlags::BASIC_STATS, ) { Ok(x) => statx_to_stat(x), - Err(io::Errno::NOSYS) => stat_old(filename), + Err(io::Errno::NOSYS) => stat_old(path), Err(err) => Err(err), } } @@ -498,7 +484,7 @@ pub(crate) fn stat(filename: &CStr) -> io::Result { ret(syscall!( __NR_newfstatat, raw_fd(AT_FDCWD), - filename, + path, &mut result, c_uint(0) ))?; @@ -507,7 +493,7 @@ pub(crate) fn stat(filename: &CStr) -> io::Result { } #[cfg(any(target_pointer_width = "32", target_arch = "mips64"))] -fn stat_old(filename: &CStr) -> io::Result { +fn stat_old(path: &CStr) -> io::Result { let mut result = MaybeUninit::::uninit(); #[cfg(target_arch = "mips64")] @@ -515,7 +501,7 @@ fn stat_old(filename: &CStr) -> io::Result { ret(syscall!( __NR_newfstatat, raw_fd(AT_FDCWD), - filename, + path, &mut result, c_uint(0) ))?; @@ -527,7 +513,7 @@ fn stat_old(filename: &CStr) -> io::Result { ret(syscall!( __NR_fstatat64, raw_fd(AT_FDCWD), - filename, + path, &mut result, c_uint(0) ))?; @@ -536,12 +522,13 @@ fn stat_old(filename: &CStr) -> io::Result { } #[inline] -pub(crate) fn statat(dirfd: BorrowedFd<'_>, filename: &CStr, flags: AtFlags) -> io::Result { +pub(crate) fn statat(dirfd: BorrowedFd<'_>, path: &CStr, flags: AtFlags) -> io::Result { + // See the comments in `fstat` about using `crate::fs::statx` here. #[cfg(any(target_pointer_width = "32", target_arch = "mips64"))] { - match statx(dirfd, filename, flags, StatxFlags::BASIC_STATS) { + match crate::fs::statx(dirfd, path, flags, StatxFlags::BASIC_STATS) { Ok(x) => statx_to_stat(x), - Err(io::Errno::NOSYS) => statat_old(dirfd, filename, flags), + Err(io::Errno::NOSYS) => statat_old(dirfd, path, flags), Err(err) => Err(err), } } @@ -549,58 +536,41 @@ pub(crate) fn statat(dirfd: BorrowedFd<'_>, filename: &CStr, flags: AtFlags) -> #[cfg(all(target_pointer_width = "64", not(target_arch = "mips64")))] unsafe { let mut result = MaybeUninit::::uninit(); - ret(syscall!( - __NR_newfstatat, - dirfd, - filename, - &mut result, - flags - ))?; + ret(syscall!(__NR_newfstatat, dirfd, path, &mut result, flags))?; Ok(result.assume_init()) } } #[cfg(any(target_pointer_width = "32", target_arch = "mips64"))] -fn statat_old(dirfd: BorrowedFd<'_>, filename: &CStr, flags: AtFlags) -> io::Result { +fn statat_old(dirfd: BorrowedFd<'_>, path: &CStr, flags: AtFlags) -> io::Result { let mut result = MaybeUninit::::uninit(); #[cfg(target_arch = "mips64")] unsafe { - ret(syscall!( - __NR_newfstatat, - dirfd, - filename, - &mut result, - flags - ))?; + ret(syscall!(__NR_newfstatat, dirfd, path, &mut result, flags))?; stat_to_stat(result.assume_init()) } #[cfg(target_pointer_width = "32")] unsafe { - ret(syscall!( - __NR_fstatat64, - dirfd, - filename, - &mut result, - flags - ))?; + ret(syscall!(__NR_fstatat64, dirfd, path, &mut result, flags))?; stat_to_stat(result.assume_init()) } } #[inline] -pub(crate) fn lstat(filename: &CStr) -> io::Result { +pub(crate) fn lstat(path: &CStr) -> io::Result { + // See the comments in `fstat` about using `crate::fs::statx` here. #[cfg(any(target_pointer_width = "32", target_arch = "mips64"))] { - match statx( - crate::fs::cwd().as_fd(), - filename, + match crate::fs::statx( + crate::fs::CWD.as_fd(), + path, AtFlags::SYMLINK_NOFOLLOW, StatxFlags::BASIC_STATS, ) { Ok(x) => statx_to_stat(x), - Err(io::Errno::NOSYS) => lstat_old(filename), + Err(io::Errno::NOSYS) => lstat_old(path), Err(err) => Err(err), } } @@ -611,7 +581,7 @@ pub(crate) fn lstat(filename: &CStr) -> io::Result { ret(syscall!( __NR_newfstatat, raw_fd(AT_FDCWD), - filename, + path, &mut result, c_uint(AT_SYMLINK_NOFOLLOW) ))?; @@ -620,7 +590,7 @@ pub(crate) fn lstat(filename: &CStr) -> io::Result { } #[cfg(any(target_pointer_width = "32", target_arch = "mips64"))] -fn lstat_old(filename: &CStr) -> io::Result { +fn lstat_old(path: &CStr) -> io::Result { let mut result = MaybeUninit::::uninit(); #[cfg(target_arch = "mips64")] @@ -628,7 +598,7 @@ fn lstat_old(filename: &CStr) -> io::Result { ret(syscall!( __NR_newfstatat, raw_fd(AT_FDCWD), - filename, + path, &mut result, c_uint(AT_SYMLINK_NOFOLLOW) ))?; @@ -640,7 +610,7 @@ fn lstat_old(filename: &CStr) -> io::Result { ret(syscall!( __NR_fstatat64, raw_fd(AT_FDCWD), - filename, + path, &mut result, c_uint(AT_SYMLINK_NOFOLLOW) ))?; @@ -750,7 +720,7 @@ fn stat_to_stat(s: linux_raw_sys::general::stat) -> io::Result { #[inline] pub(crate) fn statx( dirfd: BorrowedFd<'_>, - pathname: &CStr, + path: &CStr, flags: AtFlags, mask: StatxFlags, ) -> io::Result { @@ -777,7 +747,7 @@ pub(crate) fn statx( ret(syscall!( __NR_statx, dirfd, - pathname, + path, flags, mask, &mut statx_buf @@ -837,13 +807,13 @@ pub(crate) fn fstatvfs(fd: BorrowedFd<'_>) -> io::Result { } #[inline] -pub(crate) fn statfs(filename: &CStr) -> io::Result { +pub(crate) fn statfs(path: &CStr) -> io::Result { #[cfg(target_pointer_width = "32")] unsafe { let mut result = MaybeUninit::::uninit(); ret(syscall!( __NR_statfs64, - filename, + path, size_of::(), &mut result ))?; @@ -852,16 +822,16 @@ pub(crate) fn statfs(filename: &CStr) -> io::Result { #[cfg(target_pointer_width = "64")] unsafe { let mut result = MaybeUninit::::uninit(); - ret(syscall!(__NR_statfs, filename, &mut result))?; + ret(syscall!(__NR_statfs, path, &mut result))?; Ok(result.assume_init()) } } #[inline] -pub(crate) fn statvfs(filename: &CStr) -> io::Result { +pub(crate) fn statvfs(path: &CStr) -> io::Result { // Linux doesn't have a `statvfs` syscall; we have to do `statfs` and // translate the fields as best we can. - let statfs = statfs(filename)?; + let statfs = statfs(path)?; Ok(statfs_to_statvfs(statfs)) } @@ -883,8 +853,8 @@ fn statfs_to_statvfs(statfs: StatFs) -> StatVfs { f_files: statfs.f_files as u64, f_ffree: statfs.f_ffree as u64, f_favail: statfs.f_ffree as u64, - f_fsid: f_fsid_val0 as u32 as u64 | ((f_fsid_val1 as u32 as u64) << 32), - f_flag: unsafe { StatVfsMountFlags::from_bits_unchecked(statfs.f_flags as u64) }, + f_fsid: u64::from(f_fsid_val0 as u32) | u64::from(f_fsid_val1 as u32) << 32, + f_flag: StatVfsMountFlags::from_bits_retain(statfs.f_flags as u64), f_namemax: statfs.f_namelen as u64, } } @@ -904,7 +874,11 @@ pub(crate) fn readlink(path: &CStr, buf: &mut [u8]) -> io::Result { } #[inline] -pub(crate) fn readlinkat(dirfd: BorrowedFd<'_>, path: &CStr, buf: &mut [u8]) -> io::Result { +pub(crate) fn readlinkat( + dirfd: BorrowedFd<'_>, + path: &CStr, + buf: &mut [MaybeUninit], +) -> io::Result { let (buf_addr_mut, buf_len) = slice_mut(buf); unsafe { ret_usize(syscall!( @@ -922,17 +896,19 @@ pub(crate) fn fcntl_getfl(fd: BorrowedFd<'_>) -> io::Result { #[cfg(target_pointer_width = "32")] unsafe { ret_c_uint(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETFL))) - .map(OFlags::from_bits_truncate) + .map(OFlags::from_bits_retain) } #[cfg(target_pointer_width = "64")] unsafe { - ret_c_uint(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETFL))) - .map(OFlags::from_bits_truncate) + ret_c_uint(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETFL))).map(OFlags::from_bits_retain) } } #[inline] pub(crate) fn fcntl_setfl(fd: BorrowedFd<'_>, flags: OFlags) -> io::Result<()> { + // Always enable support for large files. + let flags = flags | OFlags::from_bits_retain(c::O_LARGEFILE); + #[cfg(target_pointer_width = "32")] unsafe { ret(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_SETFL), flags)) @@ -943,87 +919,17 @@ pub(crate) fn fcntl_setfl(fd: BorrowedFd<'_>, flags: OFlags) -> io::Result<()> { } } -#[inline] -pub(crate) fn fcntl_getlease(fd: BorrowedFd<'_>) -> io::Result { - #[cfg(target_pointer_width = "32")] - unsafe { - ret_c_int(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETLEASE))) - } - #[cfg(target_pointer_width = "64")] - unsafe { - ret_c_int(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETLEASE))) - } -} - -#[inline] -pub(crate) fn fcntl_getown(fd: BorrowedFd<'_>) -> io::Result { - #[cfg(target_pointer_width = "32")] - unsafe { - ret_c_int(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETOWN))) - } - #[cfg(target_pointer_width = "64")] - unsafe { - ret_c_int(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETOWN))) - } -} - -#[inline] -pub(crate) fn fcntl_getsig(fd: BorrowedFd<'_>) -> io::Result { - #[cfg(target_pointer_width = "32")] - unsafe { - ret_c_int(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETSIG))) - } - #[cfg(target_pointer_width = "64")] - unsafe { - ret_c_int(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETSIG))) - } -} - -#[inline] -pub(crate) fn fcntl_getpipe_sz(fd: BorrowedFd<'_>) -> io::Result { - #[cfg(target_pointer_width = "32")] - unsafe { - ret_usize(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETPIPE_SZ))) - } - #[cfg(target_pointer_width = "64")] - unsafe { - ret_usize(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETPIPE_SZ))) - } -} - -#[inline] -pub(crate) fn fcntl_setpipe_sz(fd: BorrowedFd<'_>, size: c::c_int) -> io::Result { - #[cfg(target_pointer_width = "32")] - unsafe { - ret_usize(syscall_readonly!( - __NR_fcntl64, - fd, - c_uint(F_SETPIPE_SZ), - c_int(size) - )) - } - #[cfg(target_pointer_width = "64")] - unsafe { - ret_usize(syscall_readonly!( - __NR_fcntl, - fd, - c_uint(F_SETPIPE_SZ), - c_int(size) - )) - } -} - #[inline] pub(crate) fn fcntl_get_seals(fd: BorrowedFd<'_>) -> io::Result { #[cfg(target_pointer_width = "32")] unsafe { ret_c_int(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GET_SEALS))) - .map(|seals| SealFlags::from_bits_unchecked(seals as u32)) + .map(|seals| SealFlags::from_bits_retain(seals as u32)) } #[cfg(target_pointer_width = "64")] unsafe { ret_c_int(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GET_SEALS))) - .map(|seals| SealFlags::from_bits_unchecked(seals as u32)) + .map(|seals| SealFlags::from_bits_retain(seals as u32)) } } @@ -1077,7 +983,7 @@ pub(crate) fn fcntl_lock(fd: BorrowedFd<'_>, operation: FlockOperation) -> io::R l_start: 0, l_len: 0, - ..core::mem::zeroed() + ..zeroed() }; #[cfg(target_pointer_width = "32")] @@ -1102,15 +1008,15 @@ pub(crate) fn fcntl_lock(fd: BorrowedFd<'_>, operation: FlockOperation) -> io::R } #[inline] -pub(crate) fn rename(oldname: &CStr, newname: &CStr) -> io::Result<()> { +pub(crate) fn rename(old_path: &CStr, new_path: &CStr) -> io::Result<()> { #[cfg(target_arch = "riscv64")] unsafe { ret(syscall_readonly!( __NR_renameat2, raw_fd(AT_FDCWD), - oldname, + old_path, raw_fd(AT_FDCWD), - newname, + new_path, c_uint(0) )) } @@ -1119,9 +1025,9 @@ pub(crate) fn rename(oldname: &CStr, newname: &CStr) -> io::Result<()> { ret(syscall_readonly!( __NR_renameat, raw_fd(AT_FDCWD), - oldname, + old_path, raw_fd(AT_FDCWD), - newname + new_path )) } } @@ -1129,18 +1035,18 @@ pub(crate) fn rename(oldname: &CStr, newname: &CStr) -> io::Result<()> { #[inline] pub(crate) fn renameat( old_dirfd: BorrowedFd<'_>, - oldname: &CStr, + old_path: &CStr, new_dirfd: BorrowedFd<'_>, - newname: &CStr, + new_path: &CStr, ) -> io::Result<()> { #[cfg(target_arch = "riscv64")] unsafe { ret(syscall_readonly!( __NR_renameat2, old_dirfd, - oldname, + old_path, new_dirfd, - newname, + new_path, c_uint(0) )) } @@ -1149,9 +1055,9 @@ pub(crate) fn renameat( ret(syscall_readonly!( __NR_renameat, old_dirfd, - oldname, + old_path, new_dirfd, - newname + new_path )) } } @@ -1159,61 +1065,61 @@ pub(crate) fn renameat( #[inline] pub(crate) fn renameat2( old_dirfd: BorrowedFd<'_>, - oldname: &CStr, + old_path: &CStr, new_dirfd: BorrowedFd<'_>, - newname: &CStr, + new_path: &CStr, flags: RenameFlags, ) -> io::Result<()> { unsafe { ret(syscall_readonly!( __NR_renameat2, old_dirfd, - oldname, + old_path, new_dirfd, - newname, + new_path, flags )) } } #[inline] -pub(crate) fn unlink(pathname: &CStr) -> io::Result<()> { +pub(crate) fn unlink(path: &CStr) -> io::Result<()> { unsafe { ret(syscall_readonly!( __NR_unlinkat, raw_fd(AT_FDCWD), - pathname, + path, c_uint(0) )) } } #[inline] -pub(crate) fn unlinkat(dirfd: BorrowedFd<'_>, pathname: &CStr, flags: AtFlags) -> io::Result<()> { - unsafe { ret(syscall_readonly!(__NR_unlinkat, dirfd, pathname, flags)) } +pub(crate) fn unlinkat(dirfd: BorrowedFd<'_>, path: &CStr, flags: AtFlags) -> io::Result<()> { + unsafe { ret(syscall_readonly!(__NR_unlinkat, dirfd, path, flags)) } } #[inline] -pub(crate) fn rmdir(pathname: &CStr) -> io::Result<()> { +pub(crate) fn rmdir(path: &CStr) -> io::Result<()> { unsafe { ret(syscall_readonly!( __NR_unlinkat, raw_fd(AT_FDCWD), - pathname, + path, c_uint(AT_REMOVEDIR) )) } } #[inline] -pub(crate) fn link(oldname: &CStr, newname: &CStr) -> io::Result<()> { +pub(crate) fn link(old_path: &CStr, new_path: &CStr) -> io::Result<()> { unsafe { ret(syscall_readonly!( __NR_linkat, raw_fd(AT_FDCWD), - oldname, + old_path, raw_fd(AT_FDCWD), - newname, + new_path, c_uint(0) )) } @@ -1222,55 +1128,55 @@ pub(crate) fn link(oldname: &CStr, newname: &CStr) -> io::Result<()> { #[inline] pub(crate) fn linkat( old_dirfd: BorrowedFd<'_>, - oldname: &CStr, + old_path: &CStr, new_dirfd: BorrowedFd<'_>, - newname: &CStr, + new_path: &CStr, flags: AtFlags, ) -> io::Result<()> { unsafe { ret(syscall_readonly!( __NR_linkat, old_dirfd, - oldname, + old_path, new_dirfd, - newname, + new_path, flags )) } } #[inline] -pub(crate) fn symlink(oldname: &CStr, newname: &CStr) -> io::Result<()> { +pub(crate) fn symlink(old_path: &CStr, new_path: &CStr) -> io::Result<()> { unsafe { ret(syscall_readonly!( __NR_symlinkat, - oldname, + old_path, raw_fd(AT_FDCWD), - newname + new_path )) } } #[inline] -pub(crate) fn symlinkat(oldname: &CStr, dirfd: BorrowedFd<'_>, newname: &CStr) -> io::Result<()> { - unsafe { ret(syscall_readonly!(__NR_symlinkat, oldname, dirfd, newname)) } +pub(crate) fn symlinkat(old_path: &CStr, dirfd: BorrowedFd<'_>, new_path: &CStr) -> io::Result<()> { + unsafe { ret(syscall_readonly!(__NR_symlinkat, old_path, dirfd, new_path)) } } #[inline] -pub(crate) fn mkdir(pathname: &CStr, mode: Mode) -> io::Result<()> { +pub(crate) fn mkdir(path: &CStr, mode: Mode) -> io::Result<()> { unsafe { ret(syscall_readonly!( __NR_mkdirat, raw_fd(AT_FDCWD), - pathname, + path, mode )) } } #[inline] -pub(crate) fn mkdirat(dirfd: BorrowedFd<'_>, pathname: &CStr, mode: Mode) -> io::Result<()> { - unsafe { ret(syscall_readonly!(__NR_mkdirat, dirfd, pathname, mode)) } +pub(crate) fn mkdirat(dirfd: BorrowedFd<'_>, path: &CStr, mode: Mode) -> io::Result<()> { + unsafe { ret(syscall_readonly!(__NR_mkdirat, dirfd, path, mode)) } } #[inline] @@ -1293,33 +1199,35 @@ pub(crate) fn getdents_uninit( #[inline] pub(crate) fn utimensat( dirfd: BorrowedFd<'_>, - pathname: &CStr, + path: &CStr, times: &Timestamps, flags: AtFlags, ) -> io::Result<()> { - _utimensat(dirfd, Some(pathname), times, flags) + _utimensat(dirfd, Some(path), times, flags) } #[inline] fn _utimensat( dirfd: BorrowedFd<'_>, - pathname: Option<&CStr>, + path: Option<&CStr>, times: &Timestamps, flags: AtFlags, ) -> io::Result<()> { // Assert that `Timestamps` has the expected layout. - let _ = unsafe { core::mem::transmute::(times.clone()) }; + let _ = unsafe { transmute::(times.clone()) }; + // `utimensat_time64` was introduced in Linux 5.1. The old `utimensat` + // syscall is not y2038-compatible on 32-bit architectures. #[cfg(target_pointer_width = "32")] unsafe { match ret(syscall_readonly!( __NR_utimensat_time64, dirfd, - pathname, + path, by_ref(times), flags )) { - Err(io::Errno::NOSYS) => _utimensat_old(dirfd, pathname, times, flags), + Err(io::Errno::NOSYS) => _utimensat_old(dirfd, path, times, flags), otherwise => otherwise, } } @@ -1328,7 +1236,7 @@ fn _utimensat( ret(syscall_readonly!( __NR_utimensat, dirfd, - pathname, + path, by_ref(times), flags )) @@ -1338,7 +1246,7 @@ fn _utimensat( #[cfg(target_pointer_width = "32")] unsafe fn _utimensat_old( dirfd: BorrowedFd<'_>, - pathname: Option<&CStr>, + path: Option<&CStr>, times: &Timestamps, flags: AtFlags, ) -> io::Result<()> { @@ -1375,7 +1283,7 @@ unsafe fn _utimensat_old( ret(syscall_readonly!( __NR_utimensat, dirfd, - pathname, + path, old_times_addr, flags )) @@ -1386,6 +1294,19 @@ pub(crate) fn futimens(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()> _utimensat(fd, None, times, AtFlags::empty()) } +#[inline] +pub(crate) fn access(path: &CStr, access: Access) -> io::Result<()> { + #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] + { + accessat_noflags(CWD.as_fd(), path, access) + } + + #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))] + unsafe { + ret(syscall_readonly!(__NR_access, path, access)) + } +} + pub(crate) fn accessat( dirfd: BorrowedFd<'_>, path: &CStr, @@ -1400,35 +1321,46 @@ pub(crate) fn accessat( } // Linux's `faccessat` syscall doesn't have a flags argument, so if we have - // any flags, use the newer `faccessat2` which does. Unless we're on - // Android where using newer system calls can cause seccomp to abort the - // process. + // any flags, use the newer `faccessat2` introduced in Linux 5.8 which + // does. Unless we're on Android where using newer system calls can cause + // seccomp to abort the process. #[cfg(not(target_os = "android"))] if !flags.is_empty() { - return unsafe { - ret(syscall_readonly!( + unsafe { + match ret(syscall_readonly!( __NR_faccessat2, dirfd, path, access, flags - )) - }; + )) { + Ok(()) => return Ok(()), + Err(io::Errno::NOSYS) => {} + Err(other) => return Err(other), + } + } } // Linux's `faccessat` doesn't have a flags parameter. If we have // `AT_EACCESS` and we're not setuid or setgid, we can emulate it. if flags.is_empty() || (flags.bits() == AT_EACCESS - && crate::process::getuid() == crate::process::geteuid() - && crate::process::getgid() == crate::process::getegid()) + && crate::backend::ugid::syscalls::getuid() + == crate::backend::ugid::syscalls::geteuid() + && crate::backend::ugid::syscalls::getgid() + == crate::backend::ugid::syscalls::getegid()) { - return unsafe { ret(syscall_readonly!(__NR_faccessat, dirfd, path, access)) }; + return accessat_noflags(dirfd, path, access); } Err(io::Errno::NOSYS) } +#[inline] +fn accessat_noflags(dirfd: BorrowedFd<'_>, path: &CStr, access: Access) -> io::Result<()> { + unsafe { ret(syscall_readonly!(__NR_faccessat, dirfd, path, access)) } +} + #[inline] pub(crate) fn copy_file_range( fd_in: BorrowedFd<'_>, @@ -1485,7 +1417,6 @@ pub(crate) fn sendfile( } #[inline] -#[cfg(any(target_os = "android", target_os = "linux"))] pub(crate) fn mount( source: Option<&CStr>, target: &CStr, @@ -1506,7 +1437,6 @@ pub(crate) fn mount( } #[inline] -#[cfg(any(target_os = "android", target_os = "linux"))] pub(crate) fn unmount(target: &CStr, flags: super::types::UnmountFlags) -> io::Result<()> { unsafe { ret(syscall_readonly!(__NR_umount2, target, flags)) } } @@ -1652,15 +1582,50 @@ pub(crate) fn flistxattr(fd: BorrowedFd<'_>, list: &mut [c::c_char]) -> io::Resu #[inline] pub(crate) fn removexattr(path: &CStr, name: &CStr) -> io::Result<()> { - unsafe { ret(syscall!(__NR_removexattr, path, name)) } + unsafe { ret(syscall_readonly!(__NR_removexattr, path, name)) } } #[inline] pub(crate) fn lremovexattr(path: &CStr, name: &CStr) -> io::Result<()> { - unsafe { ret(syscall!(__NR_lremovexattr, path, name)) } + unsafe { ret(syscall_readonly!(__NR_lremovexattr, path, name)) } } #[inline] pub(crate) fn fremovexattr(fd: BorrowedFd<'_>, name: &CStr) -> io::Result<()> { - unsafe { ret(syscall!(__NR_fremovexattr, fd, name)) } + unsafe { ret(syscall_readonly!(__NR_fremovexattr, fd, name)) } +} + +#[inline] +pub(crate) fn ioctl_blksszget(fd: BorrowedFd) -> io::Result { + let mut result = MaybeUninit::::uninit(); + unsafe { + ret(syscall!(__NR_ioctl, fd, c_uint(BLKSSZGET), &mut result))?; + Ok(result.assume_init() as u32) + } +} + +#[inline] +pub(crate) fn ioctl_blkpbszget(fd: BorrowedFd) -> io::Result { + let mut result = MaybeUninit::::uninit(); + unsafe { + ret(syscall!(__NR_ioctl, fd, c_uint(BLKPBSZGET), &mut result))?; + Ok(result.assume_init() as u32) + } +} + +#[inline] +pub(crate) fn ioctl_ficlone(fd: BorrowedFd<'_>, src_fd: BorrowedFd<'_>) -> io::Result<()> { + unsafe { ret(syscall_readonly!(__NR_ioctl, fd, c_uint(FICLONE), src_fd)) } +} + +#[inline] +pub(crate) fn ext4_ioc_resize_fs(fd: BorrowedFd<'_>, blocks: u64) -> io::Result<()> { + unsafe { + ret(syscall_readonly!( + __NR_ioctl, + fd, + c_uint(EXT4_IOC_RESIZE_FS), + by_ref(&blocks) + )) + } } diff --git a/vendor/rustix/src/backend/linux_raw/fs/types.rs b/vendor/rustix/src/backend/linux_raw/fs/types.rs index 68bb9ed46..df61cf721 100644 --- a/vendor/rustix/src/backend/linux_raw/fs/types.rs +++ b/vendor/rustix/src/backend/linux_raw/fs/types.rs @@ -1,10 +1,12 @@ -use super::super::c; +use crate::backend::c; use bitflags::bitflags; bitflags! { /// `*_OK` constants for use with [`accessat`]. /// /// [`accessat`]: fn.accessat.html + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct Access: c::c_uint { /// `R_OK` const READ_OK = linux_raw_sys::general::R_OK; @@ -26,22 +28,27 @@ bitflags! { /// /// [`openat`]: crate::fs::openat /// [`statat`]: crate::fs::statat + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct AtFlags: c::c_uint { + /// `AT_SYMLINK_NOFOLLOW` + const SYMLINK_NOFOLLOW = linux_raw_sys::general::AT_SYMLINK_NOFOLLOW; + + /// `AT_EACCESS` + const EACCESS = linux_raw_sys::general::AT_EACCESS; + /// `AT_REMOVEDIR` const REMOVEDIR = linux_raw_sys::general::AT_REMOVEDIR; /// `AT_SYMLINK_FOLLOW` const SYMLINK_FOLLOW = linux_raw_sys::general::AT_SYMLINK_FOLLOW; - /// `AT_SYMLINK_NOFOLLOW` - const SYMLINK_NOFOLLOW = linux_raw_sys::general::AT_SYMLINK_NOFOLLOW; + /// `AT_NO_AUTOMOUNT` + const NO_AUTOMOUNT = linux_raw_sys::general::AT_NO_AUTOMOUNT; /// `AT_EMPTY_PATH` const EMPTY_PATH = linux_raw_sys::general::AT_EMPTY_PATH; - /// `AT_EACCESS` - const EACCESS = linux_raw_sys::general::AT_EACCESS; - /// `AT_STATX_SYNC_AS_STAT` const STATX_SYNC_AS_STAT = linux_raw_sys::general::AT_STATX_SYNC_AS_STAT; @@ -59,6 +66,8 @@ bitflags! { /// [`openat`]: crate::fs::openat /// [`chmodat`]: crate::fs::chmodat /// [`fchmod`]: crate::fs::fchmod + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct Mode: RawMode { /// `S_IRWXU` const RWXU = linux_raw_sys::general::S_IRWXU; @@ -136,7 +145,7 @@ impl From for Mode { } impl From for RawMode { - /// Support conversions from `Mode to raw mode values. + /// Support conversions from `Mode` to raw mode values. /// /// ``` /// use rustix::fs::{Mode, RawMode}; @@ -152,6 +161,8 @@ bitflags! { /// `O_*` constants for use with [`openat`]. /// /// [`openat`]: crate::fs::openat + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct OFlags: c::c_uint { /// `O_ACCMODE` const ACCMODE = linux_raw_sys::general::O_ACCMODE; @@ -234,7 +245,8 @@ bitflags! { /// `RESOLVE_*` constants for use with [`openat2`]. /// /// [`openat2`]: crate::fs::openat2 - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct ResolveFlags: u64 { /// `RESOLVE_NO_XDEV` const NO_XDEV = linux_raw_sys::general::RESOLVE_NO_XDEV as u64; @@ -260,6 +272,8 @@ bitflags! { /// `RENAME_*` constants for use with [`renameat_with`]. /// /// [`renameat_with`]: crate::fs::renameat_with + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct RenameFlags: c::c_uint { /// `RENAME_EXCHANGE` const EXCHANGE = linux_raw_sys::general::RENAME_EXCHANGE; @@ -382,6 +396,8 @@ bitflags! { /// `MFD_*` constants for use with [`memfd_create`]. /// /// [`memfd_create`]: crate::fs::memfd_create + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct MemfdFlags: c::c_uint { /// `MFD_CLOEXEC` const CLOEXEC = linux_raw_sys::general::MFD_CLOEXEC; @@ -425,6 +441,8 @@ bitflags! { /// /// [`fcntl_add_seals`]: crate::fs::fcntl_add_seals /// [`fcntl_get_seals`]: crate::fs::fcntl_get_seals + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct SealFlags: u32 { /// `F_SEAL_SEAL`. const SEAL = linux_raw_sys::general::F_SEAL_SEAL; @@ -443,6 +461,8 @@ bitflags! { /// `STATX_*` constants for use with [`statx`]. /// /// [`statx`]: crate::fs::statx + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct StatxFlags: u32 { /// `STATX_TYPE` const TYPE = linux_raw_sys::general::STATX_TYPE; @@ -486,6 +506,9 @@ bitflags! { /// `STATX_MNT_ID` (since Linux 5.8) const MNT_ID = linux_raw_sys::general::STATX_MNT_ID; + /// `STATX_DIOALIGN` (since Linux 6.1) + const DIOALIGN = linux_raw_sys::general::STATX_DIOALIGN; + /// `STATX_ALL` const ALL = linux_raw_sys::general::STATX_ALL; } @@ -495,6 +518,8 @@ bitflags! { /// `FALLOC_FL_*` constants for use with [`fallocate`]. /// /// [`fallocate`]: crate::fs::fallocate + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct FallocateFlags: u32 { /// `FALLOC_FL_KEEP_SIZE` const KEEP_SIZE = linux_raw_sys::general::FALLOC_FL_KEEP_SIZE; @@ -515,6 +540,8 @@ bitflags! { bitflags! { /// `ST_*` constants for use with [`StatVfs`]. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct StatVfsMountFlags: u64 { /// `ST_MANDLOCK` const MANDLOCK = linux_raw_sys::general::MS_MANDLOCK as u64; @@ -668,11 +695,12 @@ pub type FsWord = linux_raw_sys::general::__fsword_t; #[cfg(target_arch = "mips64")] pub type FsWord = i64; -#[cfg(any(target_os = "android", target_os = "linux"))] bitflags! { /// `MS_*` constants for use with [`mount`]. /// /// [`mount`]: crate::fs::mount + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct MountFlags: c::c_uint { /// `MS_BIND` const BIND = linux_raw_sys::general::MS_BIND; @@ -725,11 +753,12 @@ bitflags! { } } -#[cfg(any(target_os = "android", target_os = "linux"))] bitflags! { /// `MS_*` constants for use with [`change_mount`]. /// /// [`change_mount`]: crate::fs::mount::change_mount + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct MountPropagationFlags: c::c_uint { /// `MS_SHARED` const SHARED = linux_raw_sys::general::MS_SHARED; @@ -744,22 +773,24 @@ bitflags! { } } -#[cfg(any(target_os = "android", target_os = "linux"))] bitflags! { + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub(crate) struct InternalMountFlags: c::c_uint { const REMOUNT = linux_raw_sys::general::MS_REMOUNT; const MOVE = linux_raw_sys::general::MS_MOVE; } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[repr(transparent)] pub(crate) struct MountFlagsArg(pub(crate) c::c_uint); -#[cfg(any(target_os = "android", target_os = "linux"))] bitflags! { /// `MNT_*` constants for use with [`unmount`]. /// /// [`unmount`]: crate::fs::mount::unmount + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct UnmountFlags: c::c_uint { /// `MNT_FORCE` const FORCE = linux_raw_sys::general::MNT_FORCE; diff --git a/vendor/rustix/src/backend/linux_raw/io/epoll.rs b/vendor/rustix/src/backend/linux_raw/io/epoll.rs deleted file mode 100644 index 3fc6462a2..000000000 --- a/vendor/rustix/src/backend/linux_raw/io/epoll.rs +++ /dev/null @@ -1,346 +0,0 @@ -//! epoll support. -//! -//! This is an experiment, and it isn't yet clear whether epoll is the right -//! level of abstraction at which to introduce safety. But it works fairly well -//! in simple examples 🙂. -//! -//! # Examples -//! -//! ```no_run -//! # #![cfg_attr(io_lifetimes_use_std, feature(io_safety))] -//! # #[cfg(feature = "net")] -//! # fn main() -> std::io::Result<()> { -//! use io_lifetimes::AsFd; -//! use rustix::io::{epoll, ioctl_fionbio, read, write}; -//! use rustix::net::{ -//! accept, bind_v4, listen, socket, AddressFamily, Ipv4Addr, Protocol, SocketAddrV4, -//! SocketType, -//! }; -//! use std::collections::HashMap; -//! use std::os::unix::io::AsRawFd; -//! -//! // Create a socket and listen on it. -//! let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?; -//! bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0))?; -//! listen(&listen_sock, 1)?; -//! -//! // Create an epoll object. Using `Owning` here means the epoll object will -//! // take ownership of the file descriptors registered with it. -//! let epoll = epoll::epoll_create(epoll::CreateFlags::CLOEXEC)?; -//! -//! // Register the socket with the epoll object. -//! epoll::epoll_add(&epoll, &listen_sock, 1, epoll::EventFlags::IN)?; -//! -//! // Keep track of the sockets we've opened. -//! let mut next_id = 2; -//! let mut sockets = HashMap::new(); -//! -//! // Process events. -//! let mut event_list = epoll::EventVec::with_capacity(4); -//! loop { -//! epoll::epoll_wait(&epoll, &mut event_list, -1)?; -//! for (_event_flags, target) in &event_list { -//! if target == 1 { -//! // Accept a new connection, set it to non-blocking, and -//! // register to be notified when it's ready to write to. -//! let conn_sock = accept(&listen_sock)?; -//! ioctl_fionbio(&conn_sock, true)?; -//! epoll::epoll_add( -//! &epoll, -//! &conn_sock, -//! next_id, -//! epoll::EventFlags::OUT | epoll::EventFlags::ET, -//! )?; -//! -//! // Keep track of the socket. -//! sockets.insert(next_id, conn_sock); -//! next_id += 1; -//! } else { -//! // Write a message to the stream and then unregister it. -//! let target = sockets.remove(&target).unwrap(); -//! write(&target, b"hello\n")?; -//! let _ = epoll::epoll_del(&epoll, &target)?; -//! } -//! } -//! } -//! # } -//! # #[cfg(not(feature = "net"))] -//! # fn main() {} -//! ``` - -#![allow(unsafe_code)] - -use super::super::c; -use crate::backend::io::syscalls; -use crate::fd::{AsFd, AsRawFd, OwnedFd}; -use crate::io; -use alloc::vec::Vec; -use bitflags::bitflags; - -bitflags! { - /// `EPOLL_*` for use with [`Epoll::new`]. - pub struct CreateFlags: c::c_uint { - /// `EPOLL_CLOEXEC` - const CLOEXEC = linux_raw_sys::general::EPOLL_CLOEXEC; - } -} - -bitflags! { - /// `EPOLL*` for use with [`Epoll::add`]. - #[derive(Default)] - pub struct EventFlags: u32 { - /// `EPOLLIN` - const IN = linux_raw_sys::general::EPOLLIN as u32; - - /// `EPOLLOUT` - const OUT = linux_raw_sys::general::EPOLLOUT as u32; - - /// `EPOLLPRI` - const PRI = linux_raw_sys::general::EPOLLPRI as u32; - - /// `EPOLLERR` - const ERR = linux_raw_sys::general::EPOLLERR as u32; - - /// `EPOLLHUP` - const HUP = linux_raw_sys::general::EPOLLHUP as u32; - - /// `EPOLLRDNORM` - const RDNORM = linux_raw_sys::general::EPOLLRDNORM as u32; - - /// `EPOLLRDBAND` - const RDBAND = linux_raw_sys::general::EPOLLRDBAND as u32; - - /// `EPOLLWRNORM` - const WRNORM = linux_raw_sys::general::EPOLLWRNORM as u32; - - /// `EPOLLWRBAND` - const WRBAND = linux_raw_sys::general::EPOLLWRBAND as u32; - - /// `EPOLLMSG` - const MSG = linux_raw_sys::general::EPOLLMSG as u32; - - /// `EPOLLRDHUP` - const RDHUP = linux_raw_sys::general::EPOLLRDHUP as u32; - - /// `EPOLLET` - const ET = linux_raw_sys::general::EPOLLET as u32; - - /// `EPOLLONESHOT` - const ONESHOT = linux_raw_sys::general::EPOLLONESHOT as u32; - - /// `EPOLLWAKEUP` - const WAKEUP = linux_raw_sys::general::EPOLLWAKEUP as u32; - - /// `EPOLLEXCLUSIVE` - const EXCLUSIVE = linux_raw_sys::general::EPOLLEXCLUSIVE as u32; - } -} - -/// `epoll_create1(flags)`—Creates a new `Epoll`. -/// -/// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file -/// descriptor from being implicitly passed across `exec` boundaries. -#[inline] -#[doc(alias = "epoll_create1")] -pub fn epoll_create(flags: CreateFlags) -> io::Result { - syscalls::epoll_create(flags) -} - -/// `epoll_ctl(self, EPOLL_CTL_ADD, data, event)`—Adds an element to an -/// `Epoll`. -/// -/// This registers interest in any of the events set in `events` occurring -/// on the file descriptor associated with `data`. -/// -/// Note that if `epoll_del` is not called on the I/O source passed into -/// this function before the I/O source is `close`d, then the `epoll` will -/// act as if the I/O source is still registered with it. This can lead to -/// spurious events being returned from `epoll_wait`. If a file descriptor -/// is an `Arc`, then `epoll` can be thought to maintain -/// a `Weak` to the file descriptor. -#[doc(alias = "epoll_ctl")] -pub fn epoll_add( - epoll: impl AsFd, - source: impl AsFd, - data: u64, - event_flags: EventFlags, -) -> io::Result<()> { - // SAFETY: We're calling `epoll_ctl` via FFI and we know how it - // behaves. - unsafe { - syscalls::epoll_add( - epoll.as_fd(), - source.as_fd().as_raw_fd(), - &linux_raw_sys::general::epoll_event { - events: event_flags.bits(), - data, - }, - ) - } -} - -/// `epoll_ctl(self, EPOLL_CTL_MOD, target, event)`—Modifies an element in -/// this `Epoll`. -/// -/// This sets the events of interest with `target` to `events`. -#[doc(alias = "epoll_ctl")] -pub fn epoll_mod( - epoll: impl AsFd, - source: impl AsFd, - data: u64, - event_flags: EventFlags, -) -> io::Result<()> { - // SAFETY: We're calling `epoll_ctl` via FFI and we know how it - // behaves. - unsafe { - let raw_fd = source.as_fd().as_raw_fd(); - syscalls::epoll_mod( - epoll.as_fd(), - raw_fd, - &linux_raw_sys::general::epoll_event { - events: event_flags.bits(), - data, - }, - ) - } -} - -/// `epoll_ctl(self, EPOLL_CTL_DEL, target, NULL)`—Removes an element in -/// this `Epoll`. -/// -/// This also returns the owning `Data`. -#[doc(alias = "epoll_ctl")] -pub fn epoll_del(epoll: impl AsFd, source: impl AsFd) -> io::Result<()> { - // SAFETY: We're calling `epoll_ctl` via FFI and we know how it - // behaves. - unsafe { - let raw_fd = source.as_fd().as_raw_fd(); - syscalls::epoll_del(epoll.as_fd(), raw_fd) - } -} - -/// `epoll_wait(self, events, timeout)`—Waits for registered events of -/// interest. -/// -/// For each event of interest, an element is written to `events`. On -/// success, this returns the number of written elements. -pub fn epoll_wait( - epoll: impl AsFd, - event_list: &mut EventVec, - timeout: c::c_int, -) -> io::Result<()> { - // SAFETY: We're calling `epoll_wait` via FFI and we know how it - // behaves. - unsafe { - event_list.events.set_len(0); - let nfds = syscalls::epoll_wait( - epoll.as_fd(), - event_list.events[..].as_mut_ptr().cast(), - event_list.events.capacity(), - timeout, - )?; - event_list.events.set_len(nfds); - } - - Ok(()) -} - -/// An iterator over the `Event`s in an `EventVec`. -pub struct Iter<'a> { - iter: core::slice::Iter<'a, Event>, -} - -impl<'a> Iterator for Iter<'a> { - type Item = (EventFlags, u64); - - fn next(&mut self) -> Option { - self.iter - .next() - .map(|event| (event.event_flags, event.data)) - } -} - -/// A record of an event that occurred. -#[repr(C)] -#[cfg_attr(target_arch = "x86_64", repr(packed))] -struct Event { - // Match the layout of `linux_raw_sys::general::epoll_event`. We just use a - // `u64` instead of the full union. - event_flags: EventFlags, - data: u64, -} - -/// A vector of `Event`s, plus context for interpreting them. -pub struct EventVec { - events: Vec, -} - -impl EventVec { - /// Constructs an `EventVec` with memory for `capacity` `Event`s. - #[inline] - pub fn with_capacity(capacity: usize) -> Self { - Self { - events: Vec::with_capacity(capacity), - } - } - - /// Returns the current `Event` capacity of this `EventVec`. - #[inline] - pub fn capacity(&self) -> usize { - self.events.capacity() - } - - /// Reserves enough memory for at least `additional` more `Event`s. - #[inline] - pub fn reserve(&mut self, additional: usize) { - self.events.reserve(additional); - } - - /// Reserves enough memory for exactly `additional` more `Event`s. - #[inline] - pub fn reserve_exact(&mut self, additional: usize) { - self.events.reserve_exact(additional); - } - - /// Clears all the `Events` out of this `EventVec`. - #[inline] - pub fn clear(&mut self) { - self.events.clear(); - } - - /// Shrinks the capacity of this `EventVec` as much as possible. - #[inline] - pub fn shrink_to_fit(&mut self) { - self.events.shrink_to_fit(); - } - - /// Returns an iterator over the `Event`s in this `EventVec`. - #[inline] - pub fn iter(&self) -> Iter<'_> { - Iter { - iter: self.events.iter(), - } - } - - /// Returns the number of `Event`s logically contained in this `EventVec`. - #[inline] - pub fn len(&mut self) -> usize { - self.events.len() - } - - /// Tests whether this `EventVec` is logically empty. - #[inline] - pub fn is_empty(&mut self) -> bool { - self.events.is_empty() - } -} - -impl<'a> IntoIterator for &'a EventVec { - type IntoIter = Iter<'a>; - type Item = (EventFlags, u64); - - #[inline] - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} diff --git a/vendor/rustix/src/backend/linux_raw/io/errno.rs b/vendor/rustix/src/backend/linux_raw/io/errno.rs index 9db14d06e..af057e2da 100644 --- a/vendor/rustix/src/backend/linux_raw/io/errno.rs +++ b/vendor/rustix/src/backend/linux_raw/io/errno.rs @@ -10,7 +10,7 @@ #![allow(unsafe_code)] #![cfg_attr(not(rustc_attrs), allow(unused_unsafe))] -use super::super::c; +use crate::backend::c; use crate::backend::fd::RawFd; use crate::backend::reg::{RetNumber, RetReg}; use crate::io; @@ -62,12 +62,12 @@ impl Errno { /// Convert from a C `errno` value (which is positive) to an `Errno`. const fn from_errno(raw: u32) -> Self { - // We store error values in negated form, so that we don't have to negate - // them after every syscall. + // We store error values in negated form, so that we don't have to + // negate them after every syscall. let encoded = raw.wrapping_neg() as u16; // TODO: Use Range::contains, once that's `const`. - const_assert!(encoded >= 0xf001); + assert!(encoded >= 0xf001); // SAFETY: Linux syscalls return negated error values in the range // `-4095..0`, which we just asserted. @@ -239,6 +239,13 @@ pub(in crate::backend) fn decode_usize_infallible(raw: RetReg(raw: RetReg) -> c::c_int { + raw.decode_c_int() +} + +/// Return the contained `c_uint` value. +#[cfg(not(debug_assertions))] +#[inline] pub(in crate::backend) fn decode_c_uint_infallible(raw: RetReg) -> c::c_uint { raw.decode_c_uint() } diff --git a/vendor/rustix/src/backend/linux_raw/io/io_slice.rs b/vendor/rustix/src/backend/linux_raw/io/io_slice.rs deleted file mode 100644 index fc8e64698..000000000 --- a/vendor/rustix/src/backend/linux_raw/io/io_slice.rs +++ /dev/null @@ -1,98 +0,0 @@ -//! The following is derived from Rust's -//! library/std/src/sys/unix/io.rs -//! dca3f1b786efd27be3b325ed1e01e247aa589c3b. - -#![allow(unsafe_code)] -use super::super::c; -use core::marker::PhantomData; -use core::slice; -use linux_raw_sys::general::__kernel_size_t; - -/// -#[derive(Copy, Clone)] -#[repr(transparent)] -pub struct IoSlice<'a> { - vec: c::iovec, - _p: PhantomData<&'a [u8]>, -} - -impl<'a> IoSlice<'a> { - /// - #[inline] - pub fn new(buf: &'a [u8]) -> IoSlice<'a> { - IoSlice { - vec: c::iovec { - iov_base: buf.as_ptr() as *mut u8 as *mut c::c_void, - iov_len: buf.len() as _, - }, - _p: PhantomData, - } - } - - /// - #[inline] - pub fn advance(&mut self, n: usize) { - if self.vec.iov_len < n as _ { - panic!("advancing IoSlice beyond its length"); - } - - unsafe { - self.vec.iov_len -= n as __kernel_size_t; - self.vec.iov_base = self.vec.iov_base.add(n); - } - } - - /// - #[inline] - pub fn as_slice(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len as usize) } - } -} - -/// -#[repr(transparent)] -pub struct IoSliceMut<'a> { - vec: c::iovec, - _p: PhantomData<&'a mut [u8]>, -} - -impl<'a> IoSliceMut<'a> { - /// - #[inline] - pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { - IoSliceMut { - vec: c::iovec { - iov_base: buf.as_mut_ptr() as *mut c::c_void, - iov_len: buf.len() as _, - }, - _p: PhantomData, - } - } - - /// - #[inline] - pub fn advance(&mut self, n: usize) { - if self.vec.iov_len < n as _ { - panic!("advancing IoSliceMut beyond its length"); - } - - unsafe { - self.vec.iov_len -= n as __kernel_size_t; - self.vec.iov_base = self.vec.iov_base.add(n); - } - } - - /// - #[inline] - pub fn as_slice(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len as usize) } - } - - /// - #[inline] - pub fn as_mut_slice(&mut self) -> &mut [u8] { - unsafe { - slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len as usize) - } - } -} diff --git a/vendor/rustix/src/backend/linux_raw/io/mod.rs b/vendor/rustix/src/backend/linux_raw/io/mod.rs index f5c2bf3c0..9477b9b95 100644 --- a/vendor/rustix/src/backend/linux_raw/io/mod.rs +++ b/vendor/rustix/src/backend/linux_raw/io/mod.rs @@ -1,7 +1,3 @@ -pub mod epoll; pub(crate) mod errno; -#[cfg(not(feature = "std"))] -pub(crate) mod io_slice; -pub(crate) mod poll_fd; pub(crate) mod syscalls; pub(crate) mod types; diff --git a/vendor/rustix/src/backend/linux_raw/io/poll_fd.rs b/vendor/rustix/src/backend/linux_raw/io/poll_fd.rs deleted file mode 100644 index 252358331..000000000 --- a/vendor/rustix/src/backend/linux_raw/io/poll_fd.rs +++ /dev/null @@ -1,93 +0,0 @@ -use crate::fd::{AsFd, BorrowedFd}; -use bitflags::bitflags; - -bitflags! { - /// `POLL*` flags for use with [`poll`]. - /// - /// [`poll`]: crate::io::poll - pub struct PollFlags: u16 { - /// `POLLIN` - const IN = linux_raw_sys::general::POLLIN as u16; - /// `POLLPRI` - const PRI = linux_raw_sys::general::POLLPRI as u16; - /// `POLLOUT` - const OUT = linux_raw_sys::general::POLLOUT as u16; - /// `POLLRDNORM` - const RDNORM = linux_raw_sys::general::POLLRDNORM as u16; - /// `POLLWRNORM` - const WRNORM = linux_raw_sys::general::POLLWRNORM as u16; - /// `POLLRDBAND` - const RDBAND = linux_raw_sys::general::POLLRDBAND as u16; - /// `POLLWRBAND` - const WRBAND = linux_raw_sys::general::POLLWRBAND as u16; - /// `POLLERR` - const ERR = linux_raw_sys::general::POLLERR as u16; - /// `POLLHUP` - const HUP = linux_raw_sys::general::POLLHUP as u16; - /// `POLLNVAL` - const NVAL = linux_raw_sys::general::POLLNVAL as u16; - /// `POLLRDHUP` - const RDHUP = linux_raw_sys::general::POLLRDHUP as u16; - } -} - -/// `struct pollfd`—File descriptor and flags for use with [`poll`]. -/// -/// [`poll`]: crate::io::poll -#[doc(alias = "pollfd")] -#[repr(C)] -#[derive(Debug, Clone)] -pub struct PollFd<'fd> { - pub(crate) fd: BorrowedFd<'fd>, - pub(crate) events: u16, - pub(crate) revents: u16, -} - -impl<'fd> PollFd<'fd> { - /// Constructs a new `PollFd` holding `fd` and `events`. - #[inline] - pub fn new(fd: &'fd Fd, events: PollFlags) -> Self { - Self::from_borrowed_fd(fd.as_fd(), events) - } - - /// Sets the contained file descriptor to `fd`. - #[inline] - pub fn set_fd(&mut self, fd: &'fd Fd) { - self.fd = fd.as_fd(); - } - - /// Clears the ready events. - #[inline] - pub fn clear_revents(&mut self) { - self.revents = 0; - } - - /// Constructs a new `PollFd` holding `fd` and `events`. - /// - /// This is the same as `new`, but can be used to avoid borrowing the - /// `BorrowedFd`, which can be tricky in situations where the `BorrowedFd` - /// is a temporary. - #[inline] - pub fn from_borrowed_fd(fd: BorrowedFd<'fd>, events: PollFlags) -> Self { - Self { - fd, - events: events.bits(), - revents: 0, - } - } - - /// Returns the ready events. - #[inline] - pub fn revents(&self) -> PollFlags { - // Use `unwrap()` here because in theory we know we know all the bits - // the OS might set here, but OS's have added extensions in the past. - PollFlags::from_bits(self.revents).unwrap() - } -} - -impl<'fd> AsFd for PollFd<'fd> { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - self.fd.as_fd() - } -} diff --git a/vendor/rustix/src/backend/linux_raw/io/syscalls.rs b/vendor/rustix/src/backend/linux_raw/io/syscalls.rs index c76fb0635..45e0dd647 100644 --- a/vendor/rustix/src/backend/linux_raw/io/syscalls.rs +++ b/vendor/rustix/src/backend/linux_raw/io/syscalls.rs @@ -6,38 +6,30 @@ #![allow(unsafe_code)] #![allow(clippy::undocumented_unsafe_blocks)] -use super::super::c; #[cfg(target_pointer_width = "64")] -use super::super::conv::loff_t_from_u64; -use super::super::conv::{ - by_ref, c_int, c_uint, opt_mut, pass_usize, raw_fd, ret, ret_c_uint, ret_discarded_fd, - ret_owned_fd, ret_usize, slice, slice_mut, zero, +use crate::backend::conv::loff_t_from_u64; +#[cfg(all( + target_pointer_width = "32", + any(target_arch = "arm", target_arch = "mips", target_arch = "power"), +))] +use crate::backend::conv::zero; +use crate::backend::conv::{ + by_ref, c_uint, raw_fd, ret, ret_c_uint, ret_discarded_fd, ret_owned_fd, ret_usize, slice, + slice_mut, }; #[cfg(target_pointer_width = "32")] -use super::super::conv::{hi, lo}; +use crate::backend::conv::{hi, lo}; +use crate::backend::{c, MAX_IOV}; use crate::fd::{AsFd, BorrowedFd, OwnedFd, RawFd}; -#[cfg(any(target_os = "android", target_os = "linux"))] -use crate::io::SpliceFlags; -use crate::io::{ - self, epoll, DupFlags, EventfdFlags, FdFlags, IoSlice, IoSliceMut, IoSliceRaw, PipeFlags, - PollFd, ReadWriteFlags, -}; +use crate::io::{self, DupFlags, FdFlags, IoSlice, IoSliceMut, ReadWriteFlags}; #[cfg(all(feature = "fs", feature = "net"))] use crate::net::{RecvFlags, SendFlags}; use core::cmp; use core::mem::MaybeUninit; #[cfg(target_os = "espidf")] use linux_raw_sys::general::F_DUPFD; -use linux_raw_sys::general::{ - epoll_event, EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD, F_DUPFD_CLOEXEC, F_GETFD, F_SETFD, - UIO_MAXIOV, -}; -use linux_raw_sys::ioctl::{BLKPBSZGET, BLKSSZGET, FICLONE, FIONBIO, FIONREAD, TIOCEXCL, TIOCNXCL}; -#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] -use { - super::super::conv::{opt_ref, size_of}, - linux_raw_sys::general::{__kernel_timespec, kernel_sigset_t}, -}; +use linux_raw_sys::general::{F_DUPFD_CLOEXEC, F_GETFD, F_SETFD}; +use linux_raw_sys::ioctl::{FIONBIO, FIONREAD}; #[inline] pub(crate) fn read(fd: BorrowedFd<'_>, buf: &mut [u8]) -> io::Result { @@ -94,7 +86,7 @@ pub(crate) fn pread(fd: BorrowedFd<'_>, buf: &mut [u8], pos: u64) -> io::Result< #[inline] pub(crate) fn readv(fd: BorrowedFd<'_>, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), max_iov())]); + let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), MAX_IOV)]); unsafe { ret_usize(syscall!(__NR_readv, fd, bufs_addr, bufs_len)) } } @@ -105,7 +97,7 @@ pub(crate) fn preadv( bufs: &mut [IoSliceMut<'_>], pos: u64, ) -> io::Result { - let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), max_iov())]); + let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), MAX_IOV)]); #[cfg(target_pointer_width = "32")] unsafe { @@ -137,7 +129,7 @@ pub(crate) fn preadv2( pos: u64, flags: ReadWriteFlags, ) -> io::Result { - let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), max_iov())]); + let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), MAX_IOV)]); #[cfg(target_pointer_width = "32")] unsafe { @@ -219,14 +211,14 @@ pub(crate) fn pwrite(fd: BorrowedFd<'_>, buf: &[u8], pos: u64) -> io::Result, bufs: &[IoSlice<'_>]) -> io::Result { - let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), max_iov())]); + let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), MAX_IOV)]); unsafe { ret_usize(syscall_readonly!(__NR_writev, fd, bufs_addr, bufs_len)) } } #[inline] pub(crate) fn pwritev(fd: BorrowedFd<'_>, bufs: &[IoSlice<'_>], pos: u64) -> io::Result { - let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), max_iov())]); + let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), MAX_IOV)]); #[cfg(target_pointer_width = "32")] unsafe { @@ -258,7 +250,7 @@ pub(crate) fn pwritev2( pos: u64, flags: ReadWriteFlags, ) -> io::Result { - let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), max_iov())]); + let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), MAX_IOV)]); #[cfg(target_pointer_width = "32")] unsafe { @@ -285,23 +277,12 @@ pub(crate) fn pwritev2( } } -/// The maximum number of buffers that can be passed into a vectored I/O system -/// call on the current platform. -const fn max_iov() -> usize { - UIO_MAXIOV as usize -} - #[inline] pub(crate) unsafe fn close(fd: RawFd) { // See the documentation for [`io::close`] for why errors are ignored. syscall_readonly!(__NR_close, raw_fd(fd)).decode_void(); } -#[inline] -pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result { - unsafe { ret_owned_fd(syscall_readonly!(__NR_eventfd2, c_uint(initval), flags)) } -} - #[inline] pub(crate) fn ioctl_fionread(fd: BorrowedFd<'_>) -> io::Result { unsafe { @@ -324,39 +305,6 @@ pub(crate) fn ioctl_fionbio(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> { } } -#[inline] -pub(crate) fn ioctl_tiocexcl(fd: BorrowedFd<'_>) -> io::Result<()> { - unsafe { ret(syscall_readonly!(__NR_ioctl, fd, c_uint(TIOCEXCL))) } -} - -#[inline] -pub(crate) fn ioctl_tiocnxcl(fd: BorrowedFd<'_>) -> io::Result<()> { - unsafe { ret(syscall_readonly!(__NR_ioctl, fd, c_uint(TIOCNXCL))) } -} - -#[inline] -pub(crate) fn ioctl_blksszget(fd: BorrowedFd) -> io::Result { - let mut result = MaybeUninit::::uninit(); - unsafe { - ret(syscall!(__NR_ioctl, fd, c_uint(BLKSSZGET), &mut result))?; - Ok(result.assume_init() as u32) - } -} - -#[inline] -pub(crate) fn ioctl_blkpbszget(fd: BorrowedFd) -> io::Result { - let mut result = MaybeUninit::::uninit(); - unsafe { - ret(syscall!(__NR_ioctl, fd, c_uint(BLKPBSZGET), &mut result))?; - Ok(result.assume_init() as u32) - } -} - -#[inline] -pub(crate) fn ioctl_ficlone(fd: BorrowedFd<'_>, src_fd: BorrowedFd<'_>) -> io::Result<()> { - unsafe { ret(syscall_readonly!(__NR_ioctl, fd, c_uint(FICLONE), src_fd)) } -} - #[cfg(all(feature = "fs", feature = "net"))] pub(crate) fn is_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> { let (mut read, mut write) = crate::fs::fd::_is_file_read_write(fd)?; @@ -369,8 +317,11 @@ pub(crate) fn is_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> { // TODO: This code would benefit from having a better way to read into // uninitialized memory. let mut buf = [0]; - match super::super::net::syscalls::recv(fd, &mut buf, RecvFlags::PEEK | RecvFlags::DONTWAIT) - { + match crate::backend::net::syscalls::recv( + fd, + &mut buf, + RecvFlags::PEEK | RecvFlags::DONTWAIT, + ) { Ok(0) => read = false, Err(err) => { #[allow(unreachable_patterns)] // `EAGAIN` may equal `EWOULDBLOCK` @@ -387,7 +338,7 @@ pub(crate) fn is_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> { // Do a `send` with `DONTWAIT` for 0 bytes. An `EPIPE` indicates // the write side is shut down. #[allow(unreachable_patterns)] // `EAGAIN` equals `EWOULDBLOCK` - match super::super::net::syscalls::send(fd, &[], SendFlags::DONTWAIT) { + match crate::backend::net::syscalls::send(fd, &[], SendFlags::DONTWAIT) { // TODO or-patterns when we don't need 1.51 Err(io::Errno::AGAIN) => (), Err(io::Errno::WOULDBLOCK) => (), @@ -431,12 +382,12 @@ pub(crate) fn fcntl_getfd(fd: BorrowedFd<'_>) -> io::Result { #[cfg(target_pointer_width = "32")] unsafe { ret_c_uint(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETFD))) - .map(FdFlags::from_bits_truncate) + .map(FdFlags::from_bits_retain) } #[cfg(target_pointer_width = "64")] unsafe { ret_c_uint(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETFD))) - .map(FdFlags::from_bits_truncate) + .map(FdFlags::from_bits_retain) } } @@ -496,186 +447,3 @@ pub(crate) fn fcntl_dupfd_cloexec(fd: BorrowedFd<'_>, min: RawFd) -> io::Result< )) } } - -#[inline] -pub(crate) fn pipe_with(flags: PipeFlags) -> io::Result<(OwnedFd, OwnedFd)> { - unsafe { - let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit(); - ret(syscall!(__NR_pipe2, &mut result, flags))?; - let [p0, p1] = result.assume_init(); - Ok((p0, p1)) - } -} - -#[inline] -pub(crate) fn pipe() -> io::Result<(OwnedFd, OwnedFd)> { - // aarch64 and risc64 omit `__NR_pipe`. On mips, `__NR_pipe` uses a special - // calling convention, but using it is not worth complicating our syscall - // wrapping infrastructure at this time. - #[cfg(any( - target_arch = "aarch64", - target_arch = "mips", - target_arch = "mips64", - target_arch = "riscv64", - ))] - { - pipe_with(PipeFlags::empty()) - } - #[cfg(not(any( - target_arch = "aarch64", - target_arch = "mips", - target_arch = "mips64", - target_arch = "riscv64", - )))] - unsafe { - let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit(); - ret(syscall!(__NR_pipe, &mut result))?; - let [p0, p1] = result.assume_init(); - Ok((p0, p1)) - } -} - -#[inline] -pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result { - let (fds_addr_mut, fds_len) = slice_mut(fds); - - #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] - unsafe { - let timeout = if timeout >= 0 { - Some(__kernel_timespec { - tv_sec: (timeout as i64) / 1000, - tv_nsec: (timeout as i64) % 1000 * 1_000_000, - }) - } else { - None - }; - ret_usize(syscall!( - __NR_ppoll, - fds_addr_mut, - fds_len, - opt_ref(timeout.as_ref()), - zero(), - size_of::() - )) - } - #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))] - unsafe { - ret_usize(syscall!(__NR_poll, fds_addr_mut, fds_len, c_int(timeout))) - } -} - -#[inline] -pub(crate) fn epoll_create(flags: epoll::CreateFlags) -> io::Result { - unsafe { ret_owned_fd(syscall_readonly!(__NR_epoll_create1, flags)) } -} - -#[inline] -pub(crate) unsafe fn epoll_add( - epfd: BorrowedFd<'_>, - fd: c::c_int, - event: &epoll_event, -) -> io::Result<()> { - ret(syscall_readonly!( - __NR_epoll_ctl, - epfd, - c_uint(EPOLL_CTL_ADD), - raw_fd(fd), - by_ref(event) - )) -} - -#[inline] -pub(crate) unsafe fn epoll_mod( - epfd: BorrowedFd<'_>, - fd: c::c_int, - event: &epoll_event, -) -> io::Result<()> { - ret(syscall_readonly!( - __NR_epoll_ctl, - epfd, - c_uint(EPOLL_CTL_MOD), - raw_fd(fd), - by_ref(event) - )) -} - -#[inline] -pub(crate) unsafe fn epoll_del(epfd: BorrowedFd<'_>, fd: c::c_int) -> io::Result<()> { - ret(syscall_readonly!( - __NR_epoll_ctl, - epfd, - c_uint(EPOLL_CTL_DEL), - raw_fd(fd), - zero() - )) -} - -#[inline] -pub(crate) fn epoll_wait( - epfd: BorrowedFd<'_>, - events: *mut epoll_event, - num_events: usize, - timeout: c::c_int, -) -> io::Result { - #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))] - unsafe { - ret_usize(syscall!( - __NR_epoll_wait, - epfd, - events, - pass_usize(num_events), - c_int(timeout) - )) - } - #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] - unsafe { - ret_usize(syscall!( - __NR_epoll_pwait, - epfd, - events, - pass_usize(num_events), - c_int(timeout), - zero() - )) - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -pub fn splice( - fd_in: BorrowedFd, - off_in: Option<&mut u64>, - fd_out: BorrowedFd, - off_out: Option<&mut u64>, - len: usize, - flags: SpliceFlags, -) -> io::Result { - unsafe { - ret_usize(syscall!( - __NR_splice, - fd_in, - opt_mut(off_in), - fd_out, - opt_mut(off_out), - pass_usize(len), - c_uint(flags.bits()) - )) - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -pub unsafe fn vmsplice( - fd: BorrowedFd, - bufs: &[IoSliceRaw], - flags: SpliceFlags, -) -> io::Result { - let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), max_iov())]); - ret_usize(syscall!( - __NR_vmsplice, - fd, - bufs_addr, - bufs_len, - c_uint(flags.bits()) - )) -} diff --git a/vendor/rustix/src/backend/linux_raw/io/types.rs b/vendor/rustix/src/backend/linux_raw/io/types.rs index cb6c6acef..c06134440 100644 --- a/vendor/rustix/src/backend/linux_raw/io/types.rs +++ b/vendor/rustix/src/backend/linux_raw/io/types.rs @@ -1,12 +1,13 @@ -use super::super::c; +use crate::backend::c; use bitflags::bitflags; -use core::marker::PhantomData; bitflags! { /// `FD_*` constants for use with [`fcntl_getfd`] and [`fcntl_setfd`]. /// /// [`fcntl_getfd`]: crate::io::fcntl_getfd /// [`fcntl_setfd`]: crate::io::fcntl_setfd + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct FdFlags: c::c_uint { /// `FD_CLOEXEC` const CLOEXEC = linux_raw_sys::general::FD_CLOEXEC; @@ -18,6 +19,8 @@ bitflags! { /// /// [`preadv2`]: crate::io::preadv2 /// [`pwritev2`]: crate::io::pwritev + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct ReadWriteFlags: c::c_uint { /// `RWF_DSYNC` (since Linux 4.7) const DSYNC = linux_raw_sys::general::RWF_DSYNC; @@ -32,98 +35,14 @@ bitflags! { } } -#[cfg(any(target_os = "android", target_os = "linux"))] -bitflags! { - /// `SPLICE_F_*` constants for use with [`splice`] and [`vmsplice`]. - pub struct SpliceFlags: c::c_uint { - /// `SPLICE_F_MOVE` - const MOVE = linux_raw_sys::general::SPLICE_F_MOVE; - /// `SPLICE_F_NONBLOCK` - const NONBLOCK = linux_raw_sys::general::SPLICE_F_NONBLOCK; - /// `SPLICE_F_MORE` - const MORE = linux_raw_sys::general::SPLICE_F_MORE; - /// `SPLICE_F_GIFT` - const GIFT = linux_raw_sys::general::SPLICE_F_GIFT; - } -} - bitflags! { /// `O_*` constants for use with [`dup2`]. /// /// [`dup2`]: crate::io::dup2 + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct DupFlags: c::c_uint { /// `O_CLOEXEC` const CLOEXEC = linux_raw_sys::general::O_CLOEXEC; } } - -bitflags! { - /// `O_*` constants for use with [`pipe_with`]. - /// - /// [`pipe_with`]: crate::io::pipe_with - pub struct PipeFlags: c::c_uint { - /// `O_CLOEXEC` - const CLOEXEC = linux_raw_sys::general::O_CLOEXEC; - /// `O_DIRECT` - const DIRECT = linux_raw_sys::general::O_DIRECT; - /// `O_NONBLOCK` - const NONBLOCK = linux_raw_sys::general::O_NONBLOCK; - } -} - -bitflags! { - /// `EFD_*` flags for use with [`eventfd`]. - /// - /// [`eventfd`]: crate::io::eventfd - pub struct EventfdFlags: c::c_uint { - /// `EFD_CLOEXEC` - const CLOEXEC = linux_raw_sys::general::EFD_CLOEXEC; - /// `EFD_NONBLOCK` - const NONBLOCK = linux_raw_sys::general::EFD_NONBLOCK; - /// `EFD_SEMAPHORE` - const SEMAPHORE = linux_raw_sys::general::EFD_SEMAPHORE; - } -} - -/// `PIPE_BUF`—The maximum size of a write to a pipe guaranteed to be atomic. -pub const PIPE_BUF: usize = linux_raw_sys::general::PIPE_BUF as usize; - -pub(crate) const AT_FDCWD: c::c_int = linux_raw_sys::general::AT_FDCWD; -pub(crate) const STDIN_FILENO: c::c_uint = linux_raw_sys::general::STDIN_FILENO; -pub(crate) const STDOUT_FILENO: c::c_uint = linux_raw_sys::general::STDOUT_FILENO; -pub(crate) const STDERR_FILENO: c::c_uint = linux_raw_sys::general::STDERR_FILENO; - -/// A buffer type used with `vmsplice`. -/// It is guaranteed to be ABI compatible with the iovec type on Unix platforms -/// and `WSABUF` on Windows. Unlike `IoSlice` and `IoSliceMut` it is -/// semantically like a raw pointer, and therefore can be shared or mutated as -/// needed. -#[repr(transparent)] -pub struct IoSliceRaw<'a> { - _buf: c::iovec, - _lifetime: PhantomData<&'a ()>, -} - -impl<'a> IoSliceRaw<'a> { - /// Creates a new `IoSlice` wrapping a byte slice. - pub fn from_slice(buf: &'a [u8]) -> Self { - IoSliceRaw { - _buf: c::iovec { - iov_base: buf.as_ptr() as *mut u8 as *mut c::c_void, - iov_len: buf.len() as _, - }, - _lifetime: PhantomData, - } - } - - /// Creates a new `IoSlice` wrapping a mutable byte slice. - pub fn from_slice_mut(buf: &'a mut [u8]) -> Self { - IoSliceRaw { - _buf: c::iovec { - iov_base: buf.as_mut_ptr() as *mut c::c_void, - iov_len: buf.len() as _, - }, - _lifetime: PhantomData, - } - } -} diff --git a/vendor/rustix/src/backend/linux_raw/io_uring/syscalls.rs b/vendor/rustix/src/backend/linux_raw/io_uring/syscalls.rs index 16655fe77..90c82c129 100644 --- a/vendor/rustix/src/backend/linux_raw/io_uring/syscalls.rs +++ b/vendor/rustix/src/backend/linux_raw/io_uring/syscalls.rs @@ -6,7 +6,7 @@ #![allow(unsafe_code)] #![allow(clippy::undocumented_unsafe_blocks)] -use super::super::conv::{by_mut, c_uint, pass_usize, ret_c_uint, ret_owned_fd}; +use crate::backend::conv::{by_mut, c_uint, pass_usize, ret_c_uint, ret_owned_fd}; use crate::fd::{BorrowedFd, OwnedFd}; use crate::io; use crate::io_uring::{io_uring_params, IoringEnterFlags, IoringRegisterOp}; diff --git a/vendor/rustix/src/backend/linux_raw/mm/syscalls.rs b/vendor/rustix/src/backend/linux_raw/mm/syscalls.rs index 8fa6a3ec3..b51f826a9 100644 --- a/vendor/rustix/src/backend/linux_raw/mm/syscalls.rs +++ b/vendor/rustix/src/backend/linux_raw/mm/syscalls.rs @@ -6,18 +6,16 @@ #![allow(unsafe_code)] #![allow(clippy::undocumented_unsafe_blocks)] -use super::super::c; -#[cfg(target_pointer_width = "64")] -use super::super::conv::loff_t_from_u64; -use super::super::conv::{c_uint, no_fd, pass_usize, ret, ret_owned_fd, ret_void_star}; use super::types::{ Advice, MapFlags, MlockFlags, MprotectFlags, MremapFlags, MsyncFlags, ProtFlags, UserfaultfdFlags, }; +use crate::backend::c; +#[cfg(target_pointer_width = "64")] +use crate::backend::conv::loff_t_from_u64; +use crate::backend::conv::{c_uint, no_fd, pass_usize, ret, ret_owned_fd, ret_void_star}; use crate::fd::{BorrowedFd, OwnedFd}; use crate::io; -#[cfg(target_pointer_width = "32")] -use core::convert::TryInto; use linux_raw_sys::general::MAP_ANONYMOUS; #[inline] diff --git a/vendor/rustix/src/backend/linux_raw/mm/types.rs b/vendor/rustix/src/backend/linux_raw/mm/types.rs index a34c41f4f..576f08a3d 100644 --- a/vendor/rustix/src/backend/linux_raw/mm/types.rs +++ b/vendor/rustix/src/backend/linux_raw/mm/types.rs @@ -1,4 +1,4 @@ -use super::super::c; +use crate::backend::c; use bitflags::bitflags; bitflags! { @@ -7,6 +7,8 @@ bitflags! { /// For `PROT_NONE`, use `ProtFlags::empty()`. /// /// [`mmap`]: crate::io::mmap + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct ProtFlags: u32 { /// `PROT_READ` const READ = linux_raw_sys::general::PROT_READ; @@ -23,6 +25,8 @@ bitflags! { /// For `PROT_NONE`, use `MprotectFlags::empty()`. /// /// [`mprotect`]: crate::io::mprotect + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct MprotectFlags: u32 { /// `PROT_READ` const READ = linux_raw_sys::general::PROT_READ; @@ -44,6 +48,8 @@ bitflags! { /// /// [`mmap`]: crate::io::mmap /// [`mmap_anonymous`]: crates::io::mmap_anonymous + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct MapFlags: u32 { /// `MAP_SHARED` const SHARED = linux_raw_sys::general::MAP_SHARED; @@ -89,6 +95,8 @@ bitflags! { /// /// [`mremap`]: crate::io::mremap /// [`mremap_fixed`]: crate::io::mremap_fixed + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct MremapFlags: u32 { /// `MREMAP_MAYMOVE` const MAYMOVE = linux_raw_sys::general::MREMAP_MAYMOVE; @@ -101,6 +109,8 @@ bitflags! { /// `MLOCK_*` flags for use with [`mlock_with`]. /// /// [`mlock_with`]: crate::io::mlock_with + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct MlockFlags: u32 { /// `MLOCK_ONFAULT` const ONFAULT = linux_raw_sys::general::MLOCK_ONFAULT; @@ -111,6 +121,8 @@ bitflags! { /// `MS_*` flags for use with [`msync`]. /// /// [`msync`]: crate::io::msync + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct MsyncFlags: u32 { /// `MS_SYNC`—Requests an update and waits for it to complete. const SYNC = linux_raw_sys::general::MS_SYNC; @@ -128,6 +140,8 @@ bitflags! { /// `O_*` flags for use with [`userfaultfd`]. /// /// [`userfaultfd`]: crate::io::userfaultfd + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct UserfaultfdFlags: c::c_uint { /// `O_CLOEXEC` const CLOEXEC = linux_raw_sys::general::O_CLOEXEC; @@ -195,6 +209,8 @@ pub enum Advice { LinuxPopulateRead = linux_raw_sys::general::MADV_POPULATE_READ, /// `MADV_POPULATE_WRITE` (since Linux 5.14) LinuxPopulateWrite = linux_raw_sys::general::MADV_POPULATE_WRITE, + /// `MADV_DONTNEED_LOCKED` (since Linux 5.18) + LinuxDontneedLocked = linux_raw_sys::general::MADV_DONTNEED_LOCKED, } #[allow(non_upper_case_globals)] diff --git a/vendor/rustix/src/backend/linux_raw/mod.rs b/vendor/rustix/src/backend/linux_raw/mod.rs index e7e073e32..cd5805f88 100644 --- a/vendor/rustix/src/backend/linux_raw/mod.rs +++ b/vendor/rustix/src/backend/linux_raw/mod.rs @@ -17,6 +17,12 @@ #[macro_use] mod arch; mod conv; +#[cfg(any( + feature = "param", + feature = "runtime", + feature = "time", + target_arch = "x86" +))] mod elf; mod reg; #[cfg(any(feature = "time", target_arch = "x86"))] @@ -24,7 +30,21 @@ mod vdso; #[cfg(any(feature = "time", target_arch = "x86"))] mod vdso_wrappers; -#[cfg(feature = "fs")] +#[cfg(feature = "event")] +pub(crate) mod event; +#[cfg(any( + feature = "fs", + all( + not(feature = "use-libc-auxv"), + not(target_vendor = "mustang"), + any( + feature = "param", + feature = "runtime", + feature = "time", + target_arch = "x86", + ) + ) +))] pub(crate) mod fs; pub(crate) mod io; #[cfg(feature = "io_uring")] @@ -40,28 +60,57 @@ pub(crate) mod net; target_arch = "x86", ))] pub(crate) mod param; +#[cfg(feature = "pipe")] +pub(crate) mod pipe; +#[cfg(feature = "process")] pub(crate) mod process; +#[cfg(feature = "pty")] +pub(crate) mod pty; #[cfg(feature = "rand")] pub(crate) mod rand; #[cfg(feature = "runtime")] pub(crate) mod runtime; +#[cfg(feature = "system")] +pub(crate) mod system; #[cfg(feature = "termios")] pub(crate) mod termios; #[cfg(feature = "thread")] pub(crate) mod thread; +#[cfg(feature = "time")] pub(crate) mod time; -#[cfg(feature = "std")] pub(crate) mod fd { - pub use io_lifetimes::*; - #[allow(unused_imports)] - pub(crate) use std::os::unix::io::RawFd as LibcFd; - pub use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; + pub use crate::maybe_polyfill::os::fd::{ + AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd, + }; } -#[cfg(not(feature = "std"))] -pub(crate) use crate::io::fd; - // The linux_raw backend doesn't use actual libc, so we define selected // libc-like definitions in a module called `c`. pub(crate) mod c; + +// Private modules used by multiple public modules. +#[cfg(any(feature = "procfs", feature = "process", feature = "runtime"))] +pub(crate) mod pid; +#[cfg(any(feature = "process", feature = "thread"))] +pub(crate) mod prctl; +#[cfg(any( + feature = "fs", + feature = "process", + feature = "thread", + all( + not(feature = "use-libc-auxv"), + not(target_vendor = "mustang"), + any( + feature = "param", + feature = "runtime", + feature = "time", + target_arch = "x86", + ) + ) +))] +pub(crate) mod ugid; + +/// The maximum number of buffers that can be passed into a vectored I/O system +/// call on the current platform. +const MAX_IOV: usize = linux_raw_sys::general::UIO_MAXIOV as usize; diff --git a/vendor/rustix/src/backend/linux_raw/net/addr.rs b/vendor/rustix/src/backend/linux_raw/net/addr.rs index b69c6deca..4a203ed16 100644 --- a/vendor/rustix/src/backend/linux_raw/net/addr.rs +++ b/vendor/rustix/src/backend/linux_raw/net/addr.rs @@ -1,15 +1,17 @@ -//! IPv4, IPv6, and Socket addresses. +//! Socket address utilities. //! //! # Safety //! -//! Linux's IPv6 type contains a union. +//! This file uses `CStr::from_bytes_with_nul_unchecked` on a string it knows +//! to be NUL-terminated. #![allow(unsafe_code)] -use super::super::c; +use crate::backend::c; use crate::ffi::CStr; use crate::{io, path}; -use core::convert::TryInto; -use core::{fmt, slice}; +use core::cmp::Ordering; +use core::fmt; +use core::hash::{Hash, Hasher}; /// `struct sockaddr_un` #[derive(Clone)] @@ -34,7 +36,7 @@ impl SocketAddrUnix { return Err(io::Errno::NAMETOOLONG); } for (i, b) in bytes.iter().enumerate() { - unix.sun_path[i] = *b as c::c_char; + unix.sun_path[i] = *b; } let len = offsetof_sun_path() + bytes.len(); let len = len.try_into().unwrap(); @@ -45,19 +47,18 @@ impl SocketAddrUnix { #[inline] pub fn new_abstract_name(name: &[u8]) -> io::Result { let mut unix = Self::init(); - if 1 + name.len() > unix.sun_path.len() { - return Err(io::Errno::NAMETOOLONG); - } - unix.sun_path[0] = b'\0' as c::c_char; - for (i, b) in name.iter().enumerate() { - unix.sun_path[1 + i] = *b as c::c_char; + let id = &mut unix.sun_path[1..]; + if let Some(id) = id.get_mut(..name.len()) { + id.copy_from_slice(name); + let len = offsetof_sun_path() + 1 + name.len(); + let len = len.try_into().unwrap(); + Ok(Self { unix, len }) + } else { + Err(io::Errno::NAMETOOLONG) } - let len = offsetof_sun_path() + 1 + name.len(); - let len = len.try_into().unwrap(); - Ok(Self { unix, len }) } - fn init() -> c::sockaddr_un { + const fn init() -> c::sockaddr_un { c::sockaddr_un { sun_family: c::AF_UNIX as _, sun_path: [0; 108], @@ -68,17 +69,12 @@ impl SocketAddrUnix { #[inline] pub fn path(&self) -> Option<&CStr> { let len = self.len(); - if len != 0 && self.unix.sun_path[0] != b'\0' as c::c_char { + if len != 0 && self.unix.sun_path[0] != b'\0' { let end = len as usize - offsetof_sun_path(); let bytes = &self.unix.sun_path[..end]; - // SAFETY: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`. And - // `from_bytes_with_nul_unchecked` since the string is NUL-terminated. - unsafe { - Some(CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts( - bytes.as_ptr().cast(), - bytes.len(), - ))) - } + // SAFETY: `from_bytes_with_nul_unchecked` since the string is + // NUL-terminated. + unsafe { Some(CStr::from_bytes_with_nul_unchecked(bytes)) } } else { None } @@ -88,11 +84,9 @@ impl SocketAddrUnix { #[inline] pub fn abstract_name(&self) -> Option<&[u8]> { let len = self.len(); - if len != 0 && self.unix.sun_path[0] == b'\0' as c::c_char { + if len != 0 && self.unix.sun_path[0] == b'\0' { let end = len as usize - offsetof_sun_path(); - let bytes = &self.unix.sun_path[1..end]; - // SAFETY: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`. - unsafe { Some(slice::from_raw_parts(bytes.as_ptr().cast(), bytes.len())) } + Some(&self.unix.sun_path[1..end]) } else { None } @@ -122,7 +116,7 @@ impl Eq for SocketAddrUnix {} impl PartialOrd for SocketAddrUnix { #[inline] - fn partial_cmp(&self, other: &Self) -> Option { + fn partial_cmp(&self, other: &Self) -> Option { let self_len = self.len() - offsetof_sun_path(); let other_len = other.len() - offsetof_sun_path(); self.unix.sun_path[..self_len].partial_cmp(&other.unix.sun_path[..other_len]) @@ -131,16 +125,16 @@ impl PartialOrd for SocketAddrUnix { impl Ord for SocketAddrUnix { #[inline] - fn cmp(&self, other: &Self) -> core::cmp::Ordering { + fn cmp(&self, other: &Self) -> Ordering { let self_len = self.len() - offsetof_sun_path(); let other_len = other.len() - offsetof_sun_path(); self.unix.sun_path[..self_len].cmp(&other.unix.sun_path[..other_len]) } } -impl core::hash::Hash for SocketAddrUnix { +impl Hash for SocketAddrUnix { #[inline] - fn hash(&self, state: &mut H) { + fn hash(&self, state: &mut H) { let self_len = self.len() - offsetof_sun_path(); self.unix.sun_path[..self_len].hash(state) } diff --git a/vendor/rustix/src/backend/linux_raw/net/mod.rs b/vendor/rustix/src/backend/linux_raw/net/mod.rs index f2273db1b..2b6ab34ba 100644 --- a/vendor/rustix/src/backend/linux_raw/net/mod.rs +++ b/vendor/rustix/src/backend/linux_raw/net/mod.rs @@ -1,6 +1,6 @@ pub(crate) mod addr; +pub(crate) mod msghdr; pub(crate) mod read_sockaddr; pub(crate) mod send_recv; pub(crate) mod syscalls; -pub(crate) mod types; pub(crate) mod write_sockaddr; diff --git a/vendor/rustix/src/backend/linux_raw/net/msghdr.rs b/vendor/rustix/src/backend/linux_raw/net/msghdr.rs new file mode 100644 index 000000000..3c435bcfa --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/net/msghdr.rs @@ -0,0 +1,143 @@ +//! Utilities for dealing with message headers. +//! +//! These take closures rather than returning a `c::msghdr` directly because +//! the message headers may reference stack-local data. + +#![allow(unsafe_code)] + +use crate::backend::c; +use crate::backend::net::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6}; + +use crate::io::{self, IoSlice, IoSliceMut}; +use crate::net::{RecvAncillaryBuffer, SendAncillaryBuffer, SocketAddrV4, SocketAddrV6}; +use crate::utils::as_ptr; + +use core::mem::{size_of, zeroed, MaybeUninit}; +use core::ptr::null_mut; + +fn msg_iov_len(len: usize) -> c::size_t { + // This cast cannot overflow. + len as c::size_t +} + +pub(crate) fn msg_control_len(len: usize) -> c::size_t { + // Same as above. + len as c::size_t +} + +/// Create a message header intended to receive a datagram. +pub(crate) fn with_recv_msghdr( + name: &mut MaybeUninit, + iov: &mut [IoSliceMut<'_>], + control: &mut RecvAncillaryBuffer<'_>, + f: impl FnOnce(&mut c::msghdr) -> io::Result, +) -> io::Result { + control.clear(); + + let namelen = size_of::() as c::c_int; + let mut msghdr = c::msghdr { + msg_name: name.as_mut_ptr().cast(), + msg_namelen: namelen, + msg_iov: iov.as_mut_ptr().cast(), + msg_iovlen: msg_iov_len(iov.len()), + msg_control: control.as_control_ptr().cast(), + msg_controllen: msg_control_len(control.control_len()), + + // Zero-initialize any padding bytes. + ..unsafe { zeroed() } + }; + + let res = f(&mut msghdr); + + // Reset the control length. + if res.is_ok() { + unsafe { + control.set_control_len(msghdr.msg_controllen.try_into().unwrap_or(usize::MAX)); + } + } + + res +} + +/// Create a message header intended to send without an address. +pub(crate) fn with_noaddr_msghdr( + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + f: impl FnOnce(c::msghdr) -> R, +) -> R { + f(c::msghdr { + msg_name: null_mut(), + msg_namelen: 0, + msg_iov: iov.as_ptr() as _, + msg_iovlen: msg_iov_len(iov.len()), + msg_control: control.as_control_ptr().cast(), + msg_controllen: msg_control_len(control.control_len()), + + // Zero-initialize any padding bytes. + ..unsafe { zeroed() } + }) +} + +/// Create a message header intended to send with an IPv4 address. +pub(crate) fn with_v4_msghdr( + addr: &SocketAddrV4, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + f: impl FnOnce(c::msghdr) -> R, +) -> R { + let encoded = unsafe { encode_sockaddr_v4(addr) }; + + f(c::msghdr { + msg_name: as_ptr(&encoded) as _, + msg_namelen: size_of::() as _, + msg_iov: iov.as_ptr() as _, + msg_iovlen: msg_iov_len(iov.len()), + msg_control: control.as_control_ptr().cast(), + msg_controllen: msg_control_len(control.control_len()), + + // Zero-initialize any padding bytes. + ..unsafe { zeroed() } + }) +} + +/// Create a message header intended to send with an IPv6 address. +pub(crate) fn with_v6_msghdr( + addr: &SocketAddrV6, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + f: impl FnOnce(c::msghdr) -> R, +) -> R { + let encoded = unsafe { encode_sockaddr_v6(addr) }; + + f(c::msghdr { + msg_name: as_ptr(&encoded) as _, + msg_namelen: size_of::() as _, + msg_iov: iov.as_ptr() as _, + msg_iovlen: msg_iov_len(iov.len()), + msg_control: control.as_control_ptr().cast(), + msg_controllen: msg_control_len(control.control_len()), + + // Zero-initialize any padding bytes. + ..unsafe { zeroed() } + }) +} + +/// Create a message header intended to send with a Unix address. +pub(crate) fn with_unix_msghdr( + addr: &crate::net::SocketAddrUnix, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + f: impl FnOnce(c::msghdr) -> R, +) -> R { + f(c::msghdr { + msg_name: as_ptr(addr) as _, + msg_namelen: addr.addr_len() as _, + msg_iov: iov.as_ptr() as _, + msg_iovlen: msg_iov_len(iov.len()), + msg_control: control.as_control_ptr().cast(), + msg_controllen: msg_control_len(control.control_len()), + + // Zero-initialize any padding bytes. + ..unsafe { zeroed() } + }) +} diff --git a/vendor/rustix/src/backend/linux_raw/net/read_sockaddr.rs b/vendor/rustix/src/backend/linux_raw/net/read_sockaddr.rs index b9bc09b96..f4b7d9914 100644 --- a/vendor/rustix/src/backend/linux_raw/net/read_sockaddr.rs +++ b/vendor/rustix/src/backend/linux_raw/net/read_sockaddr.rs @@ -2,10 +2,9 @@ //! we can interpret the rest of a `sockaddr` produced by the kernel. #![allow(unsafe_code)] -use super::super::c; +use crate::backend::c; use crate::io; use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6}; -use alloc::vec::Vec; use core::mem::size_of; // This must match the header of `sockaddr`. @@ -24,9 +23,9 @@ unsafe fn read_ss_family(storage: *const c::sockaddr) -> u16 { // Assert that we know the layout of `sockaddr`. let _ = c::sockaddr { __storage: c::sockaddr_storage { - __bindgen_anon_1: linux_raw_sys::general::__kernel_sockaddr_storage__bindgen_ty_1 { + __bindgen_anon_1: linux_raw_sys::net::__kernel_sockaddr_storage__bindgen_ty_1 { __bindgen_anon_1: - linux_raw_sys::general::__kernel_sockaddr_storage__bindgen_ty_1__bindgen_ty_1 { + linux_raw_sys::net::__kernel_sockaddr_storage__bindgen_ty_1__bindgen_ty_1 { ss_family: 0_u16, __data: [0; 126_usize], }, @@ -63,7 +62,7 @@ pub(crate) unsafe fn read_sockaddr( if len < size_of::() { return Err(io::Errno::INVAL); } - let decode = *storage.cast::(); + let decode = &*storage.cast::(); Ok(SocketAddrAny::V4(SocketAddrV4::new( Ipv4Addr::from(u32::from_be(decode.sin_addr.s_addr)), u16::from_be(decode.sin_port), @@ -73,7 +72,7 @@ pub(crate) unsafe fn read_sockaddr( if len < size_of::() { return Err(io::Errno::INVAL); } - let decode = *storage.cast::(); + let decode = &*storage.cast::(); Ok(SocketAddrAny::V6(SocketAddrV6::new( Ipv6Addr::from(decode.sin6_addr.in6_u.u6_addr8), u16::from_be(decode.sin6_port), @@ -88,16 +87,22 @@ pub(crate) unsafe fn read_sockaddr( if len == offsetof_sun_path { Ok(SocketAddrAny::Unix(SocketAddrUnix::new(&[][..])?)) } else { - let decode = *storage.cast::(); - assert_eq!( - decode.sun_path[len - 1 - offsetof_sun_path], - b'\0' as c::c_char - ); + let decode = &*storage.cast::(); + + // On Linux check for Linux's [abstract namespace]. + // + // [abstract namespace]: https://man7.org/linux/man-pages/man7/unix.7.html + if decode.sun_path[0] == 0 { + return SocketAddrUnix::new_abstract_name( + &decode.sun_path[1..len - offsetof_sun_path], + ) + .map(SocketAddrAny::Unix); + } + + // Otherwise we expect a NUL-terminated filesystem path. + assert_eq!(decode.sun_path[len - 1 - offsetof_sun_path], 0); Ok(SocketAddrAny::Unix(SocketAddrUnix::new( - decode.sun_path[..len - 1 - offsetof_sun_path] - .iter() - .map(|c| *c as u8) - .collect::>(), + &decode.sun_path[..len - 1 - offsetof_sun_path], )?)) } } @@ -133,7 +138,7 @@ pub(crate) unsafe fn read_sockaddr_os(storage: *const c::sockaddr, len: usize) - match read_ss_family(storage).into() { c::AF_INET => { assert!(len >= size_of::()); - let decode = *storage.cast::(); + let decode = &*storage.cast::(); SocketAddrAny::V4(SocketAddrV4::new( Ipv4Addr::from(u32::from_be(decode.sin_addr.s_addr)), u16::from_be(decode.sin_port), @@ -141,7 +146,7 @@ pub(crate) unsafe fn read_sockaddr_os(storage: *const c::sockaddr, len: usize) - } c::AF_INET6 => { assert!(len >= size_of::()); - let decode = *storage.cast::(); + let decode = &*storage.cast::(); SocketAddrAny::V6(SocketAddrV6::new( Ipv6Addr::from(decode.sin6_addr.in6_u.u6_addr8), u16::from_be(decode.sin6_port), @@ -154,19 +159,24 @@ pub(crate) unsafe fn read_sockaddr_os(storage: *const c::sockaddr, len: usize) - if len == offsetof_sun_path { SocketAddrAny::Unix(SocketAddrUnix::new(&[][..]).unwrap()) } else { - let decode = *storage.cast::(); - assert_eq!( - decode.sun_path[len - 1 - offsetof_sun_path], - b'\0' as c::c_char - ); + let decode = &*storage.cast::(); + + // On Linux check for Linux's [abstract namespace]. + // + // [abstract namespace]: https://man7.org/linux/man-pages/man7/unix.7.html + if decode.sun_path[0] == 0 { + return SocketAddrAny::Unix( + SocketAddrUnix::new_abstract_name( + &decode.sun_path[1..len - offsetof_sun_path], + ) + .unwrap(), + ); + } + + // Otherwise we expect a NUL-terminated filesystem path. + assert_eq!(decode.sun_path[len - 1 - offsetof_sun_path], 0); SocketAddrAny::Unix( - SocketAddrUnix::new( - decode.sun_path[..len - 1 - offsetof_sun_path] - .iter() - .map(|c| *c as u8) - .collect::>(), - ) - .unwrap(), + SocketAddrUnix::new(&decode.sun_path[..len - 1 - offsetof_sun_path]).unwrap(), ) } } diff --git a/vendor/rustix/src/backend/linux_raw/net/send_recv.rs b/vendor/rustix/src/backend/linux_raw/net/send_recv.rs index fb82eaef3..6e39a13aa 100644 --- a/vendor/rustix/src/backend/linux_raw/net/send_recv.rs +++ b/vendor/rustix/src/backend/linux_raw/net/send_recv.rs @@ -1,4 +1,4 @@ -use super::super::c; +use crate::backend::c; use bitflags::bitflags; bitflags! { @@ -6,6 +6,8 @@ bitflags! { /// /// [`send`]: crate::net::send /// [`sendto`]: crate::net::sendto + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct SendFlags: u32 { /// `MSG_CONFIRM` const CONFIRM = c::MSG_CONFIRM; @@ -29,6 +31,8 @@ bitflags! { /// /// [`recv`]: crate::net::recv /// [`recvfrom`]: crate::net::recvfrom + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct RecvFlags: u32 { /// `MSG_CMSG_CLOEXEC` const CMSG_CLOEXEC = c::MSG_CMSG_CLOEXEC; diff --git a/vendor/rustix/src/backend/linux_raw/net/syscalls.rs b/vendor/rustix/src/backend/linux_raw/net/syscalls.rs index 7fe9f0ef4..dca331783 100644 --- a/vendor/rustix/src/backend/linux_raw/net/syscalls.rs +++ b/vendor/rustix/src/backend/linux_raw/net/syscalls.rs @@ -6,29 +6,33 @@ #![allow(unsafe_code)] #![allow(clippy::undocumented_unsafe_blocks)] -use super::super::c; -use super::super::conv::{ - by_mut, by_ref, c_int, c_uint, ret, ret_owned_fd, ret_usize, size_of, slice, slice_mut, - socklen_t, zero, +use super::msghdr::{ + with_noaddr_msghdr, with_recv_msghdr, with_unix_msghdr, with_v4_msghdr, with_v6_msghdr, }; use super::read_sockaddr::{initialize_family_to_unspec, maybe_read_sockaddr_os, read_sockaddr_os}; use super::send_recv::{RecvFlags, SendFlags}; -use super::types::{AddressFamily, Protocol, Shutdown, SocketFlags, SocketType}; use super::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6}; +use crate::backend::c; +use crate::backend::conv::{ + by_mut, by_ref, c_int, c_uint, ret, ret_owned_fd, ret_usize, size_of, slice, slice_mut, + socklen_t, zero, +}; use crate::fd::{BorrowedFd, OwnedFd}; -use crate::io; -use crate::net::{SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6}; +use crate::io::{self, IoSlice, IoSliceMut}; +use crate::net::{ + AddressFamily, Protocol, RecvAncillaryBuffer, RecvMsgReturn, SendAncillaryBuffer, Shutdown, + SocketAddrAny, SocketAddrUnix, SocketAddrV4, SocketAddrV6, SocketFlags, SocketType, +}; use c::{sockaddr, sockaddr_in, sockaddr_in6, socklen_t}; -use core::convert::TryInto; use core::mem::MaybeUninit; #[cfg(target_arch = "x86")] use { - super::super::conv::{slice_just_addr, x86_sys}, - super::super::reg::{ArgReg, SocketArg}, - linux_raw_sys::general::{ + crate::backend::conv::{slice_just_addr, x86_sys}, + crate::backend::reg::{ArgReg, SocketArg}, + linux_raw_sys::net::{ SYS_ACCEPT, SYS_ACCEPT4, SYS_BIND, SYS_CONNECT, SYS_GETPEERNAME, SYS_GETSOCKNAME, - SYS_GETSOCKOPT, SYS_LISTEN, SYS_RECV, SYS_RECVFROM, SYS_SEND, SYS_SENDTO, SYS_SETSOCKOPT, - SYS_SHUTDOWN, SYS_SOCKET, SYS_SOCKETPAIR, + SYS_GETSOCKOPT, SYS_LISTEN, SYS_RECV, SYS_RECVFROM, SYS_RECVMSG, SYS_SEND, SYS_SENDMSG, + SYS_SENDTO, SYS_SETSOCKOPT, SYS_SHUTDOWN, SYS_SOCKET, SYS_SOCKETPAIR, }, }; @@ -36,7 +40,7 @@ use { pub(crate) fn socket( family: AddressFamily, type_: SocketType, - protocol: Protocol, + protocol: Option, ) -> io::Result { #[cfg(not(target_arch = "x86"))] unsafe { @@ -61,7 +65,7 @@ pub(crate) fn socket_with( family: AddressFamily, type_: SocketType, flags: SocketFlags, - protocol: Protocol, + protocol: Option, ) -> io::Result { #[cfg(not(target_arch = "x86"))] unsafe { @@ -91,7 +95,7 @@ pub(crate) fn socketpair( family: AddressFamily, type_: SocketType, flags: SocketFlags, - protocol: Protocol, + protocol: Option, ) -> io::Result<(OwnedFd, OwnedFd)> { #[cfg(not(target_arch = "x86"))] unsafe { @@ -239,6 +243,166 @@ pub(crate) fn acceptfrom_with( } } +#[inline] +pub(crate) fn recvmsg( + sockfd: BorrowedFd<'_>, + iov: &mut [IoSliceMut<'_>], + control: &mut RecvAncillaryBuffer<'_>, + msg_flags: RecvFlags, +) -> io::Result { + let mut storage = MaybeUninit::::uninit(); + + with_recv_msghdr(&mut storage, iov, control, |msghdr| { + #[cfg(not(target_arch = "x86"))] + let result = + unsafe { ret_usize(syscall!(__NR_recvmsg, sockfd, by_mut(msghdr), msg_flags)) }; + + #[cfg(target_arch = "x86")] + let result = unsafe { + ret_usize(syscall!( + __NR_socketcall, + x86_sys(SYS_RECVMSG), + slice_just_addr::, _>(&[ + sockfd.into(), + by_mut(msghdr), + msg_flags.into(), + ]) + )) + }; + + result.map(|bytes| { + // Get the address of the sender, if any. + let addr = + unsafe { maybe_read_sockaddr_os(msghdr.msg_name as _, msghdr.msg_namelen as _) }; + + RecvMsgReturn { + bytes, + address: addr, + flags: RecvFlags::from_bits_retain(msghdr.msg_flags), + } + }) + }) +} + +#[inline] +pub(crate) fn sendmsg( + sockfd: BorrowedFd<'_>, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + msg_flags: SendFlags, +) -> io::Result { + with_noaddr_msghdr(iov, control, |msghdr| { + #[cfg(not(target_arch = "x86"))] + let result = + unsafe { ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) }; + + #[cfg(target_arch = "x86")] + let result = unsafe { + ret_usize(syscall!( + __NR_socketcall, + x86_sys(SYS_SENDMSG), + slice_just_addr::, _>(&[ + sockfd.into(), + by_ref(&msghdr), + msg_flags.into() + ]) + )) + }; + + result + }) +} + +#[inline] +pub(crate) fn sendmsg_v4( + sockfd: BorrowedFd<'_>, + addr: &SocketAddrV4, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + msg_flags: SendFlags, +) -> io::Result { + with_v4_msghdr(addr, iov, control, |msghdr| { + #[cfg(not(target_arch = "x86"))] + let result = + unsafe { ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) }; + + #[cfg(target_arch = "x86")] + let result = unsafe { + ret_usize(syscall!( + __NR_socketcall, + x86_sys(SYS_SENDMSG), + slice_just_addr::, _>(&[ + sockfd.into(), + by_ref(&msghdr), + msg_flags.into(), + ]) + )) + }; + + result + }) +} + +#[inline] +pub(crate) fn sendmsg_v6( + sockfd: BorrowedFd<'_>, + addr: &SocketAddrV6, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + msg_flags: SendFlags, +) -> io::Result { + with_v6_msghdr(addr, iov, control, |msghdr| { + #[cfg(not(target_arch = "x86"))] + let result = + unsafe { ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) }; + + #[cfg(target_arch = "x86")] + let result = unsafe { + ret_usize(syscall!( + __NR_socketcall, + x86_sys(SYS_SENDMSG), + slice_just_addr::, _>(&[ + sockfd.into(), + by_ref(&msghdr), + msg_flags.into() + ]) + )) + }; + + result + }) +} + +#[inline] +pub(crate) fn sendmsg_unix( + sockfd: BorrowedFd<'_>, + addr: &SocketAddrUnix, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + msg_flags: SendFlags, +) -> io::Result { + with_unix_msghdr(addr, iov, control, |msghdr| { + #[cfg(not(target_arch = "x86"))] + let result = + unsafe { ret_usize(syscall!(__NR_sendmsg, sockfd, by_ref(&msghdr), msg_flags)) }; + + #[cfg(target_arch = "x86")] + let result = unsafe { + ret_usize(syscall!( + __NR_socketcall, + x86_sys(SYS_SENDMSG), + slice_just_addr::, _>(&[ + sockfd.into(), + by_ref(&msghdr), + msg_flags.into() + ]) + )) + }; + + result + }) +} + #[inline] pub(crate) fn shutdown(fd: BorrowedFd<'_>, how: Shutdown) -> io::Result<()> { #[cfg(not(target_arch = "x86"))] @@ -754,13 +918,9 @@ pub(crate) mod sockopt { use crate::net::sockopt::Timeout; use crate::net::{Ipv4Addr, Ipv6Addr, SocketType}; use c::{SO_RCVTIMEO_NEW, SO_RCVTIMEO_OLD, SO_SNDTIMEO_NEW, SO_SNDTIMEO_OLD}; - use core::convert::TryInto; use core::time::Duration; use linux_raw_sys::general::{__kernel_timespec, timeval}; - // TODO: With Rust 1.53 we can use `Duration::ZERO` instead. - const DURATION_ZERO: Duration = Duration::from_secs(0); - #[inline] fn getsockopt(fd: BorrowedFd<'_>, level: u32, optname: u32) -> io::Result { use super::*; @@ -910,12 +1070,7 @@ pub(crate) mod sockopt { #[inline] pub(crate) fn get_socket_linger(fd: BorrowedFd<'_>) -> io::Result> { let linger: c::linger = getsockopt(fd, c::SOL_SOCKET as _, c::SO_LINGER)?; - // TODO: With Rust 1.50, this could use `.then`. - Ok(if linger.l_onoff != 0 { - Some(Duration::from_secs(linger.l_linger as u64)) - } else { - None - }) + Ok((linger.l_onoff != 0).then(|| Duration::from_secs(linger.l_linger as u64))) } #[inline] @@ -1020,7 +1175,7 @@ pub(crate) mod sockopt { fn duration_to_linux(timeout: Option) -> io::Result<__kernel_timespec> { Ok(match timeout { Some(timeout) => { - if timeout == DURATION_ZERO { + if timeout == Duration::ZERO { return Err(io::Errno::INVAL); } let mut timeout = __kernel_timespec { @@ -1043,7 +1198,7 @@ pub(crate) mod sockopt { fn duration_to_linux_old(timeout: Option) -> io::Result { Ok(match timeout { Some(timeout) => { - if timeout == DURATION_ZERO { + if timeout == Duration::ZERO { return Err(io::Errno::INVAL); } @@ -1186,14 +1341,14 @@ pub(crate) mod sockopt { setsockopt( fd, c::IPPROTO_IP as _, - c::IPV6_MULTICAST_LOOP, + c::IPV6_MULTICAST_HOPS, multicast_hops, ) } #[inline] pub(crate) fn get_ipv6_multicast_hops(fd: BorrowedFd<'_>) -> io::Result { - getsockopt(fd, c::IPPROTO_IP as _, c::IPV6_MULTICAST_LOOP) + getsockopt(fd, c::IPPROTO_IP as _, c::IPV6_MULTICAST_HOPS) } #[inline] @@ -1244,7 +1399,7 @@ pub(crate) mod sockopt { #[inline] pub(crate) fn set_ipv6_unicast_hops(fd: BorrowedFd<'_>, hops: Option) -> io::Result<()> { let hops = match hops { - Some(hops) => hops as c::c_int, + Some(hops) => hops.into(), None => -1, }; setsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_UNICAST_HOPS, hops) @@ -1286,7 +1441,7 @@ pub(crate) mod sockopt { #[inline] fn to_ipv6mr_multiaddr(multiaddr: &Ipv6Addr) -> c::in6_addr { c::in6_addr { - in6_u: linux_raw_sys::general::in6_addr__bindgen_ty_1 { + in6_u: linux_raw_sys::net::in6_addr__bindgen_ty_1 { u6_addr8: multiaddr.octets(), }, } diff --git a/vendor/rustix/src/backend/linux_raw/net/types.rs b/vendor/rustix/src/backend/linux_raw/net/types.rs deleted file mode 100644 index 3f0b571a5..000000000 --- a/vendor/rustix/src/backend/linux_raw/net/types.rs +++ /dev/null @@ -1,275 +0,0 @@ -use super::super::c; -use bitflags::bitflags; - -/// A type for holding raw integer socket types. -#[doc(hidden)] -pub type RawSocketType = u32; - -/// `SOCK_*` constants for use with [`socket`]. -/// -/// [`socket`]: crate::net::socket -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[repr(transparent)] -pub struct SocketType(pub(crate) RawSocketType); - -#[rustfmt::skip] -impl SocketType { - /// `SOCK_STREAM` - pub const STREAM: Self = Self(c::SOCK_STREAM); - - /// `SOCK_DGRAM` - pub const DGRAM: Self = Self(c::SOCK_DGRAM); - - /// `SOCK_SEQPACKET` - pub const SEQPACKET: Self = Self(c::SOCK_SEQPACKET); - - /// `SOCK_RAW` - pub const RAW: Self = Self(c::SOCK_RAW); - - /// `SOCK_RDM` - pub const RDM: Self = Self(c::SOCK_RDM); - - /// Constructs a `SocketType` from a raw integer. - #[inline] - pub const fn from_raw(raw: RawSocketType) -> Self { - Self(raw) - } - - /// Returns the raw integer for this `SocketType`. - #[inline] - pub const fn as_raw(self) -> RawSocketType { - self.0 - } -} - -/// A type for holding raw integer address families. -#[doc(hidden)] -pub type RawAddressFamily = c::sa_family_t; - -/// `AF_*` constants. -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[repr(transparent)] -pub struct AddressFamily(pub(crate) RawAddressFamily); - -#[rustfmt::skip] -#[allow(non_upper_case_globals)] -impl AddressFamily { - /// `AF_UNSPEC` - pub const UNSPEC: Self = Self(c::AF_UNSPEC as _); - /// `AF_INET` - pub const INET: Self = Self(c::AF_INET as _); - /// `AF_INET6` - pub const INET6: Self = Self(c::AF_INET6 as _); - /// `AF_NETLINK` - pub const NETLINK: Self = Self(c::AF_NETLINK as _); - /// `AF_UNIX`, aka `AF_LOCAL` - #[doc(alias = "LOCAL")] - pub const UNIX: Self = Self(c::AF_UNIX as _); - /// `AF_AX25` - pub const AX25: Self = Self(c::AF_AX25 as _); - /// `AF_IPX` - pub const IPX: Self = Self(c::AF_IPX as _); - /// `AF_APPLETALK` - pub const APPLETALK: Self = Self(c::AF_APPLETALK as _); - /// `AF_NETROM` - pub const NETROM: Self = Self(c::AF_NETROM as _); - /// `AF_BRIDGE` - pub const BRIDGE: Self = Self(c::AF_BRIDGE as _); - /// `AF_ATMPVC` - pub const ATMPVC: Self = Self(c::AF_ATMPVC as _); - /// `AF_X25` - pub const X25: Self = Self(c::AF_X25 as _); - /// `AF_ROSE` - pub const ROSE: Self = Self(c::AF_ROSE as _); - /// `AF_DECnet` - pub const DECnet: Self = Self(c::AF_DECnet as _); - /// `AF_NETBEUI` - pub const NETBEUI: Self = Self(c::AF_NETBEUI as _); - /// `AF_SECURITY` - pub const SECURITY: Self = Self(c::AF_SECURITY as _); - /// `AF_KEY` - pub const KEY: Self = Self(c::AF_KEY as _); - /// `AF_PACKET` - pub const PACKET: Self = Self(c::AF_PACKET as _); - /// `AF_ASH` - pub const ASH: Self = Self(c::AF_ASH as _); - /// `AF_ECONET` - pub const ECONET: Self = Self(c::AF_ECONET as _); - /// `AF_ATMSVC` - pub const ATMSVC: Self = Self(c::AF_ATMSVC as _); - /// `AF_RDS` - pub const RDS: Self = Self(c::AF_RDS as _); - /// `AF_SNA` - pub const SNA: Self = Self(c::AF_SNA as _); - /// `AF_IRDA` - pub const IRDA: Self = Self(c::AF_IRDA as _); - /// `AF_PPPOX` - pub const PPPOX: Self = Self(c::AF_PPPOX as _); - /// `AF_WANPIPE` - pub const WANPIPE: Self = Self(c::AF_WANPIPE as _); - /// `AF_LLC` - pub const LLC: Self = Self(c::AF_LLC as _); - /// `AF_CAN` - pub const CAN: Self = Self(c::AF_CAN as _); - /// `AF_TIPC` - pub const TIPC: Self = Self(c::AF_TIPC as _); - /// `AF_BLUETOOTH` - pub const BLUETOOTH: Self = Self(c::AF_BLUETOOTH as _); - /// `AF_IUCV` - pub const IUCV: Self = Self(c::AF_IUCV as _); - /// `AF_RXRPC` - pub const RXRPC: Self = Self(c::AF_RXRPC as _); - /// `AF_ISDN` - pub const ISDN: Self = Self(c::AF_ISDN as _); - /// `AF_PHONET` - pub const PHONET: Self = Self(c::AF_PHONET as _); - /// `AF_IEEE802154` - pub const IEEE802154: Self = Self(c::AF_IEEE802154 as _); - - /// Constructs a `AddressFamily` from a raw integer. - #[inline] - pub const fn from_raw(raw: RawAddressFamily) -> Self { - Self(raw) - } - - /// Returns the raw integer for this `AddressFamily`. - #[inline] - pub const fn as_raw(self) -> RawAddressFamily { - self.0 - } -} - -/// A type for holding raw integer protocols. -#[doc(hidden)] -pub type RawProtocol = u32; - -/// `IPPROTO_*` constants for use with [`socket`] and [`socket_with`]. -/// -/// [`socket`]: crate::net::socket -/// [`socket_with`]: crate::net::socket_with -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[repr(transparent)] -pub struct Protocol(pub(crate) RawProtocol); - -#[rustfmt::skip] -impl Protocol { - /// `IPPROTO_IP` - pub const IP: Self = Self(c::IPPROTO_IP as _); - /// `IPPROTO_ICMP` - pub const ICMP: Self = Self(c::IPPROTO_ICMP as _); - /// `IPPROTO_IGMP` - pub const IGMP: Self = Self(c::IPPROTO_IGMP as _); - /// `IPPROTO_IPIP` - pub const IPIP: Self = Self(c::IPPROTO_IPIP as _); - /// `IPPROTO_TCP` - pub const TCP: Self = Self(c::IPPROTO_TCP as _); - /// `IPPROTO_EGP` - pub const EGP: Self = Self(c::IPPROTO_EGP as _); - /// `IPPROTO_PUP` - pub const PUP: Self = Self(c::IPPROTO_PUP as _); - /// `IPPROTO_UDP` - pub const UDP: Self = Self(c::IPPROTO_UDP as _); - /// `IPPROTO_IDP` - pub const IDP: Self = Self(c::IPPROTO_IDP as _); - /// `IPPROTO_TP` - pub const TP: Self = Self(c::IPPROTO_TP as _); - /// `IPPROTO_DCCP` - pub const DCCP: Self = Self(c::IPPROTO_DCCP as _); - /// `IPPROTO_IPV6` - pub const IPV6: Self = Self(c::IPPROTO_IPV6 as _); - /// `IPPROTO_RSVP` - pub const RSVP: Self = Self(c::IPPROTO_RSVP as _); - /// `IPPROTO_GRE` - pub const GRE: Self = Self(c::IPPROTO_GRE as _); - /// `IPPROTO_ESP` - pub const ESP: Self = Self(c::IPPROTO_ESP as _); - /// `IPPROTO_AH` - pub const AH: Self = Self(c::IPPROTO_AH as _); - /// `IPPROTO_MTP` - pub const MTP: Self = Self(c::IPPROTO_MTP as _); - /// `IPPROTO_BEETPH` - pub const BEETPH: Self = Self(c::IPPROTO_BEETPH as _); - /// `IPPROTO_ENCAP` - pub const ENCAP: Self = Self(c::IPPROTO_ENCAP as _); - /// `IPPROTO_PIM` - pub const PIM: Self = Self(c::IPPROTO_PIM as _); - /// `IPPROTO_COMP` - pub const COMP: Self = Self(c::IPPROTO_COMP as _); - /// `IPPROTO_SCTP` - pub const SCTP: Self = Self(c::IPPROTO_SCTP as _); - /// `IPPROTO_UDPLITE` - pub const UDPLITE: Self = Self(c::IPPROTO_UDPLITE as _); - /// `IPPROTO_MPLS` - pub const MPLS: Self = Self(c::IPPROTO_MPLS as _); - /// `IPPROTO_ETHERNET` - pub const ETHERNET: Self = Self(c::IPPROTO_ETHERNET as _); - /// `IPPROTO_RAW` - pub const RAW: Self = Self(c::IPPROTO_RAW as _); - /// `IPPROTO_MPTCP` - pub const MPTCP: Self = Self(c::IPPROTO_MPTCP as _); - /// `IPPROTO_FRAGMENT` - pub const FRAGMENT: Self = Self(c::IPPROTO_FRAGMENT as _); - /// `IPPROTO_ICMPV6` - pub const ICMPV6: Self = Self(c::IPPROTO_ICMPV6 as _); - /// `IPPROTO_MH` - pub const MH: Self = Self(c::IPPROTO_MH as _); - /// `IPPROTO_ROUTING` - pub const ROUTING: Self = Self(c::IPPROTO_ROUTING as _); - - /// Constructs a `Protocol` from a raw integer. - #[inline] - pub const fn from_raw(raw: RawProtocol) -> Self { - Self(raw) - } - - /// Returns the raw integer for this `Protocol`. - #[inline] - pub const fn as_raw(self) -> RawProtocol { - self.0 - } -} - -/// `SHUT_*` constants for use with [`shutdown`]. -/// -/// [`shutdown`]: crate::net::shutdown -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[repr(u32)] -pub enum Shutdown { - /// `SHUT_RD`—Disable further read operations. - Read = c::SHUT_RD, - /// `SHUT_WR`—Disable further write operations. - Write = c::SHUT_WR, - /// `SHUT_RDWR`—Disable further read and write operations. - ReadWrite = c::SHUT_RDWR, -} - -bitflags! { - /// `SOCK_*` constants for use with [`socket_with`], [`accept_with`] and - /// [`acceptfrom_with`]. - /// - /// [`socket_with`]: crate::net::socket_with - /// [`accept_with`]: crate::net::accept_with - /// [`acceptfrom_with`]: crate::net::acceptfrom_with - pub struct SocketFlags: c::c_uint { - /// `SOCK_NONBLOCK` - const NONBLOCK = c::O_NONBLOCK; - - /// `SOCK_CLOEXEC` - const CLOEXEC = c::O_CLOEXEC; - } -} - -/// Timeout identifier for use with [`set_socket_timeout`] and -/// [`get_socket_timeout`]. -/// -/// [`set_socket_timeout`]: crate::net::sockopt::set_socket_timeout. -/// [`get_socket_timeout`]: crate::net::sockopt::get_socket_timeout. -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[repr(u32)] -pub enum Timeout { - /// `SO_RCVTIMEO`—Timeout for receiving. - Recv = c::SO_RCVTIMEO_NEW, - - /// `SO_SNDTIMEO`—Timeout for sending. - Send = c::SO_SNDTIMEO_NEW, -} diff --git a/vendor/rustix/src/backend/linux_raw/net/write_sockaddr.rs b/vendor/rustix/src/backend/linux_raw/net/write_sockaddr.rs index 17abd96a0..28da05cd0 100644 --- a/vendor/rustix/src/backend/linux_raw/net/write_sockaddr.rs +++ b/vendor/rustix/src/backend/linux_raw/net/write_sockaddr.rs @@ -2,7 +2,7 @@ //! we can interpret the rest of a `sockaddr` produced by the kernel. #![allow(unsafe_code)] -use super::super::c; +use crate::backend::c; use crate::net::{SocketAddrAny, SocketAddrStorage, SocketAddrUnix, SocketAddrV4, SocketAddrV6}; use core::mem::size_of; @@ -40,7 +40,7 @@ pub(crate) unsafe fn encode_sockaddr_v6(v6: &SocketAddrV6) -> c::sockaddr_in6 { sin6_port: u16::to_be(v6.port()), sin6_flowinfo: u32::to_be(v6.flowinfo()), sin6_addr: c::in6_addr { - in6_u: linux_raw_sys::general::in6_addr__bindgen_ty_1 { + in6_u: linux_raw_sys::net::in6_addr__bindgen_ty_1 { u6_addr8: v6.ip().octets(), }, }, diff --git a/vendor/rustix/src/backend/linux_raw/param/auxv.rs b/vendor/rustix/src/backend/linux_raw/param/auxv.rs index 741a0564f..bf8935a0d 100644 --- a/vendor/rustix/src/backend/linux_raw/param/auxv.rs +++ b/vendor/rustix/src/backend/linux_raw/param/auxv.rs @@ -5,12 +5,11 @@ //! This uses raw pointers to locate and read the kernel-provided auxv array. #![allow(unsafe_code)] -use super::super::c; -use super::super::elf::*; +use crate::backend::c; +use crate::backend::elf::*; use crate::fd::OwnedFd; #[cfg(feature = "param")] use crate::ffi::CStr; -#[cfg(not(target_vendor = "mustang"))] use crate::fs::{Mode, OFlags}; use crate::utils::{as_ptr, check_raw_pointer}; use alloc::vec::Vec; @@ -32,7 +31,7 @@ pub(crate) fn page_size() -> usize { let mut page_size = PAGE_SIZE.load(Relaxed); if page_size == 0 { - init_from_proc_self_auxv(); + init_auxv(); page_size = PAGE_SIZE.load(Relaxed); } @@ -45,7 +44,7 @@ pub(crate) fn clock_ticks_per_second() -> u64 { let mut ticks = CLOCK_TICKS_PER_SECOND.load(Relaxed); if ticks == 0 { - init_from_proc_self_auxv(); + init_auxv(); ticks = CLOCK_TICKS_PER_SECOND.load(Relaxed); } @@ -59,7 +58,7 @@ pub(crate) fn linux_hwcap() -> (usize, usize) { let mut hwcap2 = HWCAP2.load(Relaxed); if hwcap == 0 || hwcap2 == 0 { - init_from_proc_self_auxv(); + init_auxv(); hwcap = HWCAP.load(Relaxed); hwcap2 = HWCAP2.load(Relaxed); } @@ -73,7 +72,7 @@ pub(crate) fn linux_execfn() -> &'static CStr { let mut execfn = EXECFN.load(Relaxed); if execfn.is_null() { - init_from_proc_self_auxv(); + init_auxv(); execfn = EXECFN.load(Relaxed); } @@ -89,7 +88,7 @@ pub(crate) fn exe_phdrs() -> (*const c::c_void, usize) { let mut phnum = PHNUM.load(Relaxed); if phdr.is_null() || phnum == 0 { - init_from_proc_self_auxv(); + init_auxv(); phdr = PHDR.load(Relaxed); phnum = PHNUM.load(Relaxed); } @@ -114,7 +113,7 @@ pub(in super::super) fn sysinfo_ehdr() -> *const Elf_Ehdr { let mut ehdr = SYSINFO_EHDR.load(Relaxed); if ehdr.is_null() { - init_from_proc_self_auxv(); + init_auxv(); ehdr = SYSINFO_EHDR.load(Relaxed); } @@ -130,29 +129,61 @@ static PHDR: AtomicPtr = AtomicPtr::new(null_mut()); static PHNUM: AtomicUsize = AtomicUsize::new(0); static EXECFN: AtomicPtr = AtomicPtr::new(null_mut()); -/// On non-Mustang platforms, we read the aux vector from /proc/self/auxv. -#[cfg(not(target_vendor = "mustang"))] -fn init_from_proc_self_auxv() { +fn pr_get_auxv() -> crate::io::Result> { + use super::super::conv::{c_int, pass_usize, ret_usize}; + const PR_GET_AUXV: c::c_int = 0x41555856; + let mut buffer = alloc::vec![0u8; 512]; + let len = unsafe { + ret_usize(syscall_always_asm!( + __NR_prctl, + c_int(PR_GET_AUXV), + buffer.as_ptr(), + pass_usize(buffer.len()) + ))? + }; + if len <= buffer.len() { + buffer.truncate(len); + return Ok(buffer); + } + buffer.resize(len, 0); + let len = unsafe { + ret_usize(syscall_always_asm!( + __NR_prctl, + c_int(PR_GET_AUXV), + buffer.as_ptr(), + pass_usize(buffer.len()) + ))? + }; + assert_eq!(len, buffer.len()); + return Ok(buffer); +} + +/// On non-Mustang platforms, we read the aux vector via the `prctl` +/// `PR_GET_AUXV`, with a fallback to /proc/self/auxv for kernels that don't +/// support `PR_GET_AUXV`. +fn init_auxv() { + match pr_get_auxv() { + Ok(buffer) => { + // SAFETY: We assume the kernel returns a valid auxv. + unsafe { + init_from_auxp(buffer.as_ptr().cast()); + } + return; + } + Err(_) => { + // Fall back to /proc/self/auxv on error. + } + } + // Open "/proc/self/auxv", either because we trust "/proc", or because // we're running inside QEMU and `proc_self_auxv`'s extra checking foils // QEMU's emulation so we need to do a plain open to get the right // auxv records. - let file = crate::fs::openat( - crate::fs::cwd(), - "/proc/self/auxv", - OFlags::empty(), - Mode::empty(), - ) - .unwrap(); + let file = crate::fs::open("/proc/self/auxv", OFlags::RDONLY, Mode::empty()).unwrap(); let _ = init_from_auxv_file(file); } -#[cfg(target_vendor = "mustang")] -fn init_from_proc_self_auxv() { - panic!("mustang should have initialized the auxv values"); -} - /// Process auxv entries from the open file `auxv`. fn init_from_auxv_file(auxv: OwnedFd) -> Option<()> { let mut buffer = Vec::::with_capacity(512); @@ -276,7 +307,7 @@ unsafe fn check_vdso_base(base: *const Elf_Ehdr) -> Option> { // as an arbitrary system call which writes to a buffer and fails with // `EFAULT` if the buffer is not writable. { - use super::super::conv::{c_uint, ret}; + use crate::backend::conv::{c_uint, ret}; if ret(syscall!( __NR_clock_getres, c_uint(linux_raw_sys::general::CLOCK_MONOTONIC), diff --git a/vendor/rustix/src/backend/linux_raw/param/libc_auxv.rs b/vendor/rustix/src/backend/linux_raw/param/libc_auxv.rs index a8e291ff6..d05a87e53 100644 --- a/vendor/rustix/src/backend/linux_raw/param/libc_auxv.rs +++ b/vendor/rustix/src/backend/linux_raw/param/libc_auxv.rs @@ -5,59 +5,124 @@ //! This uses raw pointers to locate and read the kernel-provided auxv array. #![allow(unsafe_code)] -use super::super::elf::*; +use crate::backend::c; +use crate::backend::elf::*; #[cfg(feature = "param")] use crate::ffi::CStr; +#[cfg(not(feature = "runtime"))] +use core::ptr::null; #[cfg(feature = "runtime")] use core::slice; -// `getauxval` wasn't supported in glibc until 2.16. -weak!(fn getauxval(libc::c_ulong) -> *mut libc::c_void); +// `getauxval` wasn't supported in glibc until 2.16. Also this lets us use +// `*mut` as the return type to preserve strict provenance. +#[cfg(not(feature = "runtime"))] +weak!(fn getauxval(c::c_ulong) -> *mut c::c_void); + +// With the "runtime" feature, go ahead and depend on `getauxval` existing +// so that we never fail. +#[cfg(feature = "runtime")] +extern "C" { + fn getauxval(type_: c::c_ulong) -> *mut c::c_void; +} + +const AT_PHDR: c::c_ulong = 3; +const AT_PHNUM: c::c_ulong = 5; +const AT_HWCAP: c::c_ulong = 16; +const AT_HWCAP2: c::c_ulong = 26; +const AT_EXECFN: c::c_ulong = 31; +const AT_SYSINFO_EHDR: c::c_ulong = 33; + +// Declare `sysconf` ourselves so that we don't depend on all of libc +// just for this. +extern "C" { + fn sysconf(name: c::c_int) -> c::c_long; +} + +#[cfg(target_os = "android")] +const _SC_PAGESIZE: c::c_int = 39; +#[cfg(target_os = "emscripten")] +const _SC_PAGESIZE: c::c_int = 30; +#[cfg(target_os = "linux")] +const _SC_PAGESIZE: c::c_int = 30; +#[cfg(target_os = "android")] +const _SC_CLK_TCK: c::c_int = 6; +#[cfg(target_os = "emscripten")] +const _SC_CLK_TCK: c::c_int = 2; +#[cfg(target_os = "linux")] +const _SC_CLK_TCK: c::c_int = 2; + +#[test] +fn test_abi() { + assert_eq!(self::_SC_PAGESIZE, ::libc::_SC_PAGESIZE); + assert_eq!(self::_SC_CLK_TCK, ::libc::_SC_CLK_TCK); + assert_eq!(self::AT_PHDR, ::libc::AT_PHDR); + assert_eq!(self::AT_PHNUM, ::libc::AT_PHNUM); + assert_eq!(self::AT_HWCAP, ::libc::AT_HWCAP); + assert_eq!(self::AT_HWCAP2, ::libc::AT_HWCAP2); + assert_eq!(self::AT_EXECFN, ::libc::AT_EXECFN); + assert_eq!(self::AT_SYSINFO_EHDR, ::libc::AT_SYSINFO_EHDR); +} #[cfg(feature = "param")] #[inline] pub(crate) fn page_size() -> usize { - unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize } + unsafe { sysconf(_SC_PAGESIZE) as usize } } #[cfg(feature = "param")] #[inline] pub(crate) fn clock_ticks_per_second() -> u64 { - unsafe { libc::sysconf(libc::_SC_CLK_TCK) as u64 } + unsafe { sysconf(_SC_CLK_TCK) as u64 } } #[cfg(feature = "param")] #[inline] pub(crate) fn linux_hwcap() -> (usize, usize) { - if let Some(libc_getauxval) = getauxval.get() { - unsafe { - let hwcap = libc_getauxval(libc::AT_HWCAP) as usize; - let hwcap2 = libc_getauxval(libc::AT_HWCAP2) as usize; + #[cfg(not(feature = "runtime"))] + unsafe { + if let Some(libc_getauxval) = getauxval.get() { + let hwcap = libc_getauxval(AT_HWCAP) as usize; + let hwcap2 = libc_getauxval(AT_HWCAP2) as usize; (hwcap, hwcap2) + } else { + (0, 0) } - } else { - (0, 0) + } + + #[cfg(feature = "runtime")] + unsafe { + let hwcap = getauxval(AT_HWCAP) as usize; + let hwcap2 = getauxval(AT_HWCAP2) as usize; + (hwcap, hwcap2) } } #[cfg(feature = "param")] #[inline] pub(crate) fn linux_execfn() -> &'static CStr { - if let Some(libc_getauxval) = getauxval.get() { - unsafe { CStr::from_ptr(libc_getauxval(libc::AT_EXECFN).cast()) } - } else { - cstr!("") + #[cfg(not(feature = "runtime"))] + unsafe { + if let Some(libc_getauxval) = getauxval.get() { + CStr::from_ptr(libc_getauxval(AT_EXECFN).cast()) + } else { + cstr!("") + } + } + + #[cfg(feature = "runtime")] + unsafe { + CStr::from_ptr(getauxval(AT_EXECFN).cast()) } } #[cfg(feature = "runtime")] #[inline] -pub(crate) fn exe_phdrs() -> (*const libc::c_void, usize) { +pub(crate) fn exe_phdrs() -> (*const c::c_void, usize) { unsafe { - ( - libc::getauxval(libc::AT_PHDR) as *const libc::c_void, - libc::getauxval(libc::AT_PHNUM) as usize, - ) + let phdr = getauxval(AT_PHDR) as *const c::c_void; + let phnum = getauxval(AT_PHNUM) as usize; + (phdr, phnum) } } @@ -75,9 +140,17 @@ pub(in super::super) fn exe_phdrs_slice() -> &'static [Elf_Phdr] { /// so if we don't see it, this function returns a null pointer. #[inline] pub(in super::super) fn sysinfo_ehdr() -> *const Elf_Ehdr { - if let Some(libc_getauxval) = getauxval.get() { - unsafe { libc_getauxval(linux_raw_sys::general::AT_SYSINFO_EHDR.into()) as *const Elf_Ehdr } - } else { - core::ptr::null() + #[cfg(not(feature = "runtime"))] + unsafe { + if let Some(libc_getauxval) = getauxval.get() { + libc_getauxval(AT_SYSINFO_EHDR) as *const Elf_Ehdr + } else { + null() + } + } + + #[cfg(feature = "runtime")] + unsafe { + getauxval(AT_SYSINFO_EHDR) as *const Elf_Ehdr } } diff --git a/vendor/rustix/src/backend/linux_raw/param/mustang_auxv.rs b/vendor/rustix/src/backend/linux_raw/param/mustang_auxv.rs index 49cb1457c..f45a25faf 100644 --- a/vendor/rustix/src/backend/linux_raw/param/mustang_auxv.rs +++ b/vendor/rustix/src/backend/linux_raw/param/mustang_auxv.rs @@ -5,8 +5,8 @@ //! This uses raw pointers to locate and read the kernel-provided auxv array. #![allow(unsafe_code)] -use super::super::c; -use super::super::elf::*; +use crate::backend::c; +use crate::backend::elf::*; #[cfg(feature = "param")] use crate::ffi::CStr; use core::ffi::c_void; diff --git a/vendor/rustix/src/backend/linux_raw/pid/mod.rs b/vendor/rustix/src/backend/linux_raw/pid/mod.rs new file mode 100644 index 000000000..ef944f04d --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/pid/mod.rs @@ -0,0 +1 @@ +pub(crate) mod syscalls; diff --git a/vendor/rustix/src/backend/linux_raw/pid/syscalls.rs b/vendor/rustix/src/backend/linux_raw/pid/syscalls.rs new file mode 100644 index 000000000..f36bac048 --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/pid/syscalls.rs @@ -0,0 +1,18 @@ +//! linux_raw syscalls for PIDs +//! +//! # Safety +//! +//! See the `rustix::backend` module documentation for details. +#![allow(unsafe_code)] +#![allow(clippy::undocumented_unsafe_blocks)] + +use crate::backend::conv::ret_usize_infallible; +use crate::pid::{Pid, RawPid}; + +#[inline] +pub(crate) fn getpid() -> Pid { + unsafe { + let pid = ret_usize_infallible(syscall_readonly!(__NR_getpid)) as RawPid; + Pid::from_raw_unchecked(pid) + } +} diff --git a/vendor/rustix/src/backend/linux_raw/pipe/mod.rs b/vendor/rustix/src/backend/linux_raw/pipe/mod.rs new file mode 100644 index 000000000..1e0181a99 --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/pipe/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod syscalls; +pub(crate) mod types; diff --git a/vendor/rustix/src/backend/linux_raw/pipe/syscalls.rs b/vendor/rustix/src/backend/linux_raw/pipe/syscalls.rs new file mode 100644 index 000000000..ed121089d --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/pipe/syscalls.rs @@ -0,0 +1,132 @@ +//! linux_raw syscalls supporting `rustix::pipe`. +//! +//! # Safety +//! +//! See the `rustix::backend` module documentation for details. +#![allow(unsafe_code)] +#![allow(clippy::undocumented_unsafe_blocks)] + +use crate::backend::conv::{c_int, c_uint, opt_mut, pass_usize, ret, ret_usize, slice}; +use crate::backend::{c, MAX_IOV}; +use crate::fd::{BorrowedFd, OwnedFd}; +use crate::io; +use crate::pipe::{IoSliceRaw, PipeFlags, SpliceFlags}; +use core::cmp; +use core::mem::MaybeUninit; +use linux_raw_sys::general::{F_GETPIPE_SZ, F_SETPIPE_SZ}; + +#[inline] +pub(crate) fn pipe() -> io::Result<(OwnedFd, OwnedFd)> { + // aarch64 and risc64 omit `__NR_pipe`. On mips, `__NR_pipe` uses a special + // calling convention, but using it is not worth complicating our syscall + // wrapping infrastructure at this time. + #[cfg(any( + target_arch = "aarch64", + target_arch = "mips", + target_arch = "mips64", + target_arch = "riscv64", + ))] + { + pipe_with(PipeFlags::empty()) + } + #[cfg(not(any( + target_arch = "aarch64", + target_arch = "mips", + target_arch = "mips64", + target_arch = "riscv64", + )))] + unsafe { + let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit(); + ret(syscall!(__NR_pipe, &mut result))?; + let [p0, p1] = result.assume_init(); + Ok((p0, p1)) + } +} + +#[inline] +pub(crate) fn pipe_with(flags: PipeFlags) -> io::Result<(OwnedFd, OwnedFd)> { + unsafe { + let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit(); + ret(syscall!(__NR_pipe2, &mut result, flags))?; + let [p0, p1] = result.assume_init(); + Ok((p0, p1)) + } +} + +#[inline] +pub fn splice( + fd_in: BorrowedFd, + off_in: Option<&mut u64>, + fd_out: BorrowedFd, + off_out: Option<&mut u64>, + len: usize, + flags: SpliceFlags, +) -> io::Result { + unsafe { + ret_usize(syscall!( + __NR_splice, + fd_in, + opt_mut(off_in), + fd_out, + opt_mut(off_out), + pass_usize(len), + flags + )) + } +} + +#[inline] +pub unsafe fn vmsplice( + fd: BorrowedFd, + bufs: &[IoSliceRaw], + flags: SpliceFlags, +) -> io::Result { + let (bufs_addr, bufs_len) = slice(&bufs[..cmp::min(bufs.len(), MAX_IOV)]); + ret_usize(syscall!(__NR_vmsplice, fd, bufs_addr, bufs_len, flags)) +} + +#[inline] +pub fn tee( + fd_in: BorrowedFd, + fd_out: BorrowedFd, + len: usize, + flags: SpliceFlags, +) -> io::Result { + unsafe { ret_usize(syscall!(__NR_tee, fd_in, fd_out, pass_usize(len), flags)) } +} + +#[inline] +pub(crate) fn fcntl_getpipe_sz(fd: BorrowedFd<'_>) -> io::Result { + #[cfg(target_pointer_width = "32")] + unsafe { + ret_usize(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETPIPE_SZ))) + } + #[cfg(target_pointer_width = "64")] + unsafe { + ret_usize(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETPIPE_SZ))) + } +} + +#[inline] +pub(crate) fn fcntl_setpipe_sz(fd: BorrowedFd<'_>, size: usize) -> io::Result<()> { + let size: c::c_int = size.try_into().map_err(|_| io::Errno::PERM)?; + + #[cfg(target_pointer_width = "32")] + unsafe { + ret(syscall_readonly!( + __NR_fcntl64, + fd, + c_uint(F_SETPIPE_SZ), + c_int(size) + )) + } + #[cfg(target_pointer_width = "64")] + unsafe { + ret(syscall_readonly!( + __NR_fcntl, + fd, + c_uint(F_SETPIPE_SZ), + c_int(size) + )) + } +} diff --git a/vendor/rustix/src/backend/linux_raw/pipe/types.rs b/vendor/rustix/src/backend/linux_raw/pipe/types.rs new file mode 100644 index 000000000..90d2d79ab --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/pipe/types.rs @@ -0,0 +1,72 @@ +use crate::backend::c; +use bitflags::bitflags; +use core::marker::PhantomData; + +bitflags! { + /// `O_*` constants for use with [`pipe_with`]. + /// + /// [`pipe_with`]: crate::io::pipe_with + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct PipeFlags: c::c_uint { + /// `O_CLOEXEC` + const CLOEXEC = linux_raw_sys::general::O_CLOEXEC; + /// `O_DIRECT` + const DIRECT = linux_raw_sys::general::O_DIRECT; + /// `O_NONBLOCK` + const NONBLOCK = linux_raw_sys::general::O_NONBLOCK; + } +} + +bitflags! { + /// `SPLICE_F_*` constants for use with [`splice`] [`vmsplice`], and + /// [`tee`]. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct SpliceFlags: c::c_uint { + /// `SPLICE_F_MOVE` + const MOVE = linux_raw_sys::general::SPLICE_F_MOVE; + /// `SPLICE_F_NONBLOCK` + const NONBLOCK = linux_raw_sys::general::SPLICE_F_NONBLOCK; + /// `SPLICE_F_MORE` + const MORE = linux_raw_sys::general::SPLICE_F_MORE; + /// `SPLICE_F_GIFT` + const GIFT = linux_raw_sys::general::SPLICE_F_GIFT; + } +} + +/// A buffer type used with `vmsplice`. +/// +/// It is guaranteed to be ABI compatible with the iovec type on Unix platforms +/// and `WSABUF` on Windows. Unlike `IoSlice` and `IoSliceMut` it is +/// semantically like a raw pointer, and therefore can be shared or mutated as +/// needed. +#[repr(transparent)] +pub struct IoSliceRaw<'a> { + _buf: c::iovec, + _lifetime: PhantomData<&'a ()>, +} + +impl<'a> IoSliceRaw<'a> { + /// Creates a new `IoSlice` wrapping a byte slice. + pub fn from_slice(buf: &'a [u8]) -> Self { + IoSliceRaw { + _buf: c::iovec { + iov_base: (buf.as_ptr() as *mut u8).cast::(), + iov_len: buf.len() as _, + }, + _lifetime: PhantomData, + } + } + + /// Creates a new `IoSlice` wrapping a mutable byte slice. + pub fn from_slice_mut(buf: &'a mut [u8]) -> Self { + IoSliceRaw { + _buf: c::iovec { + iov_base: buf.as_mut_ptr().cast::(), + iov_len: buf.len() as _, + }, + _lifetime: PhantomData, + } + } +} diff --git a/vendor/rustix/src/backend/linux_raw/prctl/mod.rs b/vendor/rustix/src/backend/linux_raw/prctl/mod.rs new file mode 100644 index 000000000..ef944f04d --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/prctl/mod.rs @@ -0,0 +1 @@ +pub(crate) mod syscalls; diff --git a/vendor/rustix/src/backend/linux_raw/prctl/syscalls.rs b/vendor/rustix/src/backend/linux_raw/prctl/syscalls.rs new file mode 100644 index 000000000..193f4b7b4 --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/prctl/syscalls.rs @@ -0,0 +1,22 @@ +//! linux_raw syscalls supporting modules that use `prctl`. +//! +//! # Safety +//! +//! See the `rustix::backend` module documentation for details. +#![allow(unsafe_code)] +#![allow(clippy::undocumented_unsafe_blocks)] + +use crate::backend::c; +use crate::backend::conv::{c_int, ret_c_int}; +use crate::io; + +#[inline] +pub(crate) unsafe fn prctl( + option: c::c_int, + arg2: *mut c::c_void, + arg3: *mut c::c_void, + arg4: *mut c::c_void, + arg5: *mut c::c_void, +) -> io::Result { + ret_c_int(syscall!(__NR_prctl, c_int(option), arg2, arg3, arg4, arg5)) +} diff --git a/vendor/rustix/src/backend/linux_raw/process/cpu_set.rs b/vendor/rustix/src/backend/linux_raw/process/cpu_set.rs index fc81859d8..35146cfd2 100644 --- a/vendor/rustix/src/backend/linux_raw/process/cpu_set.rs +++ b/vendor/rustix/src/backend/linux_raw/process/cpu_set.rs @@ -14,10 +14,7 @@ pub(crate) fn CPU_SET(cpu: usize, cpuset: &mut RawCpuSet) { #[inline] pub(crate) fn CPU_ZERO(cpuset: &mut RawCpuSet) { - // TODO: With, Rust 1.50, use `cpuset.bits.fill(0)` instead. - for element in &mut cpuset.bits { - *element = 0; - } + cpuset.bits.fill(0) } #[inline] diff --git a/vendor/rustix/src/backend/linux_raw/process/syscalls.rs b/vendor/rustix/src/backend/linux_raw/process/syscalls.rs index 0eb6489e7..ac6e28901 100644 --- a/vendor/rustix/src/backend/linux_raw/process/syscalls.rs +++ b/vendor/rustix/src/backend/linux_raw/process/syscalls.rs @@ -6,34 +6,38 @@ #![allow(unsafe_code)] #![allow(clippy::undocumented_unsafe_blocks)] -use super::super::c; -use super::super::conv::{ - by_mut, by_ref, c_int, c_uint, negative_pid, pass_usize, ret, ret_c_int, ret_c_uint, - ret_infallible, ret_usize, ret_usize_infallible, size_of, slice, slice_just_addr, - slice_just_addr_mut, slice_mut, zero, +use super::types::RawCpuSet; +use crate::backend::c; +#[cfg(feature = "fs")] +use crate::backend::conv::slice_mut; +use crate::backend::conv::{ + by_mut, by_ref, c_int, c_uint, negative_pid, pass_usize, raw_fd, ret, ret_c_int, + ret_c_int_infallible, ret_c_uint, ret_infallible, ret_owned_fd, ret_usize, size_of, + slice_just_addr, slice_just_addr_mut, zero, }; -use super::types::{RawCpuSet, RawUname}; -use crate::backend::conv::ret_owned_fd; -use crate::fd::{AsRawFd, BorrowedFd, OwnedFd}; +use crate::fd::{AsRawFd, BorrowedFd, OwnedFd, RawFd}; +#[cfg(feature = "fs")] use crate::ffi::CStr; use crate::io; +use crate::pid::RawPid; use crate::process::{ - Cpuid, Gid, MembarrierCommand, MembarrierQuery, Pid, PidfdFlags, RawNonZeroPid, RawPid, - Resource, Rlimit, Signal, Sysinfo, Uid, WaitId, WaitOptions, WaitStatus, WaitidOptions, - WaitidStatus, + Cpuid, Gid, MembarrierCommand, MembarrierQuery, Pid, PidfdFlags, PidfdGetfdFlags, Resource, + Rlimit, Uid, WaitId, WaitOptions, WaitStatus, WaitidOptions, WaitidStatus, }; -use core::convert::TryInto; +use crate::signal::Signal; +use crate::utils::as_mut_ptr; use core::mem::MaybeUninit; -use core::num::NonZeroU32; use core::ptr::{null, null_mut}; use linux_raw_sys::general::{ - __kernel_gid_t, __kernel_pid_t, __kernel_uid_t, membarrier_cmd, membarrier_cmd_flag, rlimit, - rlimit64, PRIO_PGRP, PRIO_PROCESS, PRIO_USER, RLIM64_INFINITY, RLIM_INFINITY, + membarrier_cmd, membarrier_cmd_flag, rlimit, rlimit64, PRIO_PGRP, PRIO_PROCESS, PRIO_USER, + RLIM64_INFINITY, RLIM_INFINITY, }; +use linux_raw_sys::ioctl::TIOCSCTTY; #[cfg(not(target_os = "wasi"))] #[cfg(feature = "fs")] -use {super::super::conv::ret_c_uint_infallible, crate::fs::Mode}; +use {crate::backend::conv::ret_c_uint_infallible, crate::fs::Mode}; +#[cfg(feature = "fs")] #[inline] pub(crate) fn chdir(filename: &CStr) -> io::Result<()> { unsafe { ret(syscall_readonly!(__NR_chdir, filename)) } @@ -44,13 +48,15 @@ pub(crate) fn fchdir(fd: BorrowedFd<'_>) -> io::Result<()> { unsafe { ret(syscall_readonly!(__NR_fchdir, fd)) } } +#[cfg(feature = "fs")] #[inline] pub(crate) fn chroot(filename: &CStr) -> io::Result<()> { unsafe { ret(syscall_readonly!(__NR_chroot, filename)) } } +#[cfg(feature = "fs")] #[inline] -pub(crate) fn getcwd(buf: &mut [u8]) -> io::Result { +pub(crate) fn getcwd(buf: &mut [MaybeUninit]) -> io::Result { let (buf_addr_mut, buf_len) = slice_mut(buf); unsafe { ret_usize(syscall!(__NR_getcwd, buf_addr_mut, buf_len)) } } @@ -63,15 +69,7 @@ pub(crate) fn membarrier_query() -> MembarrierQuery { c_int(membarrier_cmd::MEMBARRIER_CMD_QUERY as _), c_uint(0) )) { - Ok(query) => { - // SAFETY: The safety of `from_bits_unchecked` is discussed - // [here]. Our "source of truth" is Linux, and here, the - // `query` value is coming from Linux, so we know it only - // contains "source of truth" valid bits. - // - // [here]: https://github.com/bitflags/bitflags/pull/207#issuecomment-671668662 - MembarrierQuery::from_bits_unchecked(query) - } + Ok(query) => MembarrierQuery::from_bits_retain(query), Err(_) => MembarrierQuery::empty(), } } @@ -94,31 +92,20 @@ pub(crate) fn membarrier_cpu(cmd: MembarrierCommand, cpu: Cpuid) -> io::Result<( } } -#[inline] -pub(crate) fn getpid() -> Pid { - unsafe { - let pid: i32 = ret_usize_infallible(syscall_readonly!(__NR_getpid)) as __kernel_pid_t; - debug_assert!(pid > 0); - Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid as u32)) - } -} - #[inline] pub(crate) fn getppid() -> Option { unsafe { - let ppid: i32 = ret_usize_infallible(syscall_readonly!(__NR_getppid)) as __kernel_pid_t; - Pid::from_raw(ppid as u32) + let ppid = ret_c_int_infallible(syscall_readonly!(__NR_getppid)); + Pid::from_raw(ppid) } } #[inline] pub(crate) fn getpgid(pid: Option) -> io::Result { unsafe { - let pgid: i32 = - ret_usize(syscall_readonly!(__NR_getpgid, c_uint(Pid::as_raw(pid))))? as __kernel_pid_t; - Ok(Pid::from_raw_nonzero(NonZeroU32::new_unchecked( - pgid as u32, - ))) + let pgid = ret_c_int(syscall_readonly!(__NR_getpgid, c_int(Pid::as_raw(pid))))?; + debug_assert!(pgid > 0); + Ok(Pid::from_raw_unchecked(pgid)) } } @@ -127,8 +114,8 @@ pub(crate) fn setpgid(pid: Option, pgid: Option) -> io::Result<()> { unsafe { ret(syscall_readonly!( __NR_setpgid, - c_uint(Pid::as_raw(pid)), - c_uint(Pid::as_raw(pgid)) + c_int(Pid::as_raw(pid)), + c_int(Pid::as_raw(pgid)) )) } } @@ -138,77 +125,17 @@ pub(crate) fn getpgrp() -> Pid { // Use the `getpgrp` syscall if available. #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))] unsafe { - let pgid: i32 = ret_usize_infallible(syscall_readonly!(__NR_getpgrp)) as __kernel_pid_t; + let pgid = ret_c_int_infallible(syscall_readonly!(__NR_getpgrp)); debug_assert!(pgid > 0); - Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pgid as u32)) + Pid::from_raw_unchecked(pgid) } // Otherwise use `getpgrp` and pass it zero. #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] unsafe { - let pgid: i32 = - ret_usize_infallible(syscall_readonly!(__NR_getpgid, c_uint(0))) as __kernel_pid_t; + let pgid = ret_c_int_infallible(syscall_readonly!(__NR_getpgid, c_uint(0))); debug_assert!(pgid > 0); - Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pgid as u32)) - } -} - -#[inline] -pub(crate) fn getgid() -> Gid { - #[cfg(any(target_arch = "x86", target_arch = "sparc", target_arch = "arm"))] - unsafe { - let gid: i32 = - (ret_usize_infallible(syscall_readonly!(__NR_getgid32)) as __kernel_gid_t).into(); - Gid::from_raw(gid as u32) - } - #[cfg(not(any(target_arch = "x86", target_arch = "sparc", target_arch = "arm")))] - unsafe { - let gid = ret_usize_infallible(syscall_readonly!(__NR_getgid)) as __kernel_gid_t; - Gid::from_raw(gid as u32) - } -} - -#[inline] -pub(crate) fn getegid() -> Gid { - #[cfg(any(target_arch = "x86", target_arch = "sparc", target_arch = "arm"))] - unsafe { - let gid: i32 = - (ret_usize_infallible(syscall_readonly!(__NR_getegid32)) as __kernel_gid_t).into(); - Gid::from_raw(gid as u32) - } - #[cfg(not(any(target_arch = "x86", target_arch = "sparc", target_arch = "arm")))] - unsafe { - let gid = ret_usize_infallible(syscall_readonly!(__NR_getegid)) as __kernel_gid_t; - Gid::from_raw(gid as u32) - } -} - -#[inline] -pub(crate) fn getuid() -> Uid { - #[cfg(any(target_arch = "x86", target_arch = "sparc", target_arch = "arm"))] - unsafe { - let uid = (ret_usize_infallible(syscall_readonly!(__NR_getuid32)) as __kernel_uid_t).into(); - Uid::from_raw(uid) - } - #[cfg(not(any(target_arch = "x86", target_arch = "sparc", target_arch = "arm")))] - unsafe { - let uid = ret_usize_infallible(syscall_readonly!(__NR_getuid)) as __kernel_uid_t; - Uid::from_raw(uid as u32) - } -} - -#[inline] -pub(crate) fn geteuid() -> Uid { - #[cfg(any(target_arch = "x86", target_arch = "sparc", target_arch = "arm"))] - unsafe { - let uid: i32 = - (ret_usize_infallible(syscall_readonly!(__NR_geteuid32)) as __kernel_uid_t).into(); - Uid::from_raw(uid as u32) - } - #[cfg(not(any(target_arch = "x86", target_arch = "sparc", target_arch = "arm")))] - unsafe { - let uid = ret_usize_infallible(syscall_readonly!(__NR_geteuid)) as __kernel_uid_t; - Uid::from_raw(uid as u32) + Pid::from_raw_unchecked(pgid) } } @@ -220,11 +147,11 @@ pub(crate) fn sched_getaffinity(pid: Option, cpuset: &mut RawCpuSet) -> io: // set bit mask. let size = ret_usize(syscall!( __NR_sched_getaffinity, - c_uint(Pid::as_raw(pid)), + c_int(Pid::as_raw(pid)), size_of::(), by_mut(&mut cpuset.bits) ))?; - let bytes = (cpuset as *mut RawCpuSet).cast::(); + let bytes = as_mut_ptr(cpuset).cast::(); let rest = bytes.wrapping_add(size); // Zero every byte in the cpuset not set by the kernel. rest.write_bytes(0, core::mem::size_of::() - size); @@ -237,7 +164,7 @@ pub(crate) fn sched_setaffinity(pid: Option, cpuset: &RawCpuSet) -> io::Res unsafe { ret(syscall_readonly!( __NR_sched_setaffinity, - c_uint(Pid::as_raw(pid)), + c_int(Pid::as_raw(pid)), size_of::(), slice_just_addr(&cpuset.bits) )) @@ -253,35 +180,20 @@ pub(crate) fn sched_yield() { } } -#[inline] -pub(crate) fn uname() -> RawUname { - let mut uname = MaybeUninit::::uninit(); - unsafe { - ret_infallible(syscall!(__NR_uname, &mut uname)); - uname.assume_init() - } -} - #[cfg(feature = "fs")] #[inline] pub(crate) fn umask(mode: Mode) -> Mode { - unsafe { - // TODO: Use `from_bits_retain` when we switch to bitflags 2.0. - Mode::from_bits_truncate(ret_c_uint_infallible(syscall_readonly!(__NR_umask, mode))) - } + unsafe { Mode::from_bits_retain(ret_c_uint_infallible(syscall_readonly!(__NR_umask, mode))) } } #[inline] pub(crate) fn nice(inc: i32) -> io::Result { - let priority = if inc > -40 && inc < 40 { + let priority = (if inc > -40 && inc < 40 { inc + getpriority_process(None)? } else { inc - } - // TODO: With Rust 1.50, use `.clamp` instead of `.min` and `.max`. - //.clamp(-20, 19); - .min(19) - .max(-20); + }) + .clamp(-20, 19); setpriority_process(None, priority)?; Ok(priority) } @@ -305,7 +217,7 @@ pub(crate) fn getpriority_pgrp(pgid: Option) -> io::Result { - ret_c_int(syscall_readonly!( __NR_getpriority, c_uint(PRIO_PGRP), - c_uint(Pid::as_raw(pgid)) + c_int(Pid::as_raw(pgid)) ))?) } } @@ -317,7 +229,7 @@ pub(crate) fn getpriority_process(pid: Option) -> io::Result { - ret_c_int(syscall_readonly!( __NR_getpriority, c_uint(PRIO_PROCESS), - c_uint(Pid::as_raw(pid)) + c_int(Pid::as_raw(pid)) ))?) } } @@ -340,7 +252,7 @@ pub(crate) fn setpriority_pgrp(pgid: Option, priority: i32) -> io::Result<( ret(syscall_readonly!( __NR_setpriority, c_uint(PRIO_PGRP), - c_uint(Pid::as_raw(pgid)), + c_int(Pid::as_raw(pgid)), c_int(priority) )) } @@ -352,7 +264,7 @@ pub(crate) fn setpriority_process(pid: Option, priority: i32) -> io::Result ret(syscall_readonly!( __NR_setpriority, c_uint(PRIO_PROCESS), - c_uint(Pid::as_raw(pid)), + c_int(Pid::as_raw(pid)), c_int(priority) )) } @@ -440,7 +352,7 @@ pub(crate) fn prlimit(pid: Option, limit: Resource, new: Rlimit) -> io::Res unsafe { match ret(syscall!( __NR_prlimit64, - c_uint(Pid::as_raw(pid)), + c_int(Pid::as_raw(pid)), limit, by_ref(&lim), &mut result @@ -531,19 +443,14 @@ pub(crate) fn _waitpid( ) -> io::Result> { unsafe { let mut status = MaybeUninit::::uninit(); - let pid = ret_c_uint(syscall!( + let pid = ret_c_int(syscall!( __NR_wait4, c_int(pid as _), &mut status, c_int(waitopts.bits() as _), zero() ))?; - Ok(RawNonZeroPid::new(pid).map(|non_zero| { - ( - Pid::from_raw_nonzero(non_zero), - WaitStatus::new(status.assume_init()), - ) - })) + Ok(Pid::from_raw(pid).map(|pid| (pid, WaitStatus::new(status.assume_init())))) } } @@ -585,7 +492,7 @@ fn _waitid_pid(pid: Pid, options: WaitidOptions) -> io::Result) -> Option ! { - unsafe { syscall_noreturn!(__NR_exit_group, c_int(code)) } -} - #[inline] pub(crate) fn getsid(pid: Option) -> io::Result { unsafe { - let pid = ret_usize(syscall_readonly!(__NR_getsid, c_uint(Pid::as_raw(pid))))?; - debug_assert!(pid > 0); - Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked( - pid as u32, - ))) + let pid = ret_c_int(syscall_readonly!(__NR_getsid, c_int(Pid::as_raw(pid))))?; + Ok(Pid::from_raw_unchecked(pid)) } } #[inline] pub(crate) fn setsid() -> io::Result { unsafe { - let pid = ret_usize(syscall_readonly!(__NR_setsid))?; - debug_assert!(pid > 0); - Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked( - pid as u32, - ))) + let pid = ret_c_int(syscall_readonly!(__NR_setsid))?; + Ok(Pid::from_raw_unchecked(pid)) } } @@ -696,27 +591,26 @@ pub(crate) fn test_kill_current_process_group() -> io::Result<()> { } #[inline] -pub(crate) unsafe fn prctl( - option: c::c_int, - arg2: *mut c::c_void, - arg3: *mut c::c_void, - arg4: *mut c::c_void, - arg5: *mut c::c_void, -) -> io::Result { - ret_c_int(syscall!(__NR_prctl, c_int(option), arg2, arg3, arg4, arg5)) -} - -#[inline] -pub(crate) fn pidfd_open(pid: Pid, flags: PidfdFlags) -> io::Result { +pub(crate) fn pidfd_getfd( + pidfd: BorrowedFd<'_>, + targetfd: RawFd, + flags: PidfdGetfdFlags, +) -> io::Result { unsafe { ret_owned_fd(syscall_readonly!( - __NR_pidfd_open, - pid, + __NR_pidfd_getfd, + pidfd, + raw_fd(targetfd), c_int(flags.bits() as _) )) } } +#[inline] +pub(crate) fn pidfd_open(pid: Pid, flags: PidfdFlags) -> io::Result { + unsafe { ret_owned_fd(syscall_readonly!(__NR_pidfd_open, pid, flags)) } +} + #[inline] pub(crate) fn getgroups(buf: &mut [Gid]) -> io::Result { let len = buf.len().try_into().map_err(|_| io::Errno::NOMEM)?; @@ -731,16 +625,13 @@ pub(crate) fn getgroups(buf: &mut [Gid]) -> io::Result { } #[inline] -pub(crate) fn sysinfo() -> Sysinfo { - let mut info = MaybeUninit::::uninit(); +pub(crate) fn ioctl_tiocsctty(fd: BorrowedFd<'_>) -> io::Result<()> { unsafe { - ret_infallible(syscall!(__NR_sysinfo, &mut info)); - info.assume_init() + ret(syscall_readonly!( + __NR_ioctl, + fd, + c_uint(TIOCSCTTY), + by_ref(&0_u32) + )) } } - -#[inline] -pub(crate) fn sethostname(name: &[u8]) -> io::Result<()> { - let (ptr, len) = slice(name); - unsafe { ret(syscall_readonly!(__NR_sethostname, ptr, len)) } -} diff --git a/vendor/rustix/src/backend/linux_raw/process/types.rs b/vendor/rustix/src/backend/linux_raw/process/types.rs index efdaddbae..f31749b83 100644 --- a/vendor/rustix/src/backend/linux_raw/process/types.rs +++ b/vendor/rustix/src/backend/linux_raw/process/types.rs @@ -1,9 +1,6 @@ -use super::super::c; +use crate::backend::c; use linux_raw_sys::general::membarrier_cmd; -/// `sysinfo` -pub type Sysinfo = linux_raw_sys::general::sysinfo; - /// A command for use with [`membarrier`] and [`membarrier_cpu`]. /// /// For `MEMBARRIER_CMD_QUERY`, see [`membarrier_query`]. @@ -81,152 +78,18 @@ pub enum Resource { Rttime = linux_raw_sys::general::RLIMIT_RTTIME, } -/// A signal number for use with [`kill_process`], [`kill_process_group`], -/// and [`kill_current_process_group`]. -/// -/// [`kill_process`]: crate::process::kill_process -/// [`kill_process_group`]: crate::process::kill_process_group -/// [`kill_current_process_group`]: crate::process::kill_current_process_group -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -#[repr(u32)] -pub enum Signal { - /// `SIGHUP` - Hup = linux_raw_sys::general::SIGHUP, - /// `SIGINT` - Int = linux_raw_sys::general::SIGINT, - /// `SIGQUIT` - Quit = linux_raw_sys::general::SIGQUIT, - /// `SIGILL` - Ill = linux_raw_sys::general::SIGILL, - /// `SIGTRAP` - Trap = linux_raw_sys::general::SIGTRAP, - /// `SIGABRT`, aka `SIGIOT` - #[doc(alias = "Iot")] - #[doc(alias = "Abrt")] - Abort = linux_raw_sys::general::SIGABRT, - /// `SIGBUS` - Bus = linux_raw_sys::general::SIGBUS, - /// `SIGFPE` - Fpe = linux_raw_sys::general::SIGFPE, - /// `SIGKILL` - Kill = linux_raw_sys::general::SIGKILL, - /// `SIGUSR1` - Usr1 = linux_raw_sys::general::SIGUSR1, - /// `SIGSEGV` - Segv = linux_raw_sys::general::SIGSEGV, - /// `SIGUSR2` - Usr2 = linux_raw_sys::general::SIGUSR2, - /// `SIGPIPE` - Pipe = linux_raw_sys::general::SIGPIPE, - /// `SIGALRM` - #[doc(alias = "Alrm")] - Alarm = linux_raw_sys::general::SIGALRM, - /// `SIGTERM` - Term = linux_raw_sys::general::SIGTERM, - /// `SIGSTKFLT` - #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] - Stkflt = linux_raw_sys::general::SIGSTKFLT, - /// `SIGCHLD` - #[doc(alias = "Chld")] - Child = linux_raw_sys::general::SIGCHLD, - /// `SIGCONT` - Cont = linux_raw_sys::general::SIGCONT, - /// `SIGSTOP` - Stop = linux_raw_sys::general::SIGSTOP, - /// `SIGTSTP` - Tstp = linux_raw_sys::general::SIGTSTP, - /// `SIGTTIN` - Ttin = linux_raw_sys::general::SIGTTIN, - /// `SIGTTOU` - Ttou = linux_raw_sys::general::SIGTTOU, - /// `SIGURG` - Urg = linux_raw_sys::general::SIGURG, - /// `SIGXCPU` - Xcpu = linux_raw_sys::general::SIGXCPU, - /// `SIGXFSZ` - Xfsz = linux_raw_sys::general::SIGXFSZ, - /// `SIGVTALRM` - #[doc(alias = "Vtalrm")] - Vtalarm = linux_raw_sys::general::SIGVTALRM, - /// `SIGPROF` - Prof = linux_raw_sys::general::SIGPROF, - /// `SIGWINCH` - Winch = linux_raw_sys::general::SIGWINCH, - /// `SIGIO`, aka `SIGPOLL` - #[doc(alias = "Poll")] - Io = linux_raw_sys::general::SIGIO, - /// `SIGPWR` - #[doc(alias = "Pwr")] - Power = linux_raw_sys::general::SIGPWR, - /// `SIGSYS`, aka `SIGUNUSED` - #[doc(alias = "Unused")] - Sys = linux_raw_sys::general::SIGSYS, - /// `SIGRTMIN` - Rtmin = linux_raw_sys::general::SIGRTMIN, -} - -impl Signal { - /// Convert a raw signal number into a `Signal`, if possible. - pub fn from_raw(sig: i32) -> Option { - match sig as _ { - linux_raw_sys::general::SIGHUP => Some(Self::Hup), - linux_raw_sys::general::SIGINT => Some(Self::Int), - linux_raw_sys::general::SIGQUIT => Some(Self::Quit), - linux_raw_sys::general::SIGILL => Some(Self::Ill), - linux_raw_sys::general::SIGTRAP => Some(Self::Trap), - linux_raw_sys::general::SIGABRT => Some(Self::Abort), - linux_raw_sys::general::SIGBUS => Some(Self::Bus), - linux_raw_sys::general::SIGFPE => Some(Self::Fpe), - linux_raw_sys::general::SIGKILL => Some(Self::Kill), - linux_raw_sys::general::SIGUSR1 => Some(Self::Usr1), - linux_raw_sys::general::SIGSEGV => Some(Self::Segv), - linux_raw_sys::general::SIGUSR2 => Some(Self::Usr2), - linux_raw_sys::general::SIGPIPE => Some(Self::Pipe), - linux_raw_sys::general::SIGALRM => Some(Self::Alarm), - linux_raw_sys::general::SIGTERM => Some(Self::Term), - #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] - linux_raw_sys::general::SIGSTKFLT => Some(Self::Stkflt), - linux_raw_sys::general::SIGCHLD => Some(Self::Child), - linux_raw_sys::general::SIGCONT => Some(Self::Cont), - linux_raw_sys::general::SIGSTOP => Some(Self::Stop), - linux_raw_sys::general::SIGTSTP => Some(Self::Tstp), - linux_raw_sys::general::SIGTTIN => Some(Self::Ttin), - linux_raw_sys::general::SIGTTOU => Some(Self::Ttou), - linux_raw_sys::general::SIGURG => Some(Self::Urg), - linux_raw_sys::general::SIGXCPU => Some(Self::Xcpu), - linux_raw_sys::general::SIGXFSZ => Some(Self::Xfsz), - linux_raw_sys::general::SIGVTALRM => Some(Self::Vtalarm), - linux_raw_sys::general::SIGPROF => Some(Self::Prof), - linux_raw_sys::general::SIGWINCH => Some(Self::Winch), - linux_raw_sys::general::SIGIO => Some(Self::Io), - linux_raw_sys::general::SIGPWR => Some(Self::Power), - linux_raw_sys::general::SIGSYS => Some(Self::Sys), - linux_raw_sys::general::SIGRTMIN => Some(Self::Rtmin), - _ => None, - } - } -} - /// `EXIT_SUCCESS` pub const EXIT_SUCCESS: c::c_int = 0; /// `EXIT_FAILURE` pub const EXIT_FAILURE: c::c_int = 1; /// The status value of a child terminated with a [`Signal::Abort`] signal. +/// +/// [`Signal::Abort`]: crate::process::Signal::Abort pub const EXIT_SIGNALED_SIGABRT: c::c_int = 128 + linux_raw_sys::general::SIGABRT as i32; -/// A process identifier as a raw integer. -pub type RawPid = u32; -/// A non-zero process identifier as a raw non-zero integer. -pub type RawNonZeroPid = core::num::NonZeroU32; -/// A group identifier as a raw integer. -pub type RawGid = u32; -/// A user identifier as a raw integer. -pub type RawUid = u32; /// A CPU identifier as a raw integer. pub type RawCpuid = u32; -pub(crate) type RawUname = linux_raw_sys::general::new_utsname; - #[repr(C)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub(crate) struct RawCpuSet { diff --git a/vendor/rustix/src/backend/linux_raw/pty/mod.rs b/vendor/rustix/src/backend/linux_raw/pty/mod.rs new file mode 100644 index 000000000..ef944f04d --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/pty/mod.rs @@ -0,0 +1 @@ +pub(crate) mod syscalls; diff --git a/vendor/rustix/src/backend/linux_raw/pty/syscalls.rs b/vendor/rustix/src/backend/linux_raw/pty/syscalls.rs new file mode 100644 index 000000000..c2d1b07c1 --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/pty/syscalls.rs @@ -0,0 +1,59 @@ +//! linux_raw syscalls supporting `rustix::pty`. +//! +//! # Safety +//! +//! See the `rustix::backend` module documentation for details. +#![allow(unsafe_code)] +#![allow(clippy::undocumented_unsafe_blocks)] + +use crate::backend::c; +use crate::backend::conv::{by_ref, c_uint, ret, ret_owned_fd}; +use crate::fd::{BorrowedFd, OwnedFd}; +use crate::ffi::CString; +use crate::io; +use crate::path::DecInt; +use crate::pty::OpenptFlags; +#[cfg(any(apple, freebsdlike, linux_like, target_os = "fuchsia"))] +use alloc::vec::Vec; +use core::mem::MaybeUninit; +use linux_raw_sys::ioctl::{TIOCGPTN, TIOCGPTPEER, TIOCSPTLCK}; + +#[cfg(any(apple, freebsdlike, linux_like, target_os = "fuchsia"))] +#[inline] +pub(crate) fn ptsname(fd: BorrowedFd, mut buffer: Vec) -> io::Result { + unsafe { + let mut n = MaybeUninit::::uninit(); + ret(syscall!(__NR_ioctl, fd, c_uint(TIOCGPTN), &mut n))?; + + buffer.clear(); + buffer.extend_from_slice(b"/dev/pts/"); + buffer.extend_from_slice(DecInt::new(n.assume_init()).as_bytes()); + buffer.push(b'\0'); + Ok(CString::from_vec_with_nul_unchecked(buffer)) + } +} + +#[inline] +pub(crate) fn unlockpt(fd: BorrowedFd) -> io::Result<()> { + unsafe { + ret(syscall_readonly!( + __NR_ioctl, + fd, + c_uint(TIOCSPTLCK), + by_ref(&0) + )) + } +} + +#[cfg(target_os = "linux")] +#[inline] +pub(crate) fn ioctl_tiocgptpeer(fd: BorrowedFd, flags: OpenptFlags) -> io::Result { + unsafe { + ret_owned_fd(syscall_readonly!( + __NR_ioctl, + fd, + c_uint(TIOCGPTPEER), + flags + )) + } +} diff --git a/vendor/rustix/src/backend/linux_raw/rand/syscalls.rs b/vendor/rustix/src/backend/linux_raw/rand/syscalls.rs index 5533f75e0..95a6efcff 100644 --- a/vendor/rustix/src/backend/linux_raw/rand/syscalls.rs +++ b/vendor/rustix/src/backend/linux_raw/rand/syscalls.rs @@ -6,7 +6,7 @@ #![allow(unsafe_code)] #![allow(clippy::undocumented_unsafe_blocks)] -use super::super::conv::{ret_usize, slice_mut}; +use crate::backend::conv::{ret_usize, slice_mut}; use crate::io; use crate::rand::GetRandomFlags; diff --git a/vendor/rustix/src/backend/linux_raw/rand/types.rs b/vendor/rustix/src/backend/linux_raw/rand/types.rs index 75f17443e..21e950015 100644 --- a/vendor/rustix/src/backend/linux_raw/rand/types.rs +++ b/vendor/rustix/src/backend/linux_raw/rand/types.rs @@ -4,6 +4,8 @@ bitflags! { /// `GRND_*` flags for use with [`getrandom`]. /// /// [`getrandom`]: crate::rand::getrandom + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct GetRandomFlags: u32 { /// `GRND_RANDOM` const RANDOM = linux_raw_sys::general::GRND_RANDOM; diff --git a/vendor/rustix/src/backend/linux_raw/reg.rs b/vendor/rustix/src/backend/linux_raw/reg.rs index afe99c5f4..206031dde 100644 --- a/vendor/rustix/src/backend/linux_raw/reg.rs +++ b/vendor/rustix/src/backend/linux_raw/reg.rs @@ -16,6 +16,7 @@ use super::c; use super::fd::RawFd; use core::marker::PhantomData; +use core::ops::Range; pub(super) trait ToAsm: private::Sealed { /// Convert `self` to a `usize` ready to be passed to a syscall @@ -188,7 +189,7 @@ impl RetReg { } #[inline] - pub(super) fn is_in_range(&self, range: core::ops::Range) -> bool { + pub(super) fn is_in_range(&self, range: Range) -> bool { range.contains(&(self.raw as isize)) } } diff --git a/vendor/rustix/src/backend/linux_raw/runtime/syscalls.rs b/vendor/rustix/src/backend/linux_raw/runtime/syscalls.rs index 74363fc32..b9814e731 100644 --- a/vendor/rustix/src/backend/linux_raw/runtime/syscalls.rs +++ b/vendor/rustix/src/backend/linux_raw/runtime/syscalls.rs @@ -6,12 +6,11 @@ #![allow(unsafe_code)] #![allow(clippy::undocumented_unsafe_blocks)] -use super::super::c; +use crate::backend::c; #[cfg(target_arch = "x86")] -use super::super::conv::by_mut; -use super::super::conv::{ - by_ref, c_int, c_uint, ret, ret_c_int, ret_c_uint, ret_error, ret_usize_infallible, size_of, - zero, +use crate::backend::conv::by_mut; +use crate::backend::conv::{ + by_ref, c_int, c_uint, ret, ret_c_int, ret_c_int_infallible, ret_error, size_of, zero, }; #[cfg(feature = "fs")] use crate::fd::BorrowedFd; @@ -19,23 +18,24 @@ use crate::ffi::CStr; #[cfg(feature = "fs")] use crate::fs::AtFlags; use crate::io; -use crate::process::{Pid, RawNonZeroPid, Signal}; -use crate::runtime::{How, Sigaction, Siginfo, Sigset, Stack, Timespec}; +use crate::pid::Pid; +use crate::runtime::{How, Sigaction, Siginfo, Sigset, Stack}; +use crate::signal::Signal; +use crate::timespec::Timespec; use crate::utils::optional_as_ptr; -#[cfg(target_pointer_width = "32")] -use core::convert::TryInto; use core::mem::MaybeUninit; #[cfg(target_pointer_width = "32")] use linux_raw_sys::general::__kernel_old_timespec; -use linux_raw_sys::general::{__kernel_pid_t, kernel_sigset_t, PR_SET_NAME, SIGCHLD}; +use linux_raw_sys::general::kernel_sigset_t; +use linux_raw_sys::prctl::PR_SET_NAME; #[cfg(target_arch = "x86_64")] -use {super::super::conv::ret_infallible, linux_raw_sys::general::ARCH_SET_FS}; +use {crate::backend::conv::ret_infallible, linux_raw_sys::general::ARCH_SET_FS}; #[inline] pub(crate) unsafe fn fork() -> io::Result> { - let pid = ret_c_uint(syscall_readonly!( + let pid = ret_c_int(syscall_readonly!( __NR_clone, - c_uint(SIGCHLD), + c_int(c::SIGCHLD), zero(), zero(), zero(), @@ -71,9 +71,9 @@ pub(crate) unsafe fn execve( } pub(crate) mod tls { - #[cfg(target_arch = "x86")] - use super::super::tls::UserDesc; use super::*; + #[cfg(target_arch = "x86")] + use crate::backend::runtime::tls::UserDesc; #[cfg(target_arch = "x86")] #[inline] @@ -99,10 +99,8 @@ pub(crate) mod tls { #[inline] pub(crate) unsafe fn set_tid_address(data: *mut c::c_void) -> Pid { - let tid: i32 = - ret_usize_infallible(syscall_readonly!(__NR_set_tid_address, data)) as __kernel_pid_t; - debug_assert_ne!(tid, 0); - Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(tid as u32)) + let tid: i32 = ret_c_int_infallible(syscall_readonly!(__NR_set_tid_address, data)); + Pid::from_raw_unchecked(tid) } #[inline] @@ -144,12 +142,13 @@ pub(crate) unsafe fn tkill(tid: Pid, sig: Signal) -> io::Result<()> { } #[inline] -pub(crate) unsafe fn sigprocmask(how: How, set: &Sigset) -> io::Result { +pub(crate) unsafe fn sigprocmask(how: How, new: Option<&Sigset>) -> io::Result { let mut old = MaybeUninit::::uninit(); + let new = optional_as_ptr(new); ret(syscall!( __NR_rt_sigprocmask, how, - by_ref(set), + new, &mut old, size_of::() ))?; @@ -192,6 +191,9 @@ pub(crate) fn sigtimedwait(set: &Sigset, timeout: Option) -> io::Resul let mut info = MaybeUninit::::uninit(); let timeout_ptr = optional_as_ptr(timeout.as_ref()); + // `rt_sigtimedwait_time64` was introduced in Linux 5.1. The old + // `rt_sigtimedwait` syscall is not y2038-compatible on 32-bit + // architectures. #[cfg(target_pointer_width = "32")] unsafe { match ret_c_int(syscall!( @@ -247,3 +249,8 @@ unsafe fn sigtimedwait_old( Ok(()) } + +#[inline] +pub(crate) fn exit_group(code: c::c_int) -> ! { + unsafe { syscall_noreturn!(__NR_exit_group, c_int(code)) } +} diff --git a/vendor/rustix/src/backend/linux_raw/runtime/tls.rs b/vendor/rustix/src/backend/linux_raw/runtime/tls.rs index 8cc156a71..763971591 100644 --- a/vendor/rustix/src/backend/linux_raw/runtime/tls.rs +++ b/vendor/rustix/src/backend/linux_raw/runtime/tls.rs @@ -6,9 +6,9 @@ //! kernel-provided AUXV values. #![allow(unsafe_code)] -use super::super::c; -use super::super::elf::*; -use super::super::param::auxv::exe_phdrs_slice; +use crate::backend::c; +use crate::backend::elf::*; +use crate::backend::param::auxv::exe_phdrs_slice; use core::ptr::null; /// For use with [`set_thread_area`]. @@ -29,7 +29,7 @@ pub(crate) fn startup_tls_info() -> StartupTlsInfo { unsafe { for phdr in phdrs { match phdr.p_type { - PT_PHDR => base = phdrs.as_ptr().cast::().offset(-(phdr.p_vaddr as isize)), + PT_PHDR => base = phdrs.as_ptr().cast::().sub(phdr.p_vaddr), PT_TLS => tls_phdr = phdr, PT_GNU_STACK => stack_size = phdr.p_memsz, _ => {} diff --git a/vendor/rustix/src/backend/linux_raw/system/mod.rs b/vendor/rustix/src/backend/linux_raw/system/mod.rs new file mode 100644 index 000000000..1e0181a99 --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/system/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod syscalls; +pub(crate) mod types; diff --git a/vendor/rustix/src/backend/linux_raw/system/syscalls.rs b/vendor/rustix/src/backend/linux_raw/system/syscalls.rs new file mode 100644 index 000000000..514751d6f --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/system/syscalls.rs @@ -0,0 +1,37 @@ +//! linux_raw syscalls supporting `rustix::system`. +//! +//! # Safety +//! +//! See the `rustix::backend` module documentation for details. +#![allow(unsafe_code)] +#![allow(clippy::undocumented_unsafe_blocks)] + +use super::types::RawUname; +use crate::backend::conv::{ret, ret_infallible, slice}; +use crate::io; +use crate::system::Sysinfo; +use core::mem::MaybeUninit; + +#[inline] +pub(crate) fn uname() -> RawUname { + let mut uname = MaybeUninit::::uninit(); + unsafe { + ret_infallible(syscall!(__NR_uname, &mut uname)); + uname.assume_init() + } +} + +#[inline] +pub(crate) fn sysinfo() -> Sysinfo { + let mut info = MaybeUninit::::uninit(); + unsafe { + ret_infallible(syscall!(__NR_sysinfo, &mut info)); + info.assume_init() + } +} + +#[inline] +pub(crate) fn sethostname(name: &[u8]) -> io::Result<()> { + let (ptr, len) = slice(name); + unsafe { ret(syscall_readonly!(__NR_sethostname, ptr, len)) } +} diff --git a/vendor/rustix/src/backend/linux_raw/system/types.rs b/vendor/rustix/src/backend/linux_raw/system/types.rs new file mode 100644 index 000000000..47292735c --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/system/types.rs @@ -0,0 +1,4 @@ +/// `sysinfo` +pub type Sysinfo = linux_raw_sys::system::sysinfo; + +pub(crate) type RawUname = linux_raw_sys::system::new_utsname; diff --git a/vendor/rustix/src/backend/linux_raw/termios/mod.rs b/vendor/rustix/src/backend/linux_raw/termios/mod.rs index 1e0181a99..ef944f04d 100644 --- a/vendor/rustix/src/backend/linux_raw/termios/mod.rs +++ b/vendor/rustix/src/backend/linux_raw/termios/mod.rs @@ -1,2 +1 @@ pub(crate) mod syscalls; -pub(crate) mod types; diff --git a/vendor/rustix/src/backend/linux_raw/termios/syscalls.rs b/vendor/rustix/src/backend/linux_raw/termios/syscalls.rs index 3c8cbb0c9..5e21397bc 100644 --- a/vendor/rustix/src/backend/linux_raw/termios/syscalls.rs +++ b/vendor/rustix/src/backend/linux_raw/termios/syscalls.rs @@ -6,21 +6,24 @@ #![allow(unsafe_code)] #![allow(clippy::undocumented_unsafe_blocks)] -use super::super::conv::{by_ref, c_uint, ret}; +use crate::backend::c; +use crate::backend::conv::{by_ref, c_uint, ret}; use crate::fd::BorrowedFd; use crate::io; -use crate::process::{Pid, RawNonZeroPid}; +use crate::pid::Pid; +#[cfg(feature = "procfs")] +use crate::procfs; use crate::termios::{ - Action, OptionalActions, QueueSelector, Termios, Winsize, BRKINT, CBAUD, CS8, CSIZE, ECHO, - ECHONL, ICANON, ICRNL, IEXTEN, IGNBRK, IGNCR, INLCR, ISIG, ISTRIP, IXON, OPOST, PARENB, PARMRK, - VMIN, VTIME, + Action, ControlModes, InputModes, LocalModes, OptionalActions, OutputModes, QueueSelector, + SpecialCodeIndex, Termios, Winsize, }; #[cfg(feature = "procfs")] use crate::{ffi::CStr, fs::FileType, path::DecInt}; use core::mem::MaybeUninit; -use linux_raw_sys::general::__kernel_pid_t; +use linux_raw_sys::general::IBSHIFT; use linux_raw_sys::ioctl::{ - TCFLSH, TCGETS, TCSBRK, TCSETS, TCXONC, TIOCGPGRP, TIOCGSID, TIOCGWINSZ, TIOCSPGRP, TIOCSWINSZ, + TCFLSH, TCSBRK, TCXONC, TIOCEXCL, TIOCGPGRP, TIOCGSID, TIOCGWINSZ, TIOCNXCL, TIOCSPGRP, + TIOCSWINSZ, }; #[inline] @@ -36,31 +39,7 @@ pub(crate) fn tcgetwinsize(fd: BorrowedFd<'_>) -> io::Result { pub(crate) fn tcgetattr(fd: BorrowedFd<'_>) -> io::Result { unsafe { let mut result = MaybeUninit::::uninit(); - ret(syscall!(__NR_ioctl, fd, c_uint(TCGETS), &mut result))?; - Ok(result.assume_init()) - } -} - -#[inline] -#[cfg(any( - target_arch = "x86", - target_arch = "x86_64", - target_arch = "x32", - target_arch = "riscv64", - target_arch = "aarch64", - target_arch = "arm", - target_arch = "mips", - target_arch = "mips64", -))] -pub(crate) fn tcgetattr2(fd: BorrowedFd<'_>) -> io::Result { - unsafe { - let mut result = MaybeUninit::::uninit(); - ret(syscall!( - __NR_ioctl, - fd, - c_uint(linux_raw_sys::ioctl::TCGETS2), - &mut result - ))?; + ret(syscall!(__NR_ioctl, fd, c_uint(c::TCGETS2), &mut result))?; Ok(result.assume_init()) } } @@ -68,13 +47,10 @@ pub(crate) fn tcgetattr2(fd: BorrowedFd<'_>) -> io::Result) -> io::Result { unsafe { - let mut result = MaybeUninit::<__kernel_pid_t>::uninit(); + let mut result = MaybeUninit::::uninit(); ret(syscall!(__NR_ioctl, fd, c_uint(TIOCGPGRP), &mut result))?; let pid = result.assume_init(); - debug_assert!(pid > 0); - Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked( - pid as u32, - ))) + Ok(Pid::from_raw_unchecked(pid)) } } @@ -86,42 +62,17 @@ pub(crate) fn tcsetattr( ) -> io::Result<()> { // Translate from `optional_actions` into an ioctl request code. On MIPS, // `optional_actions` already has `TCGETS` added to it. - let request = if cfg!(any(target_arch = "mips", target_arch = "mips64")) { - optional_actions as u32 - } else { - TCSETS + optional_actions as u32 - }; - unsafe { - ret(syscall_readonly!( - __NR_ioctl, - fd, - c_uint(request as u32), - by_ref(termios) - )) - } -} - -#[inline] -#[cfg(any( - target_arch = "x86", - target_arch = "x86_64", - target_arch = "x32", - target_arch = "riscv64", - target_arch = "aarch64", - target_arch = "arm", - target_arch = "mips", - target_arch = "mips64", -))] -pub(crate) fn tcsetattr2( - fd: BorrowedFd, - optional_actions: OptionalActions, - termios: &crate::termios::Termios2, -) -> io::Result<()> { + let request = linux_raw_sys::ioctl::TCSETS2 + + if cfg!(any(target_arch = "mips", target_arch = "mips64")) { + optional_actions as u32 - linux_raw_sys::ioctl::TCSETS + } else { + optional_actions as u32 + }; unsafe { ret(syscall_readonly!( __NR_ioctl, fd, - c_uint(linux_raw_sys::ioctl::TCSETS2 + optional_actions as u32), + c_uint(request), by_ref(termios) )) } @@ -164,13 +115,10 @@ pub(crate) fn tcflow(fd: BorrowedFd, action: Action) -> io::Result<()> { #[inline] pub(crate) fn tcgetsid(fd: BorrowedFd) -> io::Result { unsafe { - let mut result = MaybeUninit::<__kernel_pid_t>::uninit(); + let mut result = MaybeUninit::::uninit(); ret(syscall!(__NR_ioctl, fd, c_uint(TIOCGSID), &mut result))?; let pid = result.assume_init(); - debug_assert!(pid > 0); - Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked( - pid as u32, - ))) + Ok(Pid::from_raw_unchecked(pid)) } } @@ -192,66 +140,90 @@ pub(crate) fn tcsetpgrp(fd: BorrowedFd<'_>, pid: Pid) -> io::Result<()> { } #[inline] -#[must_use] -#[allow(clippy::missing_const_for_fn)] -pub(crate) fn cfgetospeed(termios: &Termios) -> u32 { - termios.c_cflag & CBAUD +pub(crate) fn ioctl_tiocexcl(fd: BorrowedFd<'_>) -> io::Result<()> { + unsafe { ret(syscall_readonly!(__NR_ioctl, fd, c_uint(TIOCEXCL))) } } #[inline] -#[must_use] -#[allow(clippy::missing_const_for_fn)] -pub(crate) fn cfgetispeed(termios: &Termios) -> u32 { - termios.c_cflag & CBAUD +pub(crate) fn ioctl_tiocnxcl(fd: BorrowedFd<'_>) -> io::Result<()> { + unsafe { ret(syscall_readonly!(__NR_ioctl, fd, c_uint(TIOCNXCL))) } } +/// A wrapper around a conceptual `cfsetspeed` which handles an arbitrary +/// integer speed value. #[inline] -pub(crate) fn cfmakeraw(termios: &mut Termios) { - // From the Linux [`cfmakeraw` manual page]: - // - // [`cfmakeraw` manual page]: https://man7.org/linux/man-pages/man3/cfmakeraw.3.html - termios.c_iflag &= !(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); - termios.c_oflag &= !OPOST; - termios.c_lflag &= !(ECHO | ECHONL | ICANON | ISIG | IEXTEN); - termios.c_cflag &= !(CSIZE | PARENB); - termios.c_cflag |= CS8; +pub(crate) fn set_speed(termios: &mut Termios, arbitrary_speed: u32) -> io::Result<()> { + let encoded_speed = crate::termios::speed::encode(arbitrary_speed).unwrap_or(c::BOTHER); - // Musl and glibc also do these: - termios.c_cc[VMIN] = 1; - termios.c_cc[VTIME] = 0; + debug_assert_eq!(encoded_speed & !c::CBAUD, 0); + + termios.control_modes -= ControlModes::from_bits_retain(c::CBAUD | c::CIBAUD); + termios.control_modes |= + ControlModes::from_bits_retain(encoded_speed | (encoded_speed << IBSHIFT)); + + termios.input_speed = arbitrary_speed; + termios.output_speed = arbitrary_speed; + + Ok(()) } +/// A wrapper around a conceptual `cfsetospeed` which handles an arbitrary +/// integer speed value. #[inline] -pub(crate) fn cfsetospeed(termios: &mut Termios, speed: u32) -> io::Result<()> { - if (speed & !CBAUD) != 0 { - return Err(io::Errno::INVAL); - } - termios.c_cflag &= !CBAUD; - termios.c_cflag |= speed; +pub(crate) fn set_output_speed(termios: &mut Termios, arbitrary_speed: u32) -> io::Result<()> { + let encoded_speed = crate::termios::speed::encode(arbitrary_speed).unwrap_or(c::BOTHER); + + debug_assert_eq!(encoded_speed & !c::CBAUD, 0); + + termios.control_modes -= ControlModes::from_bits_retain(c::CBAUD); + termios.control_modes |= ControlModes::from_bits_retain(encoded_speed); + + termios.output_speed = arbitrary_speed; + Ok(()) } +/// A wrapper around a conceptual `cfsetispeed` which handles an arbitrary +/// integer speed value. #[inline] -pub(crate) fn cfsetispeed(termios: &mut Termios, speed: u32) -> io::Result<()> { - if speed == 0 { - return Ok(()); - } - if (speed & !CBAUD) != 0 { - return Err(io::Errno::INVAL); - } - termios.c_cflag &= !CBAUD; - termios.c_cflag |= speed; +pub(crate) fn set_input_speed(termios: &mut Termios, arbitrary_speed: u32) -> io::Result<()> { + let encoded_speed = crate::termios::speed::encode(arbitrary_speed).unwrap_or(c::BOTHER); + + debug_assert_eq!(encoded_speed & !c::CBAUD, 0); + + termios.control_modes -= ControlModes::from_bits_retain(c::CIBAUD); + termios.control_modes |= ControlModes::from_bits_retain(encoded_speed << IBSHIFT); + + termios.input_speed = arbitrary_speed; + Ok(()) } #[inline] -pub(crate) fn cfsetspeed(termios: &mut Termios, speed: u32) -> io::Result<()> { - if (speed & !CBAUD) != 0 { - return Err(io::Errno::INVAL); - } - termios.c_cflag &= !CBAUD; - termios.c_cflag |= speed; - Ok(()) +pub(crate) fn cfmakeraw(termios: &mut Termios) { + // From the Linux [`cfmakeraw` manual page]: + // + // [`cfmakeraw` manual page]: https://man7.org/linux/man-pages/man3/cfmakeraw.3.html + termios.input_modes -= InputModes::IGNBRK + | InputModes::BRKINT + | InputModes::PARMRK + | InputModes::ISTRIP + | InputModes::INLCR + | InputModes::IGNCR + | InputModes::ICRNL + | InputModes::IXON; + termios.output_modes -= OutputModes::OPOST; + termios.local_modes -= LocalModes::ECHO + | LocalModes::ECHONL + | LocalModes::ICANON + | LocalModes::ISIG + | LocalModes::IEXTEN; + termios.control_modes -= ControlModes::CSIZE | ControlModes::PARENB; + termios.control_modes |= ControlModes::CS8; + + // Musl and glibc also do these: + termios.special_codes[SpecialCodeIndex::VMIN] = 1; + termios.special_codes[SpecialCodeIndex::VTIME] = 0; } #[inline] @@ -264,8 +236,9 @@ pub(crate) fn isatty(fd: BorrowedFd<'_>) -> bool { } #[cfg(feature = "procfs")] -pub(crate) fn ttyname(fd: BorrowedFd<'_>, buf: &mut [u8]) -> io::Result { - let fd_stat = super::super::fs::syscalls::fstat(fd)?; +#[allow(unsafe_code)] +pub(crate) fn ttyname(fd: BorrowedFd<'_>, buf: &mut [MaybeUninit]) -> io::Result { + let fd_stat = crate::backend::fs::syscalls::fstat(fd)?; // Quick check: if `fd` isn't a character device, it's not a tty. if FileType::from_raw_mode(fd_stat.st_mode) != FileType::CharacterDevice { @@ -276,11 +249,14 @@ pub(crate) fn ttyname(fd: BorrowedFd<'_>, buf: &mut [u8]) -> io::Result { tcgetwinsize(fd)?; // Get a fd to '/proc/self/fd'. - let proc_self_fd = io::proc_self_fd()?; + let proc_self_fd = procfs::proc_self_fd()?; // Gather the ttyname by reading the 'fd' file inside 'proc_self_fd'. - let r = - super::super::fs::syscalls::readlinkat(proc_self_fd, DecInt::from_fd(fd).as_c_str(), buf)?; + let r = crate::backend::fs::syscalls::readlinkat( + proc_self_fd, + DecInt::from_fd(fd).as_c_str(), + buf, + )?; // If the number of bytes is equal to the buffer length, truncation may // have occurred. This check also ensures that we have enough space for @@ -288,14 +264,20 @@ pub(crate) fn ttyname(fd: BorrowedFd<'_>, buf: &mut [u8]) -> io::Result { if r == buf.len() { return Err(io::Errno::RANGE); } - buf[r] = b'\0'; + + // `readlinkat` returns the number of bytes placed in the buffer. + // NUL-terminate the string at that offset. + buf[r].write(b'\0'); // Check that the path we read refers to the same file as `fd`. - let path = CStr::from_bytes_with_nul(&buf[..=r]).unwrap(); + { + // SAFETY: We just wrote the NUL byte above + let path = unsafe { CStr::from_ptr(buf.as_ptr().cast()) }; - let path_stat = super::super::fs::syscalls::stat(path)?; - if path_stat.st_dev != fd_stat.st_dev || path_stat.st_ino != fd_stat.st_ino { - return Err(io::Errno::NODEV); + let path_stat = crate::backend::fs::syscalls::stat(path)?; + if path_stat.st_dev != fd_stat.st_dev || path_stat.st_ino != fd_stat.st_ino { + return Err(io::Errno::NODEV); + } } Ok(r) diff --git a/vendor/rustix/src/backend/linux_raw/termios/types.rs b/vendor/rustix/src/backend/linux_raw/termios/types.rs deleted file mode 100644 index 3fe45af98..000000000 --- a/vendor/rustix/src/backend/linux_raw/termios/types.rs +++ /dev/null @@ -1,495 +0,0 @@ -use super::super::c; - -/// `TCSA*` values for use with [`tcsetattr`]. -/// -/// [`tcsetattr`]: crate::termios::tcsetattr -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[repr(u32)] -pub enum OptionalActions { - /// `TCSANOW`—Make the change immediately. - #[doc(alias = "TCSANOW")] - Now = linux_raw_sys::general::TCSANOW, - - /// `TCSADRAIN`—Make the change after all output has been transmitted. - #[doc(alias = "TCSADRAIN")] - Drain = linux_raw_sys::general::TCSADRAIN, - - /// `TCSAFLUSH`—Discard any pending input and then make the change - /// after all output has been transmitted. - #[doc(alias = "TCSAFLUSH")] - Flush = linux_raw_sys::general::TCSAFLUSH, -} - -/// `TC*` values for use with [`tcflush`]. -/// -/// [`tcflush`]: crate::termios::tcflush -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[repr(u32)] -pub enum QueueSelector { - /// `TCIFLUSH`—Flush data received but not read. - #[doc(alias = "TCIFLUSH")] - IFlush = linux_raw_sys::general::TCIFLUSH, - - /// `TCOFLUSH`—Flush data written but not transmitted. - #[doc(alias = "TCOFLUSH")] - OFlush = linux_raw_sys::general::TCOFLUSH, - - /// `TCIOFLUSH`—`IFlush` and `OFlush` combined. - #[doc(alias = "TCIOFLUSH")] - IOFlush = linux_raw_sys::general::TCIOFLUSH, -} - -/// `TC*` values for use with [`tcflow`]. -/// -/// [`tcflow`]: crate::termios::tcflow -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -#[repr(u32)] -pub enum Action { - /// `TCOOFF`—Suspend output. - #[doc(alias = "TCOOFF")] - OOff = linux_raw_sys::general::TCOOFF, - - /// `TCOON`—Restart suspended output. - #[doc(alias = "TCOON")] - OOn = linux_raw_sys::general::TCOON, - - /// `TCIOFF`—Transmits a STOP byte. - #[doc(alias = "TCIOFF")] - IOff = linux_raw_sys::general::TCIOFF, - - /// `TCION`—Transmits a START byte. - #[doc(alias = "TCION")] - IOn = linux_raw_sys::general::TCION, -} - -/// `struct termios` for use with [`tcgetattr`] and [`tcsetattr`]. -/// -/// [`tcgetattr`]: crate::termios::tcgetattr -/// [`tcsetattr`]: crate::termios::tcsetattr -#[doc(alias = "termios")] -pub type Termios = linux_raw_sys::general::termios; - -/// `struct termios2` for use with [`tcgetattr2`] and [`tcsetattr2`]. -/// -/// [`tcgetattr2`]: crate::termios::tcgetattr2 -/// [`tcsetattr2`]: crate::termios::tcsetattr2 -#[cfg(any( - target_arch = "x86", - target_arch = "x86_64", - target_arch = "x32", - target_arch = "riscv64", - target_arch = "aarch64", - target_arch = "arm", - target_arch = "mips", - target_arch = "mips64", -))] -#[doc(alias = "termios2")] -pub type Termios2 = linux_raw_sys::general::termios2; - -/// `struct winsize` for use with [`tcgetwinsize`]. -/// -/// [`tcgetwinsize`]: crate::termios::tcgetwinsize -#[doc(alias = "winsize")] -pub type Winsize = linux_raw_sys::general::winsize; - -/// `tcflag_t`—A type for the flags fields of [`Termios`]. -#[doc(alias = "tcflag_t")] -pub type Tcflag = linux_raw_sys::general::tcflag_t; - -/// `speed_t`—A return type for [`cfsetspeed`] and similar. -/// -/// [`cfsetspeed`]: crate::termios::cfsetspeed -#[doc(alias = "speed_t")] -pub type Speed = linux_raw_sys::general::speed_t; - -/// `VINTR` -pub const VINTR: usize = linux_raw_sys::general::VINTR as usize; - -/// `VQUIT` -pub const VQUIT: usize = linux_raw_sys::general::VQUIT as usize; - -/// `VERASE` -pub const VERASE: usize = linux_raw_sys::general::VERASE as usize; - -/// `VKILL` -pub const VKILL: usize = linux_raw_sys::general::VKILL as usize; - -/// `VEOF` -pub const VEOF: usize = linux_raw_sys::general::VEOF as usize; - -/// `VTIME` -pub const VTIME: usize = linux_raw_sys::general::VTIME as usize; - -/// `VMIN` -pub const VMIN: usize = linux_raw_sys::general::VMIN as usize; - -/// `VSWTC` -pub const VSWTC: usize = linux_raw_sys::general::VSWTC as usize; - -/// `VSTART` -pub const VSTART: usize = linux_raw_sys::general::VSTART as usize; - -/// `VSTOP` -pub const VSTOP: usize = linux_raw_sys::general::VSTOP as usize; - -/// `VSUSP` -pub const VSUSP: usize = linux_raw_sys::general::VSUSP as usize; - -/// `VEOL` -pub const VEOL: usize = linux_raw_sys::general::VEOL as usize; - -/// `VREPRINT` -pub const VREPRINT: usize = linux_raw_sys::general::VREPRINT as usize; - -/// `VDISCARD` -pub const VDISCARD: usize = linux_raw_sys::general::VDISCARD as usize; - -/// `VWERASE` -pub const VWERASE: usize = linux_raw_sys::general::VWERASE as usize; - -/// `VLNEXT` -pub const VLNEXT: usize = linux_raw_sys::general::VLNEXT as usize; - -/// `VEOL2` -pub const VEOL2: usize = linux_raw_sys::general::VEOL2 as usize; - -/// `IGNBRK` -pub const IGNBRK: c::c_uint = linux_raw_sys::general::IGNBRK; - -/// `BRKINT` -pub const BRKINT: c::c_uint = linux_raw_sys::general::BRKINT; - -/// `IGNPAR` -pub const IGNPAR: c::c_uint = linux_raw_sys::general::IGNPAR; - -/// `PARMRK` -pub const PARMRK: c::c_uint = linux_raw_sys::general::PARMRK; - -/// `INPCK` -pub const INPCK: c::c_uint = linux_raw_sys::general::INPCK; - -/// `ISTRIP` -pub const ISTRIP: c::c_uint = linux_raw_sys::general::ISTRIP; - -/// `INLCR` -pub const INLCR: c::c_uint = linux_raw_sys::general::INLCR; - -/// `IGNCR` -pub const IGNCR: c::c_uint = linux_raw_sys::general::IGNCR; - -/// `ICRNL` -pub const ICRNL: c::c_uint = linux_raw_sys::general::ICRNL; - -/// `IUCLC` -pub const IUCLC: c::c_uint = linux_raw_sys::general::IUCLC; - -/// `IXON` -pub const IXON: c::c_uint = linux_raw_sys::general::IXON; - -/// `IXANY` -pub const IXANY: c::c_uint = linux_raw_sys::general::IXANY; - -/// `IXOFF` -pub const IXOFF: c::c_uint = linux_raw_sys::general::IXOFF; - -/// `IMAXBEL` -pub const IMAXBEL: c::c_uint = linux_raw_sys::general::IMAXBEL; - -/// `IUTF8` -pub const IUTF8: c::c_uint = linux_raw_sys::general::IUTF8; - -/// `OPOST` -pub const OPOST: c::c_uint = linux_raw_sys::general::OPOST; - -/// `OLCUC` -pub const OLCUC: c::c_uint = linux_raw_sys::general::OLCUC; - -/// `ONLCR` -pub const ONLCR: c::c_uint = linux_raw_sys::general::ONLCR; - -/// `OCRNL` -pub const OCRNL: c::c_uint = linux_raw_sys::general::OCRNL; - -/// `ONOCR` -pub const ONOCR: c::c_uint = linux_raw_sys::general::ONOCR; - -/// `ONLRET` -pub const ONLRET: c::c_uint = linux_raw_sys::general::ONLRET; - -/// `OFILL` -pub const OFILL: c::c_uint = linux_raw_sys::general::OFILL; - -/// `OFDEL` -pub const OFDEL: c::c_uint = linux_raw_sys::general::OFDEL; - -/// `NLDLY` -pub const NLDLY: c::c_uint = linux_raw_sys::general::NLDLY; - -/// `NL0` -pub const NL0: c::c_uint = linux_raw_sys::general::NL0; - -/// `NL1` -pub const NL1: c::c_uint = linux_raw_sys::general::NL1; - -/// `CRDLY` -pub const CRDLY: c::c_uint = linux_raw_sys::general::CRDLY; - -/// `CR0` -pub const CR0: c::c_uint = linux_raw_sys::general::CR0; - -/// `CR1` -pub const CR1: c::c_uint = linux_raw_sys::general::CR1; - -/// `CR2` -pub const CR2: c::c_uint = linux_raw_sys::general::CR2; - -/// `CR3` -pub const CR3: c::c_uint = linux_raw_sys::general::CR3; - -/// `TABDLY` -pub const TABDLY: c::c_uint = linux_raw_sys::general::TABDLY; - -/// `TAB0` -pub const TAB0: c::c_uint = linux_raw_sys::general::TAB0; - -/// `TAB1` -pub const TAB1: c::c_uint = linux_raw_sys::general::TAB1; - -/// `TAB2` -pub const TAB2: c::c_uint = linux_raw_sys::general::TAB2; - -/// `TAB3` -pub const TAB3: c::c_uint = linux_raw_sys::general::TAB3; - -/// `BSDLY` -pub const BSDLY: c::c_uint = linux_raw_sys::general::BSDLY; - -/// `BS0` -pub const BS0: c::c_uint = linux_raw_sys::general::BS0; - -/// `BS1` -pub const BS1: c::c_uint = linux_raw_sys::general::BS1; - -/// `FFDLY` -pub const FFDLY: c::c_uint = linux_raw_sys::general::FFDLY; - -/// `FF0` -pub const FF0: c::c_uint = linux_raw_sys::general::FF0; - -/// `FF1` -pub const FF1: c::c_uint = linux_raw_sys::general::FF1; - -/// `VTDLY` -pub const VTDLY: c::c_uint = linux_raw_sys::general::VTDLY; - -/// `VT0` -pub const VT0: c::c_uint = linux_raw_sys::general::VT0; - -/// `VT1` -pub const VT1: c::c_uint = linux_raw_sys::general::VT1; - -/// `B0` -pub const B0: Speed = linux_raw_sys::general::B0; - -/// `B50` -pub const B50: Speed = linux_raw_sys::general::B50; - -/// `B75` -pub const B75: Speed = linux_raw_sys::general::B75; - -/// `B110` -pub const B110: Speed = linux_raw_sys::general::B110; - -/// `B134` -pub const B134: Speed = linux_raw_sys::general::B134; - -/// `B150` -pub const B150: Speed = linux_raw_sys::general::B150; - -/// `B200` -pub const B200: Speed = linux_raw_sys::general::B200; - -/// `B300` -pub const B300: Speed = linux_raw_sys::general::B300; - -/// `B600` -pub const B600: Speed = linux_raw_sys::general::B600; - -/// `B1200` -pub const B1200: Speed = linux_raw_sys::general::B1200; - -/// `B1800` -pub const B1800: Speed = linux_raw_sys::general::B1800; - -/// `B2400` -pub const B2400: Speed = linux_raw_sys::general::B2400; - -/// `B4800` -pub const B4800: Speed = linux_raw_sys::general::B4800; - -/// `B9600` -pub const B9600: Speed = linux_raw_sys::general::B9600; - -/// `B19200` -pub const B19200: Speed = linux_raw_sys::general::B19200; - -/// `B38400` -pub const B38400: Speed = linux_raw_sys::general::B38400; - -/// `B57600` -pub const B57600: Speed = linux_raw_sys::general::B57600; - -/// `B115200` -pub const B115200: Speed = linux_raw_sys::general::B115200; - -/// `B230400` -pub const B230400: Speed = linux_raw_sys::general::B230400; - -/// `B460800` -pub const B460800: Speed = linux_raw_sys::general::B460800; - -/// `B500000` -pub const B500000: Speed = linux_raw_sys::general::B500000; - -/// `B576000` -pub const B576000: Speed = linux_raw_sys::general::B576000; - -/// `B921600` -pub const B921600: Speed = linux_raw_sys::general::B921600; - -/// `B1000000` -pub const B1000000: Speed = linux_raw_sys::general::B1000000; - -/// `B1152000` -pub const B1152000: Speed = linux_raw_sys::general::B1152000; - -/// `B1500000` -pub const B1500000: Speed = linux_raw_sys::general::B1500000; - -/// `B2000000` -pub const B2000000: Speed = linux_raw_sys::general::B2000000; - -/// `B2500000` -#[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))] -pub const B2500000: Speed = linux_raw_sys::general::B2500000; - -/// `B3000000` -#[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))] -pub const B3000000: Speed = linux_raw_sys::general::B3000000; - -/// `B3500000` -#[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))] -pub const B3500000: Speed = linux_raw_sys::general::B3500000; - -/// `B4000000` -#[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))] -pub const B4000000: Speed = linux_raw_sys::general::B4000000; - -/// `BOTHER` -pub const BOTHER: c::c_uint = linux_raw_sys::general::BOTHER; - -/// `CSIZE` -pub const CSIZE: c::c_uint = linux_raw_sys::general::CSIZE; - -/// `CS5` -pub const CS5: c::c_uint = linux_raw_sys::general::CS5; - -/// `CS6` -pub const CS6: c::c_uint = linux_raw_sys::general::CS6; - -/// `CS7` -pub const CS7: c::c_uint = linux_raw_sys::general::CS7; - -/// `CS8` -pub const CS8: c::c_uint = linux_raw_sys::general::CS8; - -/// `CSTOPB` -pub const CSTOPB: c::c_uint = linux_raw_sys::general::CSTOPB; - -/// `CREAD` -pub const CREAD: c::c_uint = linux_raw_sys::general::CREAD; - -/// `PARENB` -pub const PARENB: c::c_uint = linux_raw_sys::general::PARENB; - -/// `PARODD` -pub const PARODD: c::c_uint = linux_raw_sys::general::PARODD; - -/// `HUPCL` -pub const HUPCL: c::c_uint = linux_raw_sys::general::HUPCL; - -/// `CLOCAL` -pub const CLOCAL: c::c_uint = linux_raw_sys::general::CLOCAL; - -/// `ISIG` -pub const ISIG: c::c_uint = linux_raw_sys::general::ISIG; - -/// `ICANON`—A flag for the `c_lflag` field of [`Termios`] indicating -/// canonical mode. -pub const ICANON: Tcflag = linux_raw_sys::general::ICANON; - -/// `ECHO` -pub const ECHO: c::c_uint = linux_raw_sys::general::ECHO; - -/// `ECHOE` -pub const ECHOE: c::c_uint = linux_raw_sys::general::ECHOE; - -/// `ECHOK` -pub const ECHOK: c::c_uint = linux_raw_sys::general::ECHOK; - -/// `ECHONL` -pub const ECHONL: c::c_uint = linux_raw_sys::general::ECHONL; - -/// `NOFLSH` -pub const NOFLSH: c::c_uint = linux_raw_sys::general::NOFLSH; - -/// `TOSTOP` -pub const TOSTOP: c::c_uint = linux_raw_sys::general::TOSTOP; - -/// `IEXTEN` -pub const IEXTEN: c::c_uint = linux_raw_sys::general::IEXTEN; - -/// `EXTA` -pub const EXTA: c::c_uint = linux_raw_sys::general::EXTA; - -/// `EXTB` -pub const EXTB: c::c_uint = linux_raw_sys::general::EXTB; - -/// `CBAUD` -pub const CBAUD: c::c_uint = linux_raw_sys::general::CBAUD; - -/// `CBAUDEX` -pub const CBAUDEX: c::c_uint = linux_raw_sys::general::CBAUDEX; - -/// `CIBAUD` -pub const CIBAUD: c::c_uint = linux_raw_sys::general::CIBAUD; - -/// `CMSPAR` -pub const CMSPAR: c::c_uint = linux_raw_sys::general::CMSPAR; - -/// `CRTSCTS` -pub const CRTSCTS: c::c_uint = linux_raw_sys::general::CRTSCTS; - -/// `XCASE` -pub const XCASE: c::c_uint = linux_raw_sys::general::XCASE; - -/// `ECHOCTL` -pub const ECHOCTL: c::c_uint = linux_raw_sys::general::ECHOCTL; - -/// `ECHOPRT` -pub const ECHOPRT: c::c_uint = linux_raw_sys::general::ECHOPRT; - -/// `ECHOKE` -pub const ECHOKE: c::c_uint = linux_raw_sys::general::ECHOKE; - -/// `FLUSHO` -pub const FLUSHO: c::c_uint = linux_raw_sys::general::FLUSHO; - -/// `PENDIN` -pub const PENDIN: c::c_uint = linux_raw_sys::general::PENDIN; - -/// `EXTPROC` -pub const EXTPROC: c::c_uint = linux_raw_sys::general::EXTPROC; - -/// `XTABS` -pub const XTABS: c::c_uint = linux_raw_sys::general::XTABS; diff --git a/vendor/rustix/src/backend/linux_raw/thread/futex.rs b/vendor/rustix/src/backend/linux_raw/thread/futex.rs index 9e087f9f1..4cde309a5 100644 --- a/vendor/rustix/src/backend/linux_raw/thread/futex.rs +++ b/vendor/rustix/src/backend/linux_raw/thread/futex.rs @@ -1,7 +1,9 @@ bitflags::bitflags! { - /// Flags for use with [`futex`]. + /// `FUTEX_*` flags for use with [`futex`]. /// /// [`futex`]: crate::thread::futex + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct FutexFlags: u32 { /// `FUTEX_PRIVATE_FLAG` const PRIVATE = linux_raw_sys::general::FUTEX_PRIVATE_FLAG; @@ -10,7 +12,7 @@ bitflags::bitflags! { } } -/// Operations for use with [`futex`]. +/// `FUTEX_*` operations for use with [`futex`]. /// /// [`futex`]: crate::thread::futex #[derive(Debug, Copy, Clone, Eq, PartialEq)] diff --git a/vendor/rustix/src/backend/linux_raw/thread/syscalls.rs b/vendor/rustix/src/backend/linux_raw/thread/syscalls.rs index 1895c8c6d..f23b7c2df 100644 --- a/vendor/rustix/src/backend/linux_raw/thread/syscalls.rs +++ b/vendor/rustix/src/backend/linux_raw/thread/syscalls.rs @@ -6,20 +6,19 @@ #![allow(unsafe_code)] #![allow(clippy::undocumented_unsafe_blocks)] -use super::super::c; -use super::super::conv::{ - by_ref, c_int, c_uint, ret, ret_c_int, ret_usize, ret_usize_infallible, zero, +use crate::backend::c; +use crate::backend::conv::{ + by_mut, by_ref, c_int, c_uint, ret, ret_c_int, ret_c_int_infallible, ret_usize, + slice_just_addr, slice_just_addr_mut, zero, }; use crate::fd::BorrowedFd; use crate::io; -use crate::process::{Pid, RawNonZeroPid}; +use crate::pid::Pid; use crate::thread::{ClockId, FutexFlags, FutexOperation, NanosleepRelativeResult, Timespec}; use core::mem::MaybeUninit; -use linux_raw_sys::general::{__kernel_pid_t, __kernel_timespec, TIMER_ABSTIME}; #[cfg(target_pointer_width = "32")] -use { - core::convert::TryInto, core::ptr, linux_raw_sys::general::timespec as __kernel_old_timespec, -}; +use linux_raw_sys::general::timespec as __kernel_old_timespec; +use linux_raw_sys::general::{__kernel_timespec, TIMER_ABSTIME}; #[inline] pub(crate) fn clock_nanosleep_relative( @@ -86,14 +85,10 @@ unsafe fn clock_nanosleep_relative_old( &mut old_rem ))?; let old_rem = old_rem.assume_init(); - // TODO: With Rust 1.55, we can use MaybeUninit::write here. - ptr::write( - rem.as_mut_ptr(), - __kernel_timespec { - tv_sec: old_rem.tv_sec.into(), - tv_nsec: old_rem.tv_nsec.into(), - }, - ); + rem.write(__kernel_timespec { + tv_sec: old_rem.tv_sec.into(), + tv_nsec: old_rem.tv_nsec.into(), + }); Ok(()) } @@ -194,23 +189,18 @@ unsafe fn nanosleep_old( let mut old_rem = MaybeUninit::<__kernel_old_timespec>::uninit(); ret(syscall!(__NR_nanosleep, by_ref(&old_req), &mut old_rem))?; let old_rem = old_rem.assume_init(); - // TODO: With Rust 1.55, we can use MaybeUninit::write here. - ptr::write( - rem.as_mut_ptr(), - __kernel_timespec { - tv_sec: old_rem.tv_sec.into(), - tv_nsec: old_rem.tv_nsec.into(), - }, - ); + rem.write(__kernel_timespec { + tv_sec: old_rem.tv_sec.into(), + tv_nsec: old_rem.tv_nsec.into(), + }); Ok(()) } #[inline] pub(crate) fn gettid() -> Pid { unsafe { - let tid: i32 = ret_usize_infallible(syscall_readonly!(__NR_gettid)) as __kernel_pid_t; - debug_assert_ne!(tid, 0); - Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(tid as u32)) + let tid = ret_c_int_infallible(syscall_readonly!(__NR_gettid)); + Pid::from_raw_unchecked(tid) } } @@ -283,48 +273,48 @@ unsafe fn futex_old( )) } -#[cfg(any(target_os = "android", target_os = "linux"))] #[inline] pub(crate) fn setns(fd: BorrowedFd, nstype: c::c_int) -> io::Result { unsafe { ret_c_int(syscall_readonly!(__NR_setns, fd, c_int(nstype))) } } -#[cfg(any(target_os = "android", target_os = "linux"))] #[inline] pub(crate) fn unshare(flags: crate::thread::UnshareFlags) -> io::Result<()> { - unsafe { ret(syscall_readonly!(__NR_unshare, c_uint(flags.bits()))) } + unsafe { ret(syscall_readonly!(__NR_unshare, flags)) } } -#[cfg(any(target_os = "android", target_os = "linux"))] #[inline] pub(crate) fn capget( header: &mut linux_raw_sys::general::__user_cap_header_struct, data: &mut [MaybeUninit], ) -> io::Result<()> { - let header: *mut _ = header; - unsafe { ret(syscall!(__NR_capget, header, data)) } + unsafe { + ret(syscall!( + __NR_capget, + by_mut(header), + slice_just_addr_mut(data) + )) + } } -#[cfg(any(target_os = "android", target_os = "linux"))] #[inline] pub(crate) fn capset( header: &mut linux_raw_sys::general::__user_cap_header_struct, data: &[linux_raw_sys::general::__user_cap_data_struct], ) -> io::Result<()> { - let header: *mut _ = header; - unsafe { ret(syscall!(__NR_capset, header, data.as_ptr())) } + unsafe { ret(syscall!(__NR_capset, by_mut(header), slice_just_addr(data))) } } #[inline] -pub(crate) fn setuid_thread(uid: crate::process::Uid) -> io::Result<()> { +pub(crate) fn setuid_thread(uid: crate::ugid::Uid) -> io::Result<()> { unsafe { ret(syscall_readonly!(__NR_setuid, uid)) } } #[inline] pub(crate) fn setresuid_thread( - ruid: crate::process::Uid, - euid: crate::process::Uid, - suid: crate::process::Uid, + ruid: crate::ugid::Uid, + euid: crate::ugid::Uid, + suid: crate::ugid::Uid, ) -> io::Result<()> { #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc"))] unsafe { @@ -337,15 +327,15 @@ pub(crate) fn setresuid_thread( } #[inline] -pub(crate) fn setgid_thread(gid: crate::process::Gid) -> io::Result<()> { +pub(crate) fn setgid_thread(gid: crate::ugid::Gid) -> io::Result<()> { unsafe { ret(syscall_readonly!(__NR_setgid, gid)) } } #[inline] pub(crate) fn setresgid_thread( - rgid: crate::process::Gid, - egid: crate::process::Gid, - sgid: crate::process::Gid, + rgid: crate::ugid::Gid, + egid: crate::ugid::Gid, + sgid: crate::ugid::Gid, ) -> io::Result<()> { #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "sparc"))] unsafe { diff --git a/vendor/rustix/src/backend/linux_raw/time/syscalls.rs b/vendor/rustix/src/backend/linux_raw/time/syscalls.rs index c039393ef..634ce2674 100644 --- a/vendor/rustix/src/backend/linux_raw/time/syscalls.rs +++ b/vendor/rustix/src/backend/linux_raw/time/syscalls.rs @@ -6,34 +6,32 @@ #![allow(unsafe_code)] #![allow(clippy::undocumented_unsafe_blocks)] -#[cfg(feature = "time")] -use super::super::conv::{by_ref, ret_owned_fd}; -use super::super::conv::{ret, ret_infallible}; -use super::types::ClockId; -#[cfg(feature = "time")] -use crate::fd::BorrowedFd; -#[cfg(feature = "time")] -use crate::fd::OwnedFd; +use crate::backend::conv::{ret, ret_infallible}; +use crate::clockid::ClockId; use crate::io; -#[cfg(feature = "time")] -use crate::time::{Itimerspec, TimerfdClockId, TimerfdFlags, TimerfdTimerFlags}; +use crate::timespec::Timespec; use core::mem::MaybeUninit; -use linux_raw_sys::general::__kernel_timespec; -#[cfg(feature = "time")] +#[cfg(all(feature = "time", target_pointer_width = "32"))] +use linux_raw_sys::general::itimerspec as __kernel_old_itimerspec; #[cfg(target_pointer_width = "32")] -use {core::convert::TryInto, linux_raw_sys::general::itimerspec as __kernel_old_itimerspec}; -#[cfg(target_pointer_width = "32")] -use {core::ptr, linux_raw_sys::general::timespec as __kernel_old_timespec}; +use linux_raw_sys::general::timespec as __kernel_old_timespec; +#[cfg(feature = "time")] +use { + crate::backend::conv::{by_ref, ret_owned_fd}, + crate::fd::BorrowedFd, + crate::fd::OwnedFd, + crate::time::{Itimerspec, TimerfdClockId, TimerfdFlags, TimerfdTimerFlags}, +}; // `clock_gettime` has special optimizations via the vDSO. #[cfg(feature = "time")] -pub(crate) use super::super::vdso_wrappers::{clock_gettime, clock_gettime_dynamic}; +pub(crate) use crate::backend::vdso_wrappers::{clock_gettime, clock_gettime_dynamic}; #[inline] -pub(crate) fn clock_getres(which_clock: ClockId) -> __kernel_timespec { +pub(crate) fn clock_getres(which_clock: ClockId) -> Timespec { #[cfg(target_pointer_width = "32")] unsafe { - let mut result = MaybeUninit::<__kernel_timespec>::uninit(); + let mut result = MaybeUninit::::uninit(); if let Err(err) = ret(syscall!(__NR_clock_getres_time64, which_clock, &mut result)) { // See the comments in `rustix_clock_gettime_via_syscall` about // emulation. @@ -44,30 +42,28 @@ pub(crate) fn clock_getres(which_clock: ClockId) -> __kernel_timespec { } #[cfg(target_pointer_width = "64")] unsafe { - let mut result = MaybeUninit::<__kernel_timespec>::uninit(); + let mut result = MaybeUninit::::uninit(); ret_infallible(syscall!(__NR_clock_getres, which_clock, &mut result)); result.assume_init() } } #[cfg(target_pointer_width = "32")] -unsafe fn clock_getres_old(which_clock: ClockId, result: &mut MaybeUninit<__kernel_timespec>) { +unsafe fn clock_getres_old(which_clock: ClockId, result: &mut MaybeUninit) { let mut old_result = MaybeUninit::<__kernel_old_timespec>::uninit(); ret_infallible(syscall!(__NR_clock_getres, which_clock, &mut old_result)); let old_result = old_result.assume_init(); - // TODO: With Rust 1.55, we can use MaybeUninit::write here. - ptr::write( - result.as_mut_ptr(), - __kernel_timespec { - tv_sec: old_result.tv_sec.into(), - tv_nsec: old_result.tv_nsec.into(), - }, - ); + result.write(Timespec { + tv_sec: old_result.tv_sec.into(), + tv_nsec: old_result.tv_nsec.into(), + }); } #[cfg(feature = "time")] #[inline] -pub(crate) fn clock_settime(which_clock: ClockId, timespec: __kernel_timespec) -> io::Result<()> { +pub(crate) fn clock_settime(which_clock: ClockId, timespec: Timespec) -> io::Result<()> { + // `clock_settime64` was introduced in Linux 5.1. The old `clock_settime` + // syscall is not y2038-compatible on 32-bit architectures. #[cfg(target_pointer_width = "32")] unsafe { match ret(syscall_readonly!( @@ -91,7 +87,7 @@ pub(crate) fn clock_settime(which_clock: ClockId, timespec: __kernel_timespec) - #[cfg(feature = "time")] #[cfg(target_pointer_width = "32")] -unsafe fn clock_settime_old(which_clock: ClockId, timespec: __kernel_timespec) -> io::Result<()> { +unsafe fn clock_settime_old(which_clock: ClockId, timespec: Timespec) -> io::Result<()> { let old_timespec = __kernel_old_timespec { tv_sec: timespec .tv_sec @@ -200,20 +196,16 @@ unsafe fn timerfd_settime_old( &mut old_result ))?; let old_result = old_result.assume_init(); - // TODO: With Rust 1.55, we can use MaybeUninit::write here. - ptr::write( - result.as_mut_ptr(), - Itimerspec { - it_interval: __kernel_timespec { - tv_sec: old_result.it_interval.tv_sec.into(), - tv_nsec: old_result.it_interval.tv_nsec.into(), - }, - it_value: __kernel_timespec { - tv_sec: old_result.it_value.tv_sec.into(), - tv_nsec: old_result.it_value.tv_nsec.into(), - }, + result.write(Itimerspec { + it_interval: Timespec { + tv_sec: old_result.it_interval.tv_sec.into(), + tv_nsec: old_result.it_interval.tv_nsec.into(), }, - ); + it_value: Timespec { + tv_sec: old_result.it_value.tv_sec.into(), + tv_nsec: old_result.it_value.tv_nsec.into(), + }, + }); Ok(()) } @@ -252,19 +244,15 @@ unsafe fn timerfd_gettime_old( let mut old_result = MaybeUninit::<__kernel_old_itimerspec>::uninit(); ret(syscall!(__NR_timerfd_gettime, fd, &mut old_result))?; let old_result = old_result.assume_init(); - // TODO: With Rust 1.55, we can use MaybeUninit::write here. - ptr::write( - result.as_mut_ptr(), - Itimerspec { - it_interval: __kernel_timespec { - tv_sec: old_result.it_interval.tv_sec.into(), - tv_nsec: old_result.it_interval.tv_nsec.into(), - }, - it_value: __kernel_timespec { - tv_sec: old_result.it_value.tv_sec.into(), - tv_nsec: old_result.it_value.tv_nsec.into(), - }, + result.write(Itimerspec { + it_interval: Timespec { + tv_sec: old_result.it_interval.tv_sec.into(), + tv_nsec: old_result.it_interval.tv_nsec.into(), + }, + it_value: Timespec { + tv_sec: old_result.it_value.tv_sec.into(), + tv_nsec: old_result.it_value.tv_nsec.into(), }, - ); + }); Ok(()) } diff --git a/vendor/rustix/src/backend/linux_raw/time/types.rs b/vendor/rustix/src/backend/linux_raw/time/types.rs index fcdd7f6d6..62cb167e6 100644 --- a/vendor/rustix/src/backend/linux_raw/time/types.rs +++ b/vendor/rustix/src/backend/linux_raw/time/types.rs @@ -1,16 +1,6 @@ -use super::super::c; -use crate::fd::BorrowedFd; +use crate::backend::c; use bitflags::bitflags; -/// `struct timespec` -pub type Timespec = linux_raw_sys::general::__kernel_timespec; - -/// A type for the `tv_sec` field of [`Timespec`]. -pub type Secs = linux_raw_sys::general::__kernel_time64_t; - -/// A type for the `tv_nsec` field of [`Timespec`]. -pub type Nsecs = i64; - /// `struct itimerspec` for use with [`timerfd_gettime`] and /// [`timerfd_settime`]. /// @@ -18,73 +8,12 @@ pub type Nsecs = i64; /// [`timerfd_settime`]: crate::time::timerfd_settime pub type Itimerspec = linux_raw_sys::general::__kernel_itimerspec; -/// `CLOCK_*` constants for use with [`clock_gettime`]. -/// -/// These constants are always supported at runtime, so `clock_gettime` never -/// has to fail with `INVAL` due to an unsupported clock. See -/// [`DynamicClockId`] for a greater set of clocks, with the caveat that not -/// all of them are always supported. -/// -/// [`clock_gettime`]: crate::time::clock_gettime -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -#[repr(u32)] -#[non_exhaustive] -pub enum ClockId { - /// `CLOCK_REALTIME` - Realtime = linux_raw_sys::general::CLOCK_REALTIME, - - /// `CLOCK_MONOTONIC` - Monotonic = linux_raw_sys::general::CLOCK_MONOTONIC, - - /// `CLOCK_PROCESS_CPUTIME_ID` - ProcessCPUTime = linux_raw_sys::general::CLOCK_PROCESS_CPUTIME_ID, - - /// `CLOCK_THREAD_CPUTIME_ID` - ThreadCPUTime = linux_raw_sys::general::CLOCK_THREAD_CPUTIME_ID, - - /// `CLOCK_REALTIME_COARSE` - RealtimeCoarse = linux_raw_sys::general::CLOCK_REALTIME_COARSE, - - /// `CLOCK_MONOTONIC_COARSE` - MonotonicCoarse = linux_raw_sys::general::CLOCK_MONOTONIC_COARSE, - - /// `CLOCK_MONOTONIC_RAW` - MonotonicRaw = linux_raw_sys::general::CLOCK_MONOTONIC_RAW, -} - -/// `CLOCK_*` constants for use with [`clock_gettime_dynamic`]. -/// -/// These constants may be unsupported at runtime, depending on the OS version, -/// and `clock_gettime_dynamic` may fail with `INVAL`. See [`ClockId`] for -/// clocks which are always supported at runtime. -/// -/// [`clock_gettime_dynamic`]: crate::time::clock_gettime_dynamic -#[derive(Debug, Copy, Clone)] -#[non_exhaustive] -pub enum DynamicClockId<'a> { - /// `ClockId` values that are always supported at runtime. - Known(ClockId), - - /// Linux dynamic clocks. - Dynamic(BorrowedFd<'a>), - - /// `CLOCK_REALTIME_ALARM`, available on Linux >= 3.0 - RealtimeAlarm, - - /// `CLOCK_TAI`, available on Linux >= 3.10 - Tai, - - /// `CLOCK_BOOTTIME`, available on Linux >= 2.6.39 - Boottime, - - /// `CLOCK_BOOTTIME_ALARM`, available on Linux >= 2.6.39 - BoottimeAlarm, -} - bitflags! { /// `TFD_*` flags for use with [`timerfd_create`]. /// /// [`timerfd_create`]: crate::time::timerfd_create + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct TimerfdFlags: c::c_uint { /// `TFD_NONBLOCK` const NONBLOCK = linux_raw_sys::general::TFD_NONBLOCK; @@ -98,6 +27,8 @@ bitflags! { /// `TFD_TIMER_*` flags for use with [`timerfd_settime`]. /// /// [`timerfd_settime`]: crate::time::timerfd_settime + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct TimerfdTimerFlags: c::c_uint { /// `TFD_TIMER_ABSTIME` const ABSTIME = linux_raw_sys::general::TFD_TIMER_ABSTIME; diff --git a/vendor/rustix/src/backend/linux_raw/ugid/mod.rs b/vendor/rustix/src/backend/linux_raw/ugid/mod.rs new file mode 100644 index 000000000..ef944f04d --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/ugid/mod.rs @@ -0,0 +1 @@ +pub(crate) mod syscalls; diff --git a/vendor/rustix/src/backend/linux_raw/ugid/syscalls.rs b/vendor/rustix/src/backend/linux_raw/ugid/syscalls.rs new file mode 100644 index 000000000..12ff6dce1 --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/ugid/syscalls.rs @@ -0,0 +1,67 @@ +//! linux_raw syscalls for UIDs and GIDs +//! +//! # Safety +//! +//! See the `rustix::backend` module documentation for details. +#![allow(unsafe_code)] +#![allow(clippy::undocumented_unsafe_blocks)] + +use crate::backend::c; +use crate::backend::conv::ret_usize_infallible; +use crate::ugid::{Gid, Uid}; + +#[inline] +pub(crate) fn getuid() -> Uid { + #[cfg(any(target_arch = "arm", target_arch = "sparc", target_arch = "x86"))] + unsafe { + let uid = ret_usize_infallible(syscall_readonly!(__NR_getuid32)) as c::uid_t; + Uid::from_raw(uid) + } + #[cfg(not(any(target_arch = "arm", target_arch = "sparc", target_arch = "x86")))] + unsafe { + let uid = ret_usize_infallible(syscall_readonly!(__NR_getuid)) as c::uid_t; + Uid::from_raw(uid) + } +} + +#[inline] +pub(crate) fn geteuid() -> Uid { + #[cfg(any(target_arch = "arm", target_arch = "sparc", target_arch = "x86"))] + unsafe { + let uid = ret_usize_infallible(syscall_readonly!(__NR_geteuid32)) as c::uid_t; + Uid::from_raw(uid) + } + #[cfg(not(any(target_arch = "arm", target_arch = "sparc", target_arch = "x86")))] + unsafe { + let uid = ret_usize_infallible(syscall_readonly!(__NR_geteuid)) as c::uid_t; + Uid::from_raw(uid) + } +} + +#[inline] +pub(crate) fn getgid() -> Gid { + #[cfg(any(target_arch = "arm", target_arch = "sparc", target_arch = "x86"))] + unsafe { + let gid = ret_usize_infallible(syscall_readonly!(__NR_getgid32)) as c::gid_t; + Gid::from_raw(gid) + } + #[cfg(not(any(target_arch = "arm", target_arch = "sparc", target_arch = "x86")))] + unsafe { + let gid = ret_usize_infallible(syscall_readonly!(__NR_getgid)) as c::gid_t; + Gid::from_raw(gid) + } +} + +#[inline] +pub(crate) fn getegid() -> Gid { + #[cfg(any(target_arch = "arm", target_arch = "sparc", target_arch = "x86"))] + unsafe { + let gid = ret_usize_infallible(syscall_readonly!(__NR_getegid32)) as c::gid_t; + Gid::from_raw(gid) + } + #[cfg(not(any(target_arch = "arm", target_arch = "sparc", target_arch = "x86")))] + unsafe { + let gid = ret_usize_infallible(syscall_readonly!(__NR_getegid)) as c::gid_t; + Gid::from_raw(gid) + } +} diff --git a/vendor/rustix/src/backend/linux_raw/vdso_wrappers.rs b/vendor/rustix/src/backend/linux_raw/vdso_wrappers.rs index 97d5862a0..422793690 100644 --- a/vendor/rustix/src/backend/linux_raw/vdso_wrappers.rs +++ b/vendor/rustix/src/backend/linux_raw/vdso_wrappers.rs @@ -9,22 +9,30 @@ //! functions. #![allow(unsafe_code)] -use super::conv::{c_int, ret}; #[cfg(target_arch = "x86")] use super::reg::{ArgReg, RetReg, SyscallNumber, A0, A1, A2, A3, A4, A5, R0}; -use super::time::types::{ClockId, DynamicClockId, Timespec}; -use super::{c, vdso}; -use crate::io; +use super::vdso; #[cfg(all(asm, target_arch = "x86"))] use core::arch::asm; -use core::mem::{transmute, MaybeUninit}; +use core::mem::transmute; use core::ptr::null_mut; use core::sync::atomic::AtomicPtr; use core::sync::atomic::Ordering::Relaxed; #[cfg(target_pointer_width = "32")] +#[cfg(feature = "time")] use linux_raw_sys::general::timespec as __kernel_old_timespec; -use linux_raw_sys::general::{__kernel_clockid_t, __kernel_timespec}; - +#[cfg(feature = "time")] +use { + super::c, + super::conv::{c_int, ret}, + crate::clockid::{ClockId, DynamicClockId}, + crate::io, + crate::timespec::Timespec, + core::mem::MaybeUninit, + linux_raw_sys::general::{__kernel_clockid_t, __kernel_timespec}, +}; + +#[cfg(feature = "time")] #[inline] pub(crate) fn clock_gettime(which_clock: ClockId) -> __kernel_timespec { // SAFETY: `CLOCK_GETTIME` contains either null or the address of a @@ -42,6 +50,7 @@ pub(crate) fn clock_gettime(which_clock: ClockId) -> __kernel_timespec { } } +#[cfg(feature = "time")] #[inline] pub(crate) fn clock_gettime_dynamic(which_clock: DynamicClockId<'_>) -> io::Result { let id = match which_clock { @@ -198,6 +207,7 @@ pub(super) mod x86_via_vdso { // With the indirect call, it isn't meaningful to do a separate // `_readonly` optimization. + #[allow(unused_imports)] pub(in crate::backend) use { syscall0 as syscall0_readonly, syscall1 as syscall1_readonly, syscall2 as syscall2_readonly, syscall3 as syscall3_readonly, @@ -206,6 +216,7 @@ pub(super) mod x86_via_vdso { }; } +#[cfg(feature = "time")] type ClockGettimeType = unsafe extern "C" fn(c::c_int, *mut Timespec) -> c::c_int; /// The underlying syscall functions are only called from asm, using the @@ -215,6 +226,7 @@ type ClockGettimeType = unsafe extern "C" fn(c::c_int, *mut Timespec) -> c::c_in pub(super) type SyscallType = unsafe extern "C" fn(); /// Initialize `CLOCK_GETTIME` and return its value. +#[cfg(feature = "time")] fn init_clock_gettime() -> ClockGettimeType { init(); // SAFETY: Load the function address from static storage that we @@ -234,10 +246,12 @@ fn init_syscall() -> SyscallType { /// `AtomicPtr` can't hold a `fn` pointer, so we use a `*` pointer to this /// placeholder type, and cast it as needed. struct Function; +#[cfg(feature = "time")] static mut CLOCK_GETTIME: AtomicPtr = AtomicPtr::new(null_mut()); #[cfg(target_arch = "x86")] static mut SYSCALL: AtomicPtr = AtomicPtr::new(null_mut()); +#[cfg(feature = "time")] unsafe extern "C" fn rustix_clock_gettime_via_syscall( clockid: c::c_int, res: *mut Timespec, @@ -248,6 +262,7 @@ unsafe extern "C" fn rustix_clock_gettime_via_syscall( } } +#[cfg(feature = "time")] #[cfg(target_pointer_width = "32")] unsafe fn _rustix_clock_gettime_via_syscall( clockid: c::c_int, @@ -260,6 +275,7 @@ unsafe fn _rustix_clock_gettime_via_syscall( } } +#[cfg(feature = "time")] #[cfg(target_pointer_width = "32")] unsafe fn _rustix_clock_gettime_via_syscall_old( clockid: c::c_int, @@ -285,6 +301,7 @@ unsafe fn _rustix_clock_gettime_via_syscall_old( } } +#[cfg(feature = "time")] #[cfg(target_pointer_width = "64")] unsafe fn _rustix_clock_gettime_via_syscall( clockid: c::c_int, @@ -314,14 +331,18 @@ fn minimal_init() { // If the memory happens to already be initialized, this is redundant, but // not harmful. unsafe { - CLOCK_GETTIME - .compare_exchange( - null_mut(), - rustix_clock_gettime_via_syscall as *mut Function, - Relaxed, - Relaxed, - ) - .ok(); + #[cfg(feature = "time")] + { + CLOCK_GETTIME + .compare_exchange( + null_mut(), + rustix_clock_gettime_via_syscall as *mut Function, + Relaxed, + Relaxed, + ) + .ok(); + } + #[cfg(target_arch = "x86")] { SYSCALL @@ -340,46 +361,49 @@ fn init() { minimal_init(); if let Some(vdso) = vdso::Vdso::new() { - // Look up the platform-specific `clock_gettime` symbol as documented - // [here], except on 32-bit platforms where we look up the - // `64`-suffixed variant and fail if we don't find it. - // - // [here]: https://man7.org/linux/man-pages/man7/vdso.7.html - #[cfg(target_arch = "x86_64")] - let ptr = vdso.sym(cstr!("LINUX_2.6"), cstr!("__vdso_clock_gettime")); - #[cfg(target_arch = "arm")] - let ptr = vdso.sym(cstr!("LINUX_2.6"), cstr!("__vdso_clock_gettime64")); - #[cfg(target_arch = "aarch64")] - let ptr = vdso.sym(cstr!("LINUX_2.6.39"), cstr!("__kernel_clock_gettime")); - #[cfg(target_arch = "x86")] - let ptr = vdso.sym(cstr!("LINUX_2.6"), cstr!("__vdso_clock_gettime64")); - #[cfg(target_arch = "riscv64")] - let ptr = vdso.sym(cstr!("LINUX_4.15"), cstr!("__vdso_clock_gettime")); - #[cfg(target_arch = "powerpc64")] - let ptr = vdso.sym(cstr!("LINUX_2.6.15"), cstr!("__kernel_clock_gettime")); - #[cfg(target_arch = "mips")] - let ptr = vdso.sym(cstr!("LINUX_2.6"), cstr!("__vdso_clock_gettime64")); - #[cfg(target_arch = "mips64")] - let ptr = vdso.sym(cstr!("LINUX_2.6"), cstr!("__vdso_clock_gettime")); - - // On all 64-bit platforms, the 64-bit `clock_gettime` symbols are - // always available. - #[cfg(target_pointer_width = "64")] - let ok = true; - - // On some 32-bit platforms, the 64-bit `clock_gettime` symbols are not - // available on older kernel versions. - #[cfg(any(target_arch = "arm", target_arch = "mips", target_arch = "x86"))] - let ok = !ptr.is_null(); - - if ok { - assert!(!ptr.is_null()); - - // SAFETY: Store the computed function addresses in static storage - // so that we don't need to compute it again (but if we do, it doesn't - // hurt anything). - unsafe { - CLOCK_GETTIME.store(ptr.cast(), Relaxed); + #[cfg(feature = "time")] + { + // Look up the platform-specific `clock_gettime` symbol as documented + // [here], except on 32-bit platforms where we look up the + // `64`-suffixed variant and fail if we don't find it. + // + // [here]: https://man7.org/linux/man-pages/man7/vdso.7.html + #[cfg(target_arch = "x86_64")] + let ptr = vdso.sym(cstr!("LINUX_2.6"), cstr!("__vdso_clock_gettime")); + #[cfg(target_arch = "arm")] + let ptr = vdso.sym(cstr!("LINUX_2.6"), cstr!("__vdso_clock_gettime64")); + #[cfg(target_arch = "aarch64")] + let ptr = vdso.sym(cstr!("LINUX_2.6.39"), cstr!("__kernel_clock_gettime")); + #[cfg(target_arch = "x86")] + let ptr = vdso.sym(cstr!("LINUX_2.6"), cstr!("__vdso_clock_gettime64")); + #[cfg(target_arch = "riscv64")] + let ptr = vdso.sym(cstr!("LINUX_4.15"), cstr!("__vdso_clock_gettime")); + #[cfg(target_arch = "powerpc64")] + let ptr = vdso.sym(cstr!("LINUX_2.6.15"), cstr!("__kernel_clock_gettime")); + #[cfg(target_arch = "mips")] + let ptr = vdso.sym(cstr!("LINUX_2.6"), cstr!("__vdso_clock_gettime64")); + #[cfg(target_arch = "mips64")] + let ptr = vdso.sym(cstr!("LINUX_2.6"), cstr!("__vdso_clock_gettime")); + + // On all 64-bit platforms, the 64-bit `clock_gettime` symbols are + // always available. + #[cfg(target_pointer_width = "64")] + let ok = true; + + // On some 32-bit platforms, the 64-bit `clock_gettime` symbols are not + // available on older kernel versions. + #[cfg(any(target_arch = "arm", target_arch = "mips", target_arch = "x86"))] + let ok = !ptr.is_null(); + + if ok { + assert!(!ptr.is_null()); + + // SAFETY: Store the computed function addresses in static storage + // so that we don't need to compute it again (but if we do, it + // doesn't hurt anything). + unsafe { + CLOCK_GETTIME.store(ptr.cast(), Relaxed); + } } } diff --git a/vendor/rustix/src/bitcast.rs b/vendor/rustix/src/bitcast.rs new file mode 100644 index 000000000..3924c29d5 --- /dev/null +++ b/vendor/rustix/src/bitcast.rs @@ -0,0 +1,32 @@ +// Ensure that the source and destination types are both primitive integer +// types and the same size, and then bitcast. +#[allow(unused_macros)] +macro_rules! bitcast { + ($x:expr) => {{ + if false { + // Ensure the source and destinations are primitive integer types. + let _ = !$x; + let _ = $x as u8; + 0 + } else if false { + // Ensure that the source and destinations are the same size. + // SAFETY: This code is under an `if false`. + #[allow(unsafe_code, unused_unsafe, clippy::useless_transmute)] + unsafe { + ::core::mem::transmute($x) + } + } else { + // Do the conversion. + $x as _ + } + }}; +} + +/// Return a [`bitcast`] of the value of `$x.bits()`, where `$x` is a +/// `bitflags` type. +#[allow(unused_macros)] +macro_rules! bitflags_bits { + ($x:expr) => {{ + bitcast!($x.bits()) + }}; +} diff --git a/vendor/rustix/src/check_types.rs b/vendor/rustix/src/check_types.rs new file mode 100644 index 000000000..2ba1f3f9e --- /dev/null +++ b/vendor/rustix/src/check_types.rs @@ -0,0 +1,101 @@ +#![allow(unused_macros)] + +/// Check that the size and alignment of a type match the `sys` bindings. +macro_rules! check_type { + ($struct:ident) => { + assert_eq!( + ( + core::mem::size_of::<$struct>(), + core::mem::align_of::<$struct>() + ), + ( + core::mem::size_of::(), + core::mem::align_of::() + ) + ); + }; +} + +/// The same as `check_type`, but for unions and anonymous structs we've +/// renamed to avoid having types like `bindgen_ty_1` in the API. +macro_rules! check_renamed_type { + ($to:ident, $from:ident) => { + assert_eq!( + (core::mem::size_of::<$to>(), core::mem::align_of::<$to>()), + ( + core::mem::size_of::(), + core::mem::align_of::() + ) + ); + }; +} + +/// Check that the field of a struct has the same offset as the +/// corresponding field in the `sys` bindings. +macro_rules! check_struct_field { + ($struct:ident, $field:ident) => { + assert_eq!( + ( + memoffset::offset_of!($struct, $field), + memoffset::span_of!($struct, $field) + ), + ( + memoffset::offset_of!(c::$struct, $field), + memoffset::span_of!(c::$struct, $field) + ) + ); + }; +} + +/// The same as `check_struct_field`, but for unions and anonymous structs +/// we've renamed to avoid having types like `bindgen_ty_1` in the API. +macro_rules! check_struct_renamed_field { + ($struct:ident, $to:ident, $from:ident) => { + assert_eq!( + ( + memoffset::offset_of!($struct, $to), + memoffset::span_of!($struct, $to) + ), + ( + memoffset::offset_of!(c::$struct, $from), + memoffset::span_of!(c::$struct, $from) + ) + ); + }; +} + +/// The same as `check_struct_renamed_field`, but for when both the struct +/// and a field are renamed. +macro_rules! check_renamed_struct_renamed_field { + ($to_struct:ident, $from_struct:ident, $to:ident, $from:ident) => { + assert_eq!( + ( + memoffset::offset_of!($to_struct, $to), + memoffset::span_of!($to_struct, $to) + ), + ( + memoffset::offset_of!(c::$from_struct, $from), + memoffset::span_of!(c::$from_struct, $from) + ) + ); + }; +} + +/// For the common case of no renaming, check all fields of a struct. +macro_rules! check_struct { + ($name:ident, $($field:ident),*) => { + // Check the size and alignment. + check_type!($name); + + // Check that we have all the fields. + if false { + let _test = $name { + // SAFETY: This code is guarded by `if false`. + $($field: unsafe { core::mem::zeroed() }),* + }; + } + + // Check that the fields have the right sizes and offsets. + $(check_struct_field!($name, $field));* + }; +} diff --git a/vendor/rustix/src/clockid.rs b/vendor/rustix/src/clockid.rs new file mode 100644 index 000000000..84ae650a5 --- /dev/null +++ b/vendor/rustix/src/clockid.rs @@ -0,0 +1,105 @@ +use crate::backend::c; +use crate::fd::BorrowedFd; + +/// `CLOCK_*` constants for use with [`clock_gettime`]. +/// +/// These constants are always supported at runtime, so `clock_gettime` never +/// has to fail with `INVAL` due to an unsupported clock. See +/// [`DynamicClockId`] for a greater set of clocks, with the caveat that not +/// all of them are always supported. +/// +/// [`clock_gettime`]: crate::time::clock_gettime +#[cfg(not(any(apple, target_os = "wasi")))] +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +#[cfg_attr(not(target_os = "dragonfly"), repr(i32))] +#[cfg_attr(target_os = "dragonfly", repr(u64))] +#[non_exhaustive] +pub enum ClockId { + /// `CLOCK_REALTIME` + Realtime = c::CLOCK_REALTIME, + + /// `CLOCK_MONOTONIC` + Monotonic = c::CLOCK_MONOTONIC, + + /// `CLOCK_UPTIME` + #[cfg(any(freebsdlike, target_os = "openbsd"))] + Uptime = c::CLOCK_UPTIME, + + /// `CLOCK_PROCESS_CPUTIME_ID` + #[cfg(not(any(solarish, target_os = "netbsd", target_os = "redox")))] + ProcessCPUTime = c::CLOCK_PROCESS_CPUTIME_ID, + + /// `CLOCK_THREAD_CPUTIME_ID` + #[cfg(not(any(solarish, target_os = "netbsd", target_os = "redox")))] + ThreadCPUTime = c::CLOCK_THREAD_CPUTIME_ID, + + /// `CLOCK_REALTIME_COARSE` + #[cfg(any(linux_kernel, target_os = "freebsd"))] + RealtimeCoarse = c::CLOCK_REALTIME_COARSE, + + /// `CLOCK_MONOTONIC_COARSE` + #[cfg(any(linux_kernel, target_os = "freebsd"))] + MonotonicCoarse = c::CLOCK_MONOTONIC_COARSE, + + /// `CLOCK_MONOTONIC_RAW` + #[cfg(linux_kernel)] + MonotonicRaw = c::CLOCK_MONOTONIC_RAW, +} + +/// `CLOCK_*` constants for use with [`clock_gettime`]. +/// +/// These constants are always supported at runtime, so `clock_gettime` never +/// has to fail with `INVAL` due to an unsupported clock. See +/// [`DynamicClockId`] for a greater set of clocks, with the caveat that not +/// all of them are always supported. +#[cfg(apple)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +#[repr(u32)] +#[non_exhaustive] +pub enum ClockId { + /// `CLOCK_REALTIME` + Realtime = c::CLOCK_REALTIME, + + /// `CLOCK_MONOTONIC` + Monotonic = c::CLOCK_MONOTONIC, + + /// `CLOCK_PROCESS_CPUTIME_ID` + ProcessCPUTime = c::CLOCK_PROCESS_CPUTIME_ID, + + /// `CLOCK_THREAD_CPUTIME_ID` + ThreadCPUTime = c::CLOCK_THREAD_CPUTIME_ID, +} + +/// `CLOCK_*` constants for use with [`clock_gettime_dynamic`]. +/// +/// These constants may be unsupported at runtime, depending on the OS version, +/// and `clock_gettime_dynamic` may fail with `INVAL`. See [`ClockId`] for +/// clocks which are always supported at runtime. +/// +/// [`clock_gettime_dynamic`]: crate::time::clock_gettime_dynamic +#[cfg(not(target_os = "wasi"))] +#[derive(Debug, Copy, Clone)] +#[non_exhaustive] +pub enum DynamicClockId<'a> { + /// `ClockId` values that are always supported at runtime. + Known(ClockId), + + /// Linux dynamic clocks. + Dynamic(BorrowedFd<'a>), + + /// `CLOCK_REALTIME_ALARM`, available on Linux >= 3.0 + #[cfg(linux_kernel)] + RealtimeAlarm, + + /// `CLOCK_TAI`, available on Linux >= 3.10 + #[cfg(linux_kernel)] + Tai, + + /// `CLOCK_BOOTTIME`, available on Linux >= 2.6.39 + #[cfg(any(linux_kernel, target_os = "openbsd"))] + Boottime, + + /// `CLOCK_BOOTTIME_ALARM`, available on Linux >= 2.6.39 + #[cfg(linux_kernel)] + BoottimeAlarm, +} diff --git a/vendor/rustix/src/const_assert.rs b/vendor/rustix/src/const_assert.rs deleted file mode 100644 index c1dd5498c..000000000 --- a/vendor/rustix/src/const_assert.rs +++ /dev/null @@ -1,23 +0,0 @@ -/// A simple `assert` macro that works in `const fn`, for use until the -/// standard `assert` macro works in `const fn`. -/// -/// TODO: Replace this with just `assert!`, once that's stable for use in -/// a `const fn` context. -#[allow(unused_macros)] -macro_rules! const_assert { - ($x:expr) => { - let b: bool = $x; - let _ = [()][!b as usize]; - }; -} - -#[test] -#[allow(clippy::missing_const_for_fn)] -fn test_const_assert() { - const_assert!(true); -} - -#[test] -const fn test_const_assert_in_const_fn() { - const_assert!(true); -} diff --git a/vendor/rustix/src/cstr.rs b/vendor/rustix/src/cstr.rs index 01dbe7e2f..0df1bf7cd 100644 --- a/vendor/rustix/src/cstr.rs +++ b/vendor/rustix/src/cstr.rs @@ -13,9 +13,9 @@ /// # #[cfg(feature = "fs")] /// # fn main() -> rustix::io::Result<()> { /// use rustix::cstr; -/// use rustix::fs::{cwd, statat, AtFlags}; +/// use rustix::fs::{statat, AtFlags, CWD}; /// -/// let metadata = statat(cwd(), cstr!("test.txt"), AtFlags::empty())?; +/// let metadata = statat(CWD, cstr!("test.txt"), AtFlags::empty())?; /// # Ok(()) /// # } /// # #[cfg(not(feature = "fs"))] @@ -40,9 +40,9 @@ macro_rules! cstr { #[allow(unsafe_code, unused_unsafe)] { - // Now that we know the string doesn't have embedded NULs, we can call - // `from_bytes_with_nul_unchecked`, which as of this writing is defined - // as `#[inline]` and completely optimizes away. + // Now that we know the string doesn't have embedded NULs, we can + // call `from_bytes_with_nul_unchecked`, which as of this writing + // is defined as `#[inline]` and completely optimizes away. // // SAFETY: We have manually checked that the string does not contain // embedded NULs above, and we append or own NUL terminator here. diff --git a/vendor/rustix/src/event/eventfd.rs b/vendor/rustix/src/event/eventfd.rs new file mode 100644 index 000000000..a76f2cfcf --- /dev/null +++ b/vendor/rustix/src/event/eventfd.rs @@ -0,0 +1,20 @@ +use crate::fd::OwnedFd; +use crate::{backend, io}; + +pub use backend::event::types::EventfdFlags; + +/// `eventfd(initval, flags)`—Creates a file descriptor for event +/// notification. +/// +/// # References +/// - [Linux] +/// - [FreeBSD] +/// - [illumos] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/eventfd.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?eventfd +/// [illumos]: https://illumos.org/man/3C/eventfd +#[inline] +pub fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result { + backend::event::syscalls::eventfd(initval, flags) +} diff --git a/vendor/rustix/src/event/kqueue.rs b/vendor/rustix/src/event/kqueue.rs new file mode 100644 index 000000000..ff0ffddc0 --- /dev/null +++ b/vendor/rustix/src/event/kqueue.rs @@ -0,0 +1,431 @@ +//! An API for interfacing with `kqueue`. + +use crate::fd::{AsFd, OwnedFd, RawFd}; +use crate::pid::Pid; +use crate::signal::Signal; +use crate::{backend, io}; + +use backend::c::{self, intptr_t, kevent as kevent_t, uintptr_t}; +use backend::event::syscalls; + +use alloc::vec::Vec; +use core::mem::zeroed; +use core::ptr::slice_from_raw_parts_mut; +use core::time::Duration; + +/// A `kqueue` event. +#[repr(transparent)] +#[derive(Copy, Clone)] +pub struct Event { + // The layout varies between BSDs and macOS. + inner: kevent_t, +} + +impl Event { + /// Create a new `Event`. + #[allow(clippy::needless_update)] + pub fn new(filter: EventFilter, flags: EventFlags, udata: isize) -> Event { + let (ident, data, filter, fflags) = match filter { + EventFilter::Read(fd) => (fd as uintptr_t, 0, c::EVFILT_READ, 0), + EventFilter::Write(fd) => (fd as _, 0, c::EVFILT_WRITE, 0), + #[cfg(target_os = "freebsd")] + EventFilter::Empty(fd) => (fd as _, 0, c::EVFILT_EMPTY, 0), + EventFilter::Vnode { vnode, flags } => (vnode as _, 0, c::EVFILT_VNODE, flags.bits()), + EventFilter::Proc { pid, flags } => { + (Pid::as_raw(Some(pid)) as _, 0, c::EVFILT_PROC, flags.bits()) + } + EventFilter::Signal { signal, times: _ } => (signal as _, 0, c::EVFILT_SIGNAL, 0), + EventFilter::Timer { ident, timer } => { + #[cfg(any(apple, target_os = "freebsd", target_os = "netbsd"))] + let (data, fflags) = match timer { + Some(timer) => { + if timer.subsec_millis() == 0 { + (timer.as_secs() as _, c::NOTE_SECONDS) + } else if timer.subsec_nanos() == 0 { + (timer.as_micros() as _, c::NOTE_USECONDS) + } else { + (timer.as_nanos() as _, c::NOTE_NSECONDS) + } + } + None => (intptr_t::MAX, c::NOTE_SECONDS), + }; + #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] + let (data, fflags) = match timer { + Some(timer) => (timer.as_millis() as _, 0), + None => (intptr_t::MAX, 0), + }; + + (ident as _, data, c::EVFILT_TIMER, fflags) + } + #[cfg(any(apple, freebsdlike))] + EventFilter::User { + ident, + flags, + user_flags, + } => (ident as _, 0, c::EVFILT_USER, flags.bits() | user_flags.0), + EventFilter::Unknown => panic!("unknown filter"), + }; + + Event { + inner: kevent_t { + ident, + filter: filter as _, + flags: flags.bits() as _, + fflags, + data: { + // On openbsd, data is an i64 and not an isize + data as _ + }, + udata: { + // On netbsd, udata is an isize and not a pointer. + // TODO: Strict provenance, prevent int-to-ptr cast. + udata as _ + }, + ..unsafe { zeroed() } + }, + } + } + + /// Get the event flags for this event. + pub fn flags(&self) -> EventFlags { + EventFlags::from_bits_retain(self.inner.flags as _) + } + + /// Get the user data for this event. + pub fn udata(&self) -> isize { + // On netbsd, udata is an isize and not a pointer. + // TODO: Strict provenance, prevent ptr-to-int cast. + + self.inner.udata as _ + } + + /// Get the filter of this event. + pub fn filter(&self) -> EventFilter { + match self.inner.filter as _ { + c::EVFILT_READ => EventFilter::Read(self.inner.ident as _), + c::EVFILT_WRITE => EventFilter::Write(self.inner.ident as _), + #[cfg(target_os = "freebsd")] + c::EVFILT_EMPTY => EventFilter::Empty(self.inner.ident as _), + c::EVFILT_VNODE => EventFilter::Vnode { + vnode: self.inner.ident as _, + flags: VnodeEvents::from_bits_retain(self.inner.fflags), + }, + c::EVFILT_PROC => EventFilter::Proc { + pid: Pid::from_raw(self.inner.ident as _).unwrap(), + flags: ProcessEvents::from_bits_retain(self.inner.fflags), + }, + c::EVFILT_SIGNAL => EventFilter::Signal { + signal: Signal::from_raw(self.inner.ident as _).unwrap(), + times: self.inner.data as _, + }, + c::EVFILT_TIMER => EventFilter::Timer { + ident: self.inner.ident as _, + timer: { + let (data, fflags) = (self.inner.data, self.inner.fflags); + #[cfg(not(any(apple, target_os = "freebsd", target_os = "netbsd")))] + let _ = fflags; + #[cfg(any(apple, target_os = "freebsd", target_os = "netbsd"))] + match fflags as _ { + c::NOTE_SECONDS => Some(Duration::from_secs(data as _)), + c::NOTE_USECONDS => Some(Duration::from_micros(data as _)), + c::NOTE_NSECONDS => Some(Duration::from_nanos(data as _)), + _ => { + // Unknown timer flags. + None + } + } + #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] + Some(Duration::from_millis(data as _)) + }, + }, + #[cfg(any(apple, freebsdlike))] + c::EVFILT_USER => EventFilter::User { + ident: self.inner.ident as _, + flags: UserFlags::from_bits_retain(self.inner.fflags), + user_flags: UserDefinedFlags(self.inner.fflags & EVFILT_USER_FLAGS), + }, + _ => EventFilter::Unknown, + } + } +} + +/// Bottom 24 bits of a u32. +#[cfg(any(apple, freebsdlike))] +const EVFILT_USER_FLAGS: u32 = 0x00ff_ffff; + +/// The possible filters for a `kqueue`. +#[repr(i16)] +#[non_exhaustive] +pub enum EventFilter { + /// A read filter. + Read(RawFd), + + /// A write filter. + Write(RawFd), + + /// An empty filter. + #[cfg(target_os = "freebsd")] + Empty(RawFd), + + /// A VNode filter. + Vnode { + /// The file descriptor we looked for events in. + vnode: RawFd, + + /// The flags for this event. + flags: VnodeEvents, + }, + + /// A process filter. + Proc { + /// The process ID we waited on. + pid: Pid, + + /// The flags for this event. + flags: ProcessEvents, + }, + + /// A signal filter. + Signal { + /// The signal number we waited on. + signal: Signal, + + /// The number of times the signal has been + /// received since the last call to kevent. + times: usize, + }, + + /// A timer filter. + Timer { + /// The identifier for this event. + ident: intptr_t, + + /// The duration for this event. + timer: Option, + }, + + /// A user filter. + #[cfg(any(apple, freebsdlike))] + User { + /// The identifier for this event. + ident: intptr_t, + + /// The flags for this event. + flags: UserFlags, + + /// The user-defined flags for this event. + user_flags: UserDefinedFlags, + }, + + /// This filter is unknown. + /// + /// # Panics + /// + /// Passing this into `Event::new()` will result in a panic. + Unknown, +} + +bitflags::bitflags! { + /// The flags for a `kqueue` event specifying actions to perform. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct EventFlags: u16 { + /// Add the event to the `kqueue`. + const ADD = c::EV_ADD as _; + + /// Enable the event. + const ENABLE = c::EV_ENABLE as _; + + /// Disable the event. + const DISABLE = c::EV_DISABLE as _; + + /// Delete the event from the `kqueue`. + const DELETE = c::EV_DELETE as _; + + /// TODO + const RECEIPT = c::EV_RECEIPT as _; + + /// Clear the event after it is triggered. + const ONESHOT = c::EV_ONESHOT as _; + + /// TODO + const CLEAR = c::EV_CLEAR as _; + + /// TODO + const EOF = c::EV_EOF as _; + + /// TODO + const ERROR = c::EV_ERROR as _; + } +} + +bitflags::bitflags! { + /// The flags for a virtual node event. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct VnodeEvents: u32 { + /// The file was deleted. + const DELETE = c::NOTE_DELETE; + + /// The file was written to. + const WRITE = c::NOTE_WRITE; + + /// The file was extended. + const EXTEND = c::NOTE_EXTEND; + + /// The file had its attributes changed. + const ATTRIBUTES = c::NOTE_ATTRIB; + + /// The file was renamed. + const RENAME = c::NOTE_RENAME; + + /// Access to the file was revoked. + const REVOKE = c::NOTE_REVOKE; + + /// The link count of the file has changed. + const LINK = c::NOTE_LINK; + } +} + +bitflags::bitflags! { + /// The flags for a process event. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct ProcessEvents: u32 { + /// The process exited. + const EXIT = c::NOTE_EXIT; + + /// The process forked itself. + const FORK = c::NOTE_FORK; + + /// The process executed a new process. + const EXEC = c::NOTE_EXEC; + + /// Follow the process through `fork()` calls (write only). + const TRACK = c::NOTE_TRACK; + + /// An error has occurred with following the process. + const TRACKERR = c::NOTE_TRACKERR; + } +} + +#[cfg(any(apple, freebsdlike))] +bitflags::bitflags! { + /// The flags for a user event. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct UserFlags: u32 { + /// Ignore the user input flags. + const NOINPUT = c::NOTE_FFNOP; + + /// Bitwise AND `fflags`. + const AND = c::NOTE_FFAND; + + /// Bitwise OR `fflags`. + const OR = c::NOTE_FFOR; + + /// Copy `fflags`. + const COPY = c::NOTE_FFCOPY; + + /// Control mask for operations. + const CTRLMASK = c::NOTE_FFCTRLMASK; + + /// User defined flags for masks. + const UDFMASK = c::NOTE_FFLAGSMASK; + + /// Trigger the event. + const TRIGGER = c::NOTE_TRIGGER; + } +} + +/// User-defined flags. +/// +/// Only the lower 24 bits are used in this struct. +#[repr(transparent)] +#[cfg(any(apple, freebsdlike))] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct UserDefinedFlags(u32); + +#[cfg(any(apple, freebsdlike))] +impl UserDefinedFlags { + /// Create a new `UserDefinedFlags` from a `u32`. + pub fn new(flags: u32) -> Self { + Self(flags & EVFILT_USER_FLAGS) + } + + /// Get the underlying `u32`. + pub fn get(self) -> u32 { + self.0 + } +} + +/// `kqueue()`—Create a new `kqueue` file descriptor. +/// +/// # References +/// - [Apple] +/// - [FreeBSD] +/// - [OpenBSD] +/// - [NetBSD] +/// - [DragonFly BSD] +/// +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/kqueue.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2 +/// [OpenBSD]: https://man.openbsd.org/kqueue.2 +/// [NetBSD]: https://man.netbsd.org/kqueue.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=kqueue§ion=2 +pub fn kqueue() -> io::Result { + syscalls::kqueue() +} + +/// `kevent(kqueue, changelist, eventlist, timeout)`—Wait for events on a +/// `kqueue`. +/// +/// Note: in order to receive events, make sure to allocate capacity in the +/// eventlist! Otherwise, the function will return immediately. +/// +/// # Safety +/// +/// The file descriptors referred to by the `Event` structs must be valid for +/// the lifetime of the `kqueue` file descriptor. +/// +/// # References +/// - [Apple] +/// - [FreeBSD] +/// - [OpenBSD] +/// - [NetBSD] +/// - [DragonFly BSD] +/// +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/kevent.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=kevent&sektion=2 +/// [OpenBSD]: https://man.openbsd.org/kevent.2 +/// [NetBSD]: https://man.netbsd.org/kevent.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=kevent§ion=2 +pub unsafe fn kevent( + kqueue: impl AsFd, + changelist: &[Event], + eventlist: &mut Vec, + timeout: Option, +) -> io::Result { + let timeout = timeout.map(|timeout| backend::c::timespec { + tv_sec: timeout.as_secs() as _, + tv_nsec: timeout.subsec_nanos() as _, + }); + + // Populate the event list with events. + eventlist.set_len(0); + let out_slice = slice_from_raw_parts_mut(eventlist.as_mut_ptr().cast(), eventlist.capacity()); + let res = syscalls::kevent( + kqueue.as_fd(), + changelist, + &mut *out_slice, + timeout.as_ref(), + ) + .map(|res| res as _); + + // Update the event list. + if let Ok(len) = res { + eventlist.set_len(len); + } + + res +} diff --git a/vendor/rustix/src/event/mod.rs b/vendor/rustix/src/event/mod.rs new file mode 100644 index 000000000..192afdcaa --- /dev/null +++ b/vendor/rustix/src/event/mod.rs @@ -0,0 +1,15 @@ +//! Event operations. + +#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "illumos"))] +mod eventfd; +#[cfg(bsd)] +pub mod kqueue; +mod poll; +#[cfg(solarish)] +pub mod port; + +#[cfg(linux_kernel)] +pub use crate::backend::event::epoll; +#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "illumos"))] +pub use eventfd::{eventfd, EventfdFlags}; +pub use poll::{poll, PollFd, PollFlags}; diff --git a/vendor/rustix/src/event/poll.rs b/vendor/rustix/src/event/poll.rs new file mode 100644 index 000000000..2ee40521f --- /dev/null +++ b/vendor/rustix/src/event/poll.rs @@ -0,0 +1,32 @@ +use crate::{backend, io}; + +pub use backend::event::poll_fd::{PollFd, PollFlags}; + +/// `poll(self.fds, timeout)` +/// +/// # References +/// - [Beej's Guide to Network Programming] +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [Winsock2] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/slightly-advanced-techniques.html#poll +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html +/// [Linux]: https://man7.org/linux/man-pages/man2/poll.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/poll.2.html +/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsapoll +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=poll&sektion=2 +/// [NetBSD]: https://man.netbsd.org/poll.2 +/// [OpenBSD]: https://man.openbsd.org/poll.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=poll§ion=2 +/// [illumos]: https://illumos.org/man/2/poll +#[inline] +pub fn poll(fds: &mut [PollFd<'_>], timeout: i32) -> io::Result { + backend::event::syscalls::poll(fds, timeout) +} diff --git a/vendor/rustix/src/event/port.rs b/vendor/rustix/src/event/port.rs new file mode 100644 index 000000000..b04f7c496 --- /dev/null +++ b/vendor/rustix/src/event/port.rs @@ -0,0 +1,150 @@ +//! Solaris/illumos event ports. + +use crate::backend::c; +use crate::backend::event::syscalls; +use crate::fd::{AsFd, AsRawFd, OwnedFd}; +use crate::io; + +use super::PollFlags; + +use core::time::Duration; + +/// The structure representing a port event. +#[repr(transparent)] +pub struct Event(pub(crate) c::port_event); + +impl Event { + /// Get the events associated with this event. + pub fn events(&self) -> i32 { + self.0.portev_events + } + + /// Get the event source associated with this event. + pub fn object(&self) -> usize { + self.0.portev_object + } + + /// Get the userdata associated with this event. + pub fn userdata(&self) -> *mut c::c_void { + self.0.portev_user + } +} + +/// `port_create()`—Creates a new port. +/// +/// # References +/// - [OpenSolaris] +/// - [illumos] +/// +/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_create/ +/// [illumos]: https://illumos.org/man/3C/port_create +pub fn port_create() -> io::Result { + syscalls::port_create() +} + +/// `port_associate(_, PORT_SOURCE_FD, _, _, _)`—Associates a file descriptor +/// with a port. +/// +/// # Safety +/// +/// Any `object`s passed into the `port` must be valid for the lifetime of the +/// `port`. Logically, `port` keeps a borrowed reference to the `object` until +/// it is removed via `port_dissociate_fd`. +/// +/// # References +/// - [OpenSolaris] +/// - [illumos] +/// +/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_associate/ +/// [illumos]: https://illumos.org/man/3C/port_associate +pub unsafe fn port_associate_fd( + port: impl AsFd, + object: impl AsRawFd, + events: PollFlags, + userdata: *mut c::c_void, +) -> io::Result<()> { + syscalls::port_associate( + port.as_fd(), + c::PORT_SOURCE_FD, + object.as_raw_fd() as _, + events.bits() as _, + userdata.cast(), + ) +} + +/// `port_dissociate(_, PORT_SOURCE_FD, _)`—Dissociates a file descriptor from +/// a port. +/// +/// # Safety +/// +/// The file descriptor passed into this function must have been previously +/// associated with the port via [`port_associate_fd`]. +/// +/// # References +/// - [OpenSolaris] +/// - [illumos] +/// +/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_dissociate +/// [illumos]: https://illumos.org/man/3C/port_dissociate +pub unsafe fn port_dissociate_fd(port: impl AsFd, object: impl AsRawFd) -> io::Result<()> { + syscalls::port_dissociate(port.as_fd(), c::PORT_SOURCE_FD, object.as_raw_fd() as _) +} + +/// `port_get(port, timeout)`—Gets an event from a port. +/// +/// # References +/// - [OpenSolaris] +/// - [illumos] +/// +/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_get/ +/// [illumos]: https://illumos.org/man/3C/port_get +pub fn port_get(port: impl AsFd, timeout: Option) -> io::Result { + let mut timeout = timeout.map(|timeout| c::timespec { + tv_sec: timeout.as_secs().try_into().unwrap(), + tv_nsec: timeout.subsec_nanos() as _, + }); + + syscalls::port_get(port.as_fd(), timeout.as_mut()) +} + +/// `port_getn(port, events, min_events, timeout)`—Gets multiple events from a +/// port. +/// +/// # References +/// - [OpenSolaris] +/// - [illumos] +/// +/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_getn/ +/// [illumos]: https://illumos.org/man/3C/port_getn +pub fn port_getn( + port: impl AsFd, + events: &mut Vec, + min_events: usize, + timeout: Option, +) -> io::Result<()> { + events.clear(); + + let mut timeout = timeout.map(|timeout| c::timespec { + tv_sec: timeout.as_secs().try_into().unwrap(), + tv_nsec: timeout.subsec_nanos() as _, + }); + + syscalls::port_getn( + port.as_fd(), + timeout.as_mut(), + events, + min_events.try_into().unwrap(), + ) +} + +/// `port_send(port, events, userdata)`—Sends an event to a port. +/// +/// # References +/// - [OpenSolaris] +/// - [illumos] +/// +/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_send/ +/// [illumos]: https://illumos.org/man/3C/port_send +pub fn port_send(port: impl AsFd, events: i32, userdata: *mut c::c_void) -> io::Result<()> { + syscalls::port_send(port.as_fd(), events, userdata.cast()) +} diff --git a/vendor/rustix/src/ffi.rs b/vendor/rustix/src/ffi.rs new file mode 100644 index 000000000..bd04a9cb4 --- /dev/null +++ b/vendor/rustix/src/ffi.rs @@ -0,0 +1,16 @@ +//! Utilities related to FFI bindings. + +// If we have std, use it. +#[cfg(feature = "std")] +pub use { + std::ffi::{CStr, CString, FromBytesWithNulError, NulError}, + std::os::raw::c_char, +}; + +// If we don't have std, we can depend on core and alloc having these features +// in Rust 1.64+. +#[cfg(not(feature = "std"))] +pub use { + alloc::ffi::{CString, NulError}, + core::ffi::{c_char, CStr, FromBytesWithNulError}, +}; diff --git a/vendor/rustix/src/ffi/mod.rs b/vendor/rustix/src/ffi/mod.rs deleted file mode 100644 index eb9983610..000000000 --- a/vendor/rustix/src/ffi/mod.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! Utilities related to FFI bindings. - -// If we have std, use it. -#[cfg(feature = "std")] -pub use { - std::ffi::{CStr, CString, FromBytesWithNulError, NulError}, - std::os::raw::c_char, -}; - -// If we don't have std, we can depend on core and alloc having these features -// in new versions of Rust. -#[cfg(not(feature = "std"))] -pub use { - alloc::ffi::{CString, NulError}, - core::ffi::{c_char, CStr, FromBytesWithNulError}, -}; diff --git a/vendor/rustix/src/fs/abs.rs b/vendor/rustix/src/fs/abs.rs index 314895006..83531a4e7 100644 --- a/vendor/rustix/src/fs/abs.rs +++ b/vendor/rustix/src/fs/abs.rs @@ -1,5 +1,7 @@ //! POSIX-style filesystem functions which operate on bare paths. +use crate::fd::OwnedFd; +use crate::ffi::{CStr, CString}; #[cfg(not(any( solarish, target_os = "haiku", @@ -9,10 +11,214 @@ )))] use crate::fs::StatFs; #[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] -use { - crate::fs::StatVfs, - crate::{backend, io, path}, -}; +use crate::fs::StatVfs; +use crate::fs::{Access, Mode, OFlags, Stat}; +use crate::path::SMALL_PATH_BUFFER_SIZE; +use crate::{backend, io, path}; +use alloc::vec::Vec; + +/// `open(path, oflags, mode)`—Opens a file. +/// +/// POSIX guarantees that `open` will use the lowest unused file descriptor, +/// however it is not safe in general to rely on this, as file descriptors may +/// be unexpectedly allocated on other threads or in libraries. +/// +/// The `Mode` argument is only significant when creating a file. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html +/// [Linux]: https://man7.org/linux/man-pages/man2/open.2.html +#[inline] +pub fn open(path: P, flags: OFlags, mode: Mode) -> io::Result { + path.into_with_c_str(|path| backend::fs::syscalls::open(path, flags, mode)) +} + +/// `chmod(path, mode)`—Sets file or directory permissions. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/chmod.html +/// [Linux]: https://man7.org/linux/man-pages/man2/chmod.2.html +#[cfg(not(target_os = "wasi"))] +#[inline] +pub fn chmod(path: P, mode: Mode) -> io::Result<()> { + path.into_with_c_str(|path| backend::fs::syscalls::chmod(path, mode)) +} + +/// `stat(path)`—Queries metadata for a file or directory. +/// +/// [`Mode::from_raw_mode`] and [`FileType::from_raw_mode`] may be used to +/// interpret the `st_mode` field. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stat.html +/// [Linux]: https://man7.org/linux/man-pages/man2/stat.2.html +/// [`Mode::from_raw_mode`]: crate::fs::Mode::from_raw_mode +/// [`FileType::from_raw_mode`]: crate::fs::FileType::from_raw_mode +#[inline] +pub fn stat(path: P) -> io::Result { + path.into_with_c_str(backend::fs::syscalls::stat) +} + +/// `lstat(path)`—Queries metadata for a file or directory, without following +/// symlinks. +/// +/// [`Mode::from_raw_mode`] and [`FileType::from_raw_mode`] may be used to +/// interpret the `st_mode` field. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/lstat.html +/// [Linux]: https://man7.org/linux/man-pages/man2/lstat.2.html +/// [`Mode::from_raw_mode`]: crate::fs::Mode::from_raw_mode +/// [`FileType::from_raw_mode`]: crate::fs::FileType::from_raw_mode +#[inline] +pub fn lstat(path: P) -> io::Result { + path.into_with_c_str(backend::fs::syscalls::lstat) +} + +/// `readlink(path)`—Reads the contents of a symlink. +/// +/// If `reuse` is non-empty, reuse its buffer to store the result if possible. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html +/// [Linux]: https://man7.org/linux/man-pages/man2/readlink.2.html +#[inline] +pub fn readlink>>(path: P, reuse: B) -> io::Result { + path.into_with_c_str(|path| _readlink(path, reuse.into())) +} + +fn _readlink(path: &CStr, mut buffer: Vec) -> io::Result { + // This code would benefit from having a better way to read into + // uninitialized memory, but that requires `unsafe`. + buffer.clear(); + buffer.reserve(SMALL_PATH_BUFFER_SIZE); + buffer.resize(buffer.capacity(), 0_u8); + + loop { + let nread = backend::fs::syscalls::readlink(path, &mut buffer)?; + + let nread = nread as usize; + assert!(nread <= buffer.len()); + if nread < buffer.len() { + buffer.resize(nread, 0_u8); + return Ok(CString::new(buffer).unwrap()); + } + buffer.reserve(1); // use `Vec` reallocation strategy to grow capacity exponentially + buffer.resize(buffer.capacity(), 0_u8); + } +} + +/// `rename(old_path, new_path)`—Renames a file or directory. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/rename.html +/// [Linux]: https://man7.org/linux/man-pages/man2/rename.2.html +#[inline] +pub fn rename(old_path: P, new_path: Q) -> io::Result<()> { + old_path.into_with_c_str(|old_path| { + new_path.into_with_c_str(|new_path| backend::fs::syscalls::rename(old_path, new_path)) + }) +} + +/// `unlink(path)`—Unlinks a file. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html +/// [Linux]: https://man7.org/linux/man-pages/man2/unlink.2.html +#[inline] +pub fn unlink(path: P) -> io::Result<()> { + path.into_with_c_str(backend::fs::syscalls::unlink) +} + +/// `rmdir(path)`—Removes a directory. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/rmdir.html +/// [Linux]: https://man7.org/linux/man-pages/man2/rmdir.2.html +#[inline] +pub fn rmdir(path: P) -> io::Result<()> { + path.into_with_c_str(backend::fs::syscalls::rmdir) +} + +/// `link(old_path, new_path)`—Creates a hard link. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/link.html +/// [Linux]: https://man7.org/linux/man-pages/man2/link.2.html +#[inline] +pub fn link(old_path: P, new_path: Q) -> io::Result<()> { + old_path.into_with_c_str(|old_path| { + new_path.into_with_c_str(|new_path| backend::fs::syscalls::link(old_path, new_path)) + }) +} + +/// `symlink(old_path, new_path)`—Creates a symlink. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlink.html +/// [Linux]: https://man7.org/linux/man-pages/man2/symlink.2.html +#[inline] +pub fn symlink(old_path: P, new_path: Q) -> io::Result<()> { + old_path.into_with_c_str(|old_path| { + new_path.into_with_c_str(|new_path| backend::fs::syscalls::symlink(old_path, new_path)) + }) +} + +/// `mkdir(path, mode)`—Creates a directory. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdir.html +/// [Linux]: https://man7.org/linux/man-pages/man2/mkdir.2.html +#[inline] +pub fn mkdir(path: P, mode: Mode) -> io::Result<()> { + path.into_with_c_str(|path| backend::fs::syscalls::mkdir(path, mode)) +} + +/// `access(path, access)`—Tests permissions for a file or directory. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/access.html +/// [Linux]: https://man7.org/linux/man-pages/man2/access.2.html +#[inline] +pub fn access(path: P, access: Access) -> io::Result<()> { + path.into_with_c_str(|path| backend::fs::syscalls::access(path, access)) +} /// `statfs`—Queries filesystem metadata. /// diff --git a/vendor/rustix/src/fs/at.rs b/vendor/rustix/src/fs/at.rs index 2314cf763..0c99cc30a 100644 --- a/vendor/rustix/src/fs/at.rs +++ b/vendor/rustix/src/fs/at.rs @@ -1,9 +1,9 @@ //! POSIX-style `*at` functions. //! //! The `dirfd` argument to these functions may be a file descriptor for a -//! directory, or the special value returned by [`cwd`]. +//! directory, or the special value [`CWD`]. //! -//! [`cwd`]: crate::fs::cwd +//! [`cwd`]: crate::fs::cwd::CWD use crate::fd::OwnedFd; use crate::ffi::{CStr, CString}; @@ -11,16 +11,16 @@ use crate::ffi::{CStr, CString}; use crate::fs::CloneFlags; #[cfg(not(any(apple, target_os = "wasi")))] use crate::fs::FileType; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] use crate::fs::RenameFlags; use crate::fs::{Access, AtFlags, Mode, OFlags, Stat, Timestamps}; -use crate::path::SMALL_PATH_BUFFER_SIZE; #[cfg(not(target_os = "wasi"))] -use crate::process::{Gid, Uid}; +use crate::fs::{Gid, Uid}; +use crate::path::SMALL_PATH_BUFFER_SIZE; +use crate::timespec::Nsecs; use crate::{backend, io, path}; use alloc::vec::Vec; use backend::fd::{AsFd, BorrowedFd}; -use backend::time::types::Nsecs; pub use backend::fs::types::{Dev, RawMode}; @@ -49,7 +49,7 @@ pub const UTIME_OMIT: Nsecs = backend::c::UTIME_OMIT as Nsecs; /// - [Linux] /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/openat.html -/// [Linux]: https://man7.org/linux/man-pages/man2/open.2.html +/// [Linux]: https://man7.org/linux/man-pages/man2/openat.2.html #[inline] pub fn openat( dirfd: Fd, @@ -64,7 +64,7 @@ pub fn openat( /// `readlinkat(fd, path)`—Reads the contents of a symlink. /// -/// If `reuse` is non-empty, reuse its buffer to store the result if possible. +/// If `reuse` already has available capacity, reuse it if possible. /// /// # References /// - [POSIX] @@ -81,24 +81,44 @@ pub fn readlinkat>>( path.into_with_c_str(|path| _readlinkat(dirfd.as_fd(), path, reuse.into())) } +#[allow(unsafe_code)] fn _readlinkat(dirfd: BorrowedFd<'_>, path: &CStr, mut buffer: Vec) -> io::Result { - // This code would benefit from having a better way to read into - // uninitialized memory, but that requires `unsafe`. buffer.clear(); buffer.reserve(SMALL_PATH_BUFFER_SIZE); - buffer.resize(buffer.capacity(), 0_u8); loop { - let nread = backend::fs::syscalls::readlinkat(dirfd.as_fd(), path, &mut buffer)?; + let nread = + backend::fs::syscalls::readlinkat(dirfd.as_fd(), path, buffer.spare_capacity_mut())?; + + debug_assert!(nread <= buffer.capacity()); + if nread < buffer.capacity() { + // SAFETY from the man page: + // "On success, these calls return the number of bytes placed in buf." + unsafe { + buffer.set_len(nread); + } - let nread = nread as usize; - assert!(nread <= buffer.len()); - if nread < buffer.len() { - buffer.resize(nread, 0_u8); - return Ok(CString::new(buffer).unwrap()); + // SAFETY: + // - "readlink places the contents of the symbolic link pathname in the buffer + // buf" + // - [POSIX definition 3.271: Pathname]: "A string that is used to identify a + // file." + // - [POSIX definition 3.375: String]: "A contiguous sequence of bytes + // terminated by and including the first null byte." + // - "readlink does not append a terminating null byte to buf." + // + // Thus, there will be no NUL bytes in the string. + // + // [POSIX definition 3.271: Pathname]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_271 + // [POSIX definition 3.375: String]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_375 + unsafe { + return Ok(CString::from_vec_unchecked(buffer)); + } } - buffer.reserve(1); // use `Vec` reallocation strategy to grow capacity exponentially - buffer.resize(buffer.capacity(), 0_u8); + + buffer.reserve(buffer.capacity() + 1); // use `Vec` reallocation + // strategy to grow capacity + // exponentially } } @@ -197,7 +217,7 @@ pub fn renameat( /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/renameat2.2.html -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] #[doc(alias = "renameat2")] pub fn renameat_with( @@ -263,6 +283,13 @@ pub fn statat(dirfd: Fd, path: P, flags: AtFlags) -> io: /// `faccessat(dirfd, path, access, flags)`—Tests permissions for a file or /// directory. /// +/// On Linux before 5.8, this function uses the `faccessat` system call which +/// doesn't support any flags. This function emulates support for the +/// [`AtFlags::EACCESS`] flag by checking whether the uid and gid of the +/// process match the effective uid and gid, in which case the `EACCESS` flag +/// can be ignored. In Linux 5.8 and beyond `faccessat2` is used, which +/// supports flags. +/// /// # References /// - [POSIX] /// - [Linux] @@ -298,23 +325,6 @@ pub fn utimensat( path.into_with_c_str(|path| backend::fs::syscalls::utimensat(dirfd.as_fd(), path, times, flags)) } -/// `fchmodat(dirfd, path, mode, 0)`—Sets file or directory permissions. -/// -/// See `fchmodat_with` for a version that does take flags. -/// -/// # References -/// - [POSIX] -/// - [Linux] -/// -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html -/// [Linux]: https://man7.org/linux/man-pages/man2/fchmodat.2.html -#[cfg(not(target_os = "wasi"))] -#[inline] -#[doc(alias = "fchmodat")] -pub fn chmodat(dirfd: Fd, path: P, mode: Mode) -> io::Result<()> { - chmodat_with(dirfd, path, mode, AtFlags::empty()) -} - /// `fchmodat(dirfd, path, mode, flags)`—Sets file or directory permissions. /// /// Platform support for flags varies widely, for example on Linux @@ -329,8 +339,8 @@ pub fn chmodat(dirfd: Fd, path: P, mode: Mode) -> io::Re /// [Linux]: https://man7.org/linux/man-pages/man2/fchmodat.2.html #[cfg(not(target_os = "wasi"))] #[inline] -#[doc(alias = "fchmodat_with")] -pub fn chmodat_with( +#[doc(alias = "fchmodat")] +pub fn chmodat( dirfd: Fd, path: P, mode: Mode, diff --git a/vendor/rustix/src/fs/constants.rs b/vendor/rustix/src/fs/constants.rs index 3ccc383bb..ef677aa49 100644 --- a/vendor/rustix/src/fs/constants.rs +++ b/vendor/rustix/src/fs/constants.rs @@ -11,7 +11,7 @@ pub use backend::fs::types::AtFlags; #[cfg(apple)] pub use backend::fs::types::{CloneFlags, CopyfileFlags}; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use backend::fs::types::*; -pub use backend::time::types::{Nsecs, Secs, Timespec}; +pub use crate::timespec::{Nsecs, Secs, Timespec}; diff --git a/vendor/rustix/src/fs/cwd.rs b/vendor/rustix/src/fs/cwd.rs index 0abd75df6..2745060a1 100644 --- a/vendor/rustix/src/fs/cwd.rs +++ b/vendor/rustix/src/fs/cwd.rs @@ -8,23 +8,32 @@ #![allow(unsafe_code)] use crate::backend; +use backend::c; use backend::fd::{BorrowedFd, RawFd}; -/// `AT_FDCWD`—Returns a handle representing the current working directory. +/// `AT_FDCWD`—A handle representing the current working directory. /// -/// This returns a file descriptor which refers to the process current -/// directory which can be used as the directory argument in `*at` -/// functions such as [`openat`]. +/// This is a file descriptor which refers to the process current directory +/// which can be used as the directory argument in `*at` functions such as +/// [`openat`]. /// /// # References /// - [POSIX] /// /// [`openat`]: crate::fs::openat /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fcntl.h.html -#[inline] +// SAFETY: `AT_FDCWD` is a reserved value that is never dynamically +// allocated, so it'll remain valid for the duration of `'static`. #[doc(alias = "AT_FDCWD")] +#[cfg(not(target_os = "haiku"))] // Haiku needs +pub const CWD: BorrowedFd<'static> = + unsafe { BorrowedFd::<'static>::borrow_raw(c::AT_FDCWD as RawFd) }; + +/// Return the value of [`CWD`]. +#[deprecated(note = "Use `CWD` in place of `cwd()`.")] +#[cfg(not(target_os = "haiku"))] // Haiku needs pub const fn cwd() -> BorrowedFd<'static> { - let at_fdcwd = backend::io::types::AT_FDCWD as RawFd; + let at_fdcwd = c::AT_FDCWD as RawFd; // SAFETY: `AT_FDCWD` is a reserved value that is never dynamically // allocated, so it'll remain valid for the duration of `'static`. diff --git a/vendor/rustix/src/fs/fcntl.rs b/vendor/rustix/src/fs/fcntl.rs index 0f557ef7f..91816aaa2 100644 --- a/vendor/rustix/src/fs/fcntl.rs +++ b/vendor/rustix/src/fs/fcntl.rs @@ -55,24 +55,14 @@ pub fn fcntl_setfl(fd: Fd, flags: OFlags) -> io::Result<()> { /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))] #[inline] #[doc(alias = "F_GET_SEALS")] pub fn fcntl_get_seals(fd: Fd) -> io::Result { backend::fs::syscalls::fcntl_get_seals(fd.as_fd()) } -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))] pub use backend::fs::types::SealFlags; /// `fcntl(fd, F_ADD_SEALS)` @@ -81,12 +71,7 @@ pub use backend::fs::types::SealFlags; /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))] #[inline] #[doc(alias = "F_ADD_SEALS")] pub fn fcntl_add_seals(fd: Fd, seals: SealFlags) -> io::Result<()> { diff --git a/vendor/rustix/src/fs/fd.rs b/vendor/rustix/src/fs/fd.rs index 81e56d909..d0d50073e 100644 --- a/vendor/rustix/src/fs/fd.rs +++ b/vendor/rustix/src/fs/fd.rs @@ -2,9 +2,9 @@ #[cfg(not(target_os = "wasi"))] use crate::fs::Mode; -use crate::io::SeekFrom; #[cfg(not(target_os = "wasi"))] -use crate::process::{Gid, Uid}; +use crate::fs::{Gid, Uid}; +use crate::fs::{OFlags, SeekFrom, Timespec}; use crate::{backend, io}; use backend::fd::{AsFd, BorrowedFd}; @@ -34,7 +34,7 @@ pub use backend::fs::types::StatFs; #[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] pub use backend::fs::types::{StatVfs, StatVfsMountFlags}; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use backend::fs::types::FsWord; /// Timestamps used by [`utimensat`] and [`futimens`]. @@ -47,10 +47,10 @@ pub use backend::fs::types::FsWord; #[derive(Clone, Debug)] pub struct Timestamps { /// The timestamp of the last access to a filesystem object. - pub last_access: crate::fs::Timespec, + pub last_access: Timespec, /// The timestamp of the last modification of a filesystem object. - pub last_modification: crate::fs::Timespec, + pub last_modification: Timespec, } /// The filesystem magic number for procfs. @@ -58,7 +58,7 @@ pub struct Timestamps { /// See [the `fstatfs` manual page] for more information. /// /// [the `fstatfs` manual page]: https://man7.org/linux/man-pages/man2/fstatfs.2.html#DESCRIPTION -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub const PROC_SUPER_MAGIC: FsWord = backend::c::PROC_SUPER_MAGIC as FsWord; /// The filesystem magic number for NFS. @@ -66,7 +66,7 @@ pub const PROC_SUPER_MAGIC: FsWord = backend::c::PROC_SUPER_MAGIC as FsWord; /// See [the `fstatfs` manual page] for more information. /// /// [the `fstatfs` manual page]: https://man7.org/linux/man-pages/man2/fstatfs.2.html#DESCRIPTION -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub const NFS_SUPER_MAGIC: FsWord = backend::c::NFS_SUPER_MAGIC as FsWord; /// `lseek(fd, offset, whence)`—Repositions a file descriptor within a file. @@ -143,7 +143,7 @@ pub fn fchown(fd: Fd, owner: Option, group: Option) -> io::R /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fstat.html /// [Linux]: https://man7.org/linux/man-pages/man2/fstat.2.html -/// [`Mode::from_raw_mode`]: crate::fs::Mode::from_raw_mode +/// [`Mode::from_raw_mode`]: Mode::from_raw_mode /// [`FileType::from_raw_mode`]: crate::fs::FileType::from_raw_mode #[inline] pub fn fstat(fd: Fd) -> io::Result { @@ -247,22 +247,17 @@ pub(crate) fn _is_file_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool) let mode = backend::fs::syscalls::fcntl_getfl(fd)?; // Check for `O_PATH`. - #[cfg(any( - target_os = "android", - target_os = "fuchsia", - target_os = "linux", - target_os = "emscripten", - ))] - if mode.contains(crate::fs::OFlags::PATH) { + #[cfg(any(linux_kernel, target_os = "fuchsia", target_os = "emscripten"))] + if mode.contains(OFlags::PATH) { return Ok((false, false)); } // Use `RWMODE` rather than `ACCMODE` as `ACCMODE` may include `O_PATH`. // We handled `O_PATH` above. - match mode & crate::fs::OFlags::RWMODE { - crate::fs::OFlags::RDONLY => Ok((true, false)), - crate::fs::OFlags::RDWR => Ok((true, true)), - crate::fs::OFlags::WRONLY => Ok((false, true)), + match mode & OFlags::RWMODE { + OFlags::RDONLY => Ok((true, false)), + OFlags::RDWR => Ok((true, true)), + OFlags::WRONLY => Ok((false, true)), _ => unreachable!(), } } @@ -336,7 +331,7 @@ pub fn flock(fd: Fd, operation: FlockOperation) -> io::Result<()> { /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/syncfs.2.html -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] pub fn syncfs(fd: Fd) -> io::Result<()> { backend::fs::syscalls::syncfs(fd.as_fd()) diff --git a/vendor/rustix/src/fs/id.rs b/vendor/rustix/src/fs/id.rs new file mode 100644 index 000000000..1fc2ef81f --- /dev/null +++ b/vendor/rustix/src/fs/id.rs @@ -0,0 +1 @@ +pub use crate::ugid::{Gid, Uid}; diff --git a/vendor/rustix/src/fs/ioctl.rs b/vendor/rustix/src/fs/ioctl.rs new file mode 100644 index 000000000..28e0c8588 --- /dev/null +++ b/vendor/rustix/src/fs/ioctl.rs @@ -0,0 +1,50 @@ +//! Filesystem-oriented `ioctl` functions. + +#[cfg(linux_kernel)] +use { + crate::fd::AsFd, + crate::{backend, io}, +}; + +/// `ioctl(fd, BLKSSZGET)`—Returns the logical block size of a block device. +/// +/// This is mentioned in the [Linux `openat` manual page]. +/// +/// [Linux `openat` manual page]: https://man7.org/linux/man-pages/man2/openat.2.html +#[cfg(linux_kernel)] +#[inline] +#[doc(alias = "BLKSSZGET")] +pub fn ioctl_blksszget(fd: Fd) -> io::Result { + backend::fs::syscalls::ioctl_blksszget(fd.as_fd()) +} + +/// `ioctl(fd, BLKPBSZGET)`—Returns the physical block size of a block device. +#[cfg(linux_kernel)] +#[inline] +#[doc(alias = "BLKPBSZGET")] +pub fn ioctl_blkpbszget(fd: Fd) -> io::Result { + backend::fs::syscalls::ioctl_blkpbszget(fd.as_fd()) +} + +/// `ioctl(fd, FICLONE, src_fd)`—Share data between open files. +/// +/// This ioctl is not available on Sparc platforms +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/ioctl_ficlone.2.html +#[cfg(all(linux_kernel, not(any(target_arch = "sparc", target_arch = "sparc64"))))] +#[inline] +#[doc(alias = "FICLONE")] +pub fn ioctl_ficlone(fd: Fd, src_fd: SrcFd) -> io::Result<()> { + backend::fs::syscalls::ioctl_ficlone(fd.as_fd(), src_fd.as_fd()) +} + +/// `ioctl(fd, EXT4_IOC_RESIZE_FS, blocks)`—Resize ext4 filesystem on fd. +#[cfg(linux_kernel)] +#[inline] +#[doc(alias = "EXT4_IOC_RESIZE_FS")] +pub fn ext4_ioc_resize_fs(fd: Fd, blocks: u64) -> io::Result<()> { + backend::fs::syscalls::ext4_ioc_resize_fs(fd.as_fd(), blocks) +} diff --git a/vendor/rustix/src/fs/makedev.rs b/vendor/rustix/src/fs/makedev.rs index 36aef6d66..5793058ff 100644 --- a/vendor/rustix/src/fs/makedev.rs +++ b/vendor/rustix/src/fs/makedev.rs @@ -18,7 +18,6 @@ pub fn makedev(maj: u32, min: u32) -> Dev { /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man3/minor.3.html -#[cfg(not(bsd))] #[inline] pub fn minor(dev: Dev) -> u32 { backend::fs::makedev::minor(dev) @@ -30,7 +29,6 @@ pub fn minor(dev: Dev) -> u32 { /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man3/major.3.html -#[cfg(not(bsd))] #[inline] pub fn major(dev: Dev) -> u32 { backend::fs::makedev::major(dev) diff --git a/vendor/rustix/src/fs/mod.rs b/vendor/rustix/src/fs/mod.rs index e28ddab6f..fc2c3368b 100644 --- a/vendor/rustix/src/fs/mod.rs +++ b/vendor/rustix/src/fs/mod.rs @@ -4,7 +4,7 @@ mod abs; #[cfg(not(target_os = "redox"))] mod at; mod constants; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] mod copy_file_range; #[cfg(not(target_os = "redox"))] mod cwd; @@ -28,41 +28,46 @@ pub(crate) mod fd; mod file_type; #[cfg(apple)] mod getpath; -#[cfg(not(any(solarish, target_os = "haiku", target_os = "redox", target_os = "wasi")))] +#[cfg(not(target_os = "wasi"))] // WASI doesn't have get[gpu]id. +mod id; +#[cfg(not(target_os = "wasi"))] +mod ioctl; +#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] mod makedev; -#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "freebsd"))] mod memfd_create; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] mod mount; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] mod openat2; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] mod raw_dir; +mod seek_from; #[cfg(target_os = "linux")] mod sendfile; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] mod statx; #[cfg(not(any(target_os = "redox", target_os = "wasi")))] mod sync; -#[cfg(any(apple, target_os = "android", target_os = "linux"))] +#[cfg(any(apple, linux_kernel))] mod xattr; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use crate::backend::fs::inotify; pub use abs::*; #[cfg(not(target_os = "redox"))] pub use at::*; pub use constants::*; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use copy_file_range::copy_file_range; #[cfg(not(target_os = "redox"))] -pub use cwd::cwd; +pub use cwd::*; #[cfg(not(target_os = "redox"))] pub use dir::{Dir, DirEntry}; #[cfg(not(any( apple, - solarish, netbsdlike, + solarish, target_os = "dragonfly", target_os = "haiku", target_os = "redox", @@ -77,23 +82,28 @@ pub use fd::*; pub use file_type::FileType; #[cfg(apple)] pub use getpath::getpath; -#[cfg(not(any(solarish, target_os = "haiku", target_os = "redox", target_os = "wasi")))] +#[cfg(not(target_os = "wasi"))] +pub use id::*; +#[cfg(not(target_os = "wasi"))] +pub use ioctl::*; +#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))] pub use makedev::*; -#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] +#[cfg(any(linux_kernel, target_os = "freebsd"))] pub use memfd_create::{memfd_create, MemfdFlags}; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use mount::*; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use openat2::openat2; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use raw_dir::{RawDir, RawDirEntry}; +pub use seek_from::SeekFrom; #[cfg(target_os = "linux")] pub use sendfile::sendfile; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use statx::{statx, Statx, StatxFlags, StatxTimestamp}; #[cfg(not(any(target_os = "redox", target_os = "wasi")))] pub use sync::sync; -#[cfg(any(apple, target_os = "android", target_os = "linux"))] +#[cfg(any(apple, linux_kernel))] pub use xattr::*; /// Re-export types common to POSIX-ish platforms. diff --git a/vendor/rustix/src/fs/raw_dir.rs b/vendor/rustix/src/fs/raw_dir.rs index bad0bf97b..3131e0649 100644 --- a/vendor/rustix/src/fs/raw_dir.rs +++ b/vendor/rustix/src/fs/raw_dir.rs @@ -40,12 +40,17 @@ impl<'buf, Fd: AsFd> RawDir<'buf, Fd> { /// /// Using the heap: /// - /// ```notrust - /// # // The `notrust` above can be removed when we can depend on Rust 1.60. + /// ``` /// # use std::mem::MaybeUninit; - /// # use rustix::fs::{cwd, Mode, OFlags, openat, RawDir}; + /// # use rustix::fs::{CWD, Mode, OFlags, openat, RawDir}; /// - /// let fd = openat(cwd(), ".", OFlags::RDONLY | OFlags::DIRECTORY, Mode::empty()).unwrap(); + /// let fd = openat( + /// CWD, + /// ".", + /// OFlags::RDONLY | OFlags::DIRECTORY | OFlags::CLOEXEC, + /// Mode::empty(), + /// ) + /// .unwrap(); /// /// let mut buf = Vec::with_capacity(8192); /// let mut iter = RawDir::new(fd, buf.spare_capacity_mut()); @@ -59,12 +64,12 @@ impl<'buf, Fd: AsFd> RawDir<'buf, Fd> { /// /// ``` /// # use std::mem::MaybeUninit; - /// # use rustix::fs::{cwd, Mode, OFlags, openat, RawDir}; + /// # use rustix::fs::{CWD, Mode, OFlags, openat, RawDir}; /// /// let fd = openat( - /// cwd(), + /// CWD, /// ".", - /// OFlags::RDONLY | OFlags::DIRECTORY, + /// OFlags::RDONLY | OFlags::DIRECTORY | OFlags::CLOEXEC, /// Mode::empty(), /// ) /// .unwrap(); @@ -83,12 +88,18 @@ impl<'buf, Fd: AsFd> RawDir<'buf, Fd> { /// arbitrarily large file names: /// /// ```notrust - /// # // The `notrust` above can be removed when we can depend on Rust 1.60. + /// # // The `notrust` above can be removed when we can depend on Rust 1.65. /// # use std::mem::MaybeUninit; - /// # use rustix::fs::{cwd, Mode, OFlags, openat, RawDir}; + /// # use rustix::fs::{CWD, Mode, OFlags, openat, RawDir}; /// # use rustix::io::Errno; /// - /// let fd = openat(cwd(), ".", OFlags::RDONLY | OFlags::DIRECTORY, Mode::empty()).unwrap(); + /// let fd = openat( + /// CWD, + /// ".", + /// OFlags::RDONLY | OFlags::DIRECTORY | OFlags::CLOEXEC, + /// Mode::empty(), + /// ) + /// .unwrap(); /// /// let mut buf = Vec::with_capacity(8192); /// 'read: loop { @@ -127,8 +138,7 @@ impl<'buf, Fd: AsFd> RawDir<'buf, Fd> { /// A raw directory entry, similar to `std::fs::DirEntry`. /// -/// Note that unlike the std version, this may represent the `.` or `..` -/// entries. +/// Unlike the std version, this may represent the `.` or `..` entries. pub struct RawDirEntry<'a> { file_name: &'a CStr, file_type: u8, @@ -176,8 +186,8 @@ impl<'a> RawDirEntry<'a> { } impl<'buf, Fd: AsFd> RawDir<'buf, Fd> { - /// Identical to [Iterator::next] except that [Iterator::Item] borrows from - /// self. + /// Identical to [`Iterator::next`] except that [`Iterator::Item`] borrows + /// from self. /// /// Note: this interface will be broken to implement a stdlib iterator API /// with GAT support once one becomes available. diff --git a/vendor/rustix/src/fs/seek_from.rs b/vendor/rustix/src/fs/seek_from.rs new file mode 100644 index 000000000..cca23ed62 --- /dev/null +++ b/vendor/rustix/src/fs/seek_from.rs @@ -0,0 +1,48 @@ +//! The following is derived from Rust's +//! library/std/src/io/mod.rs at revision +//! dca3f1b786efd27be3b325ed1e01e247aa589c3b. + +/// Enumeration of possible methods to seek within an I/O object. +/// +/// It is used by the [`Seek`] trait. +/// +/// [`Seek`]: std::io::Seek +#[derive(Copy, PartialEq, Eq, Clone, Debug)] +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub enum SeekFrom { + /// Sets the offset to the provided number of bytes. + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + Start(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] u64), + + /// Sets the offset to the size of this object plus the specified number of + /// bytes. + /// + /// It is possible to seek beyond the end of an object, but it's an error + /// to seek before byte 0. + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + End(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] i64), + + /// Sets the offset to the current position plus the specified number of + /// bytes. + /// + /// It is possible to seek beyond the end of an object, but it's an error + /// to seek before byte 0. + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + Current(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] i64), + + /// Sets the offset to the current position plus the specified number of bytes, + /// plus the distance to the next byte which is not in a hole. + /// + /// If the offset is in a hole at the end of the file, the seek will produce + /// an `NXIO` error. + #[cfg(any(freebsdlike, target_os = "linux", target_os = "solaris"))] + Data(i64), + + /// Sets the offset to the current position plus the specified number of bytes, + /// plus the distance to the next byte which is in a hole. + /// + /// If there is no hole past the offset, it will be set to the end of the file + /// i.e. there is an implicit hole at the end of any file. + #[cfg(any(freebsdlike, target_os = "linux", target_os = "solaris"))] + Hole(i64), +} diff --git a/vendor/rustix/src/fs/sendfile.rs b/vendor/rustix/src/fs/sendfile.rs index 472ad37b2..7f5c8482d 100644 --- a/vendor/rustix/src/fs/sendfile.rs +++ b/vendor/rustix/src/fs/sendfile.rs @@ -7,7 +7,7 @@ use backend::fd::AsFd; /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/sendfile.2.html -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] pub fn sendfile( out_fd: OutFd, diff --git a/vendor/rustix/src/fs/statx.rs b/vendor/rustix/src/fs/statx.rs index 121f9270a..32ae84ed3 100644 --- a/vendor/rustix/src/fs/statx.rs +++ b/vendor/rustix/src/fs/statx.rs @@ -42,8 +42,8 @@ mod compat { use backend::fs::types::{Statx, StatxFlags}; - // Linux kernel prior to 4.11 old versions of Docker don't support `statx`. We - // store the availability in a global to avoid unnecessary syscalls. + // Linux kernel prior to 4.11 old versions of Docker don't support `statx`. + // We store the availability in a global to avoid unnecessary syscalls. // // 0: Unknown // 1: Not available @@ -92,9 +92,9 @@ mod compat { /// The first `statx` call failed with `PERM`. #[cold] fn statx_error_perm() -> io::Result { - // Some old versions of Docker have `statx` fail with `PERM` when it isn't - // recognized. Check whether `statx` really is available, and if so, fail - // with `PERM`, and if not, treat it like `NOSYS`. + // Some old versions of Docker have `statx` fail with `PERM` when it + // isn't recognized. Check whether `statx` really is available, and if + // so, fail with `PERM`, and if not, treat it like `NOSYS`. if backend::fs::syscalls::is_statx_available() { STATX_STATE.store(2, Ordering::Relaxed); Err(io::Errno::PERM) diff --git a/vendor/rustix/src/fs/xattr.rs b/vendor/rustix/src/fs/xattr.rs index e50841b49..01fe7d569 100644 --- a/vendor/rustix/src/fs/xattr.rs +++ b/vendor/rustix/src/fs/xattr.rs @@ -6,6 +6,8 @@ use bitflags::bitflags; bitflags! { /// `XATTR_*` constants for use with [`setxattr`], and other `*setxattr` /// functions. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct XattrFlags: c::c_uint { /// `XATTR_CREATE` const CREATE = c::XATTR_CREATE as c::c_uint; diff --git a/vendor/rustix/src/io/dup.rs b/vendor/rustix/src/io/dup.rs index 0ac99f3f3..428c69f28 100644 --- a/vendor/rustix/src/io/dup.rs +++ b/vendor/rustix/src/io/dup.rs @@ -56,8 +56,8 @@ pub fn dup(fd: Fd) -> io::Result { /// set `O_CLOEXEC`, use [`dup3`] with [`DupFlags::CLOEXEC`] on platforms which /// support it, or [`fcntl_dupfd_cloexec`] /// -/// For `dup2` to stdin, stdout, and stderr, see [`io::dup2_stdin`], -/// [`io::dup2_stdout`], and [`io::dup2_stderr`]. +/// For `dup2` to stdin, stdout, and stderr, see [`stdio::dup2_stdin`], +/// [`stdio::dup2_stdout`], and [`stdio::dup2_stderr`]. /// /// # References /// - [POSIX] @@ -81,6 +81,9 @@ pub fn dup(fd: Fd) -> io::Result { /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=dup2§ion=2 /// [illumos]: https://illumos.org/man/2/dup /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Duplicating-Descriptors.html +/// [`stdio::dup2_stdin`]: https://docs.rs/rustix/*/rustix/stdio/fn.dup2_stdin.html +/// [`stdio::dup2_stdout`]: https://docs.rs/rustix/*/rustix/stdio/fn.dup2_stdout.html +/// [`stdio::dup2_stderr`]: https://docs.rs/rustix/*/rustix/stdio/fn.dup2_stderr.html #[cfg(not(target_os = "wasi"))] #[inline] pub fn dup2(fd: Fd, new: &mut OwnedFd) -> io::Result<()> { diff --git a/vendor/rustix/src/io/eventfd.rs b/vendor/rustix/src/io/eventfd.rs deleted file mode 100644 index 1f71c96b1..000000000 --- a/vendor/rustix/src/io/eventfd.rs +++ /dev/null @@ -1,20 +0,0 @@ -use crate::fd::OwnedFd; -use crate::{backend, io}; - -pub use backend::io::types::EventfdFlags; - -/// `eventfd(initval, flags)`—Creates a file descriptor for event -/// notification. -/// -/// # References -/// - [Linux] -/// - [FreeBSD] -/// - [illumos] -/// -/// [Linux]: https://man7.org/linux/man-pages/man2/eventfd.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?eventfd -/// [illumos]: https://illumos.org/man/3C/eventfd -#[inline] -pub fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result { - backend::io::syscalls::eventfd(initval, flags) -} diff --git a/vendor/rustix/src/io/fd/mod.rs b/vendor/rustix/src/io/fd/mod.rs deleted file mode 100644 index 0978b5421..000000000 --- a/vendor/rustix/src/io/fd/mod.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! The following is derived from Rust's -//! library/std/src/os/fd/mod.rs at revision -//! fa68e73e9947be8ffc5b3b46d899e4953a44e7e9. -//! -//! Owned and borrowed Unix-like file descriptors. - -#![cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] -#![deny(unsafe_op_in_unsafe_fn)] - -// `RawFd`, `AsRawFd`, etc. -mod raw; - -// `OwnedFd`, `AsFd`, etc. -mod owned; - -pub use owned::*; -pub use raw::*; diff --git a/vendor/rustix/src/io/fd/owned.rs b/vendor/rustix/src/io/fd/owned.rs deleted file mode 100644 index 2b9238ca7..000000000 --- a/vendor/rustix/src/io/fd/owned.rs +++ /dev/null @@ -1,252 +0,0 @@ -//! The following is derived from Rust's -//! library/std/src/os/fd/owned.rs at revision -//! fa68e73e9947be8ffc5b3b46d899e4953a44e7e9. -//! -//! Owned and borrowed Unix-like file descriptors. - -#![cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] -#![deny(unsafe_op_in_unsafe_fn)] -#![allow(unsafe_code)] - -use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -use crate::io::close; -use core::fmt; -use core::marker::PhantomData; -use core::mem::forget; - -/// A borrowed file descriptor. -/// -/// This has a lifetime parameter to tie it to the lifetime of something that -/// owns the file descriptor. -/// -/// This uses `repr(transparent)` and has the representation of a host file -/// descriptor, so it can be used in FFI in places where a file descriptor is -/// passed as an argument, it is not captured or consumed, and it never has the -/// value `-1`. -/// -/// This type's `.to_owned()` implementation returns another `BorrowedFd` -/// rather than an `OwnedFd`. It just makes a trivial copy of the raw file -/// descriptor, which is then borrowed under the same lifetime. -#[derive(Copy, Clone)] -#[repr(transparent)] -#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0))] -// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a -// 32-bit c_int. Below is -2, in two's complement, but that only works out -// because c_int is 32 bits. -#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))] -#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] -#[cfg_attr(rustc_attrs, rustc_nonnull_optimization_guaranteed)] -pub struct BorrowedFd<'fd> { - fd: RawFd, - _phantom: PhantomData<&'fd OwnedFd>, -} - -/// An owned file descriptor. -/// -/// This closes the file descriptor on drop. -/// -/// This uses `repr(transparent)` and has the representation of a host file -/// descriptor, so it can be used in FFI in places where a file descriptor is -/// passed as a consumed argument or returned as an owned value, and it never -/// has the value `-1`. -#[repr(transparent)] -#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0))] -// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a -// 32-bit c_int. Below is -2, in two's complement, but that only works out -// because c_int is 32 bits. -#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))] -#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] -#[cfg_attr(rustc_attrs, rustc_nonnull_optimization_guaranteed)] -pub struct OwnedFd { - fd: RawFd, -} - -impl BorrowedFd<'_> { - /// Return a `BorrowedFd` holding the given raw file descriptor. - /// - /// # Safety - /// - /// The resource pointed to by `fd` must remain open for the duration of - /// the returned `BorrowedFd`, and it must not have the value `-1`. - #[inline] - #[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] - pub const unsafe fn borrow_raw(fd: RawFd) -> Self { - assert!(fd != u32::MAX as RawFd); - // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) - #[allow(unused_unsafe)] - unsafe { - Self { - fd, - _phantom: PhantomData, - } - } - } -} - -impl OwnedFd { - /// Creates a new `OwnedFd` instance that shares the same underlying file handle - /// as the existing `OwnedFd` instance. - #[cfg(not(target_arch = "wasm32"))] - pub fn try_clone(&self) -> crate::io::Result { - // We want to atomically duplicate this file descriptor and set the - // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This - // is a POSIX flag that was added to Linux in 2.6.24. - #[cfg(not(target_os = "espidf"))] - let fd = crate::io::fcntl_dupfd_cloexec(self, 0)?; - - // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics - // will never be supported, as this is a bare metal framework with - // no capabilities for multi-process execution. While F_DUPFD is also - // not supported yet, it might be (currently it returns ENOSYS). - #[cfg(target_os = "espidf")] - let fd = crate::io::fcntl_dupfd(self)?; - - Ok(fd.into()) - } - - #[cfg(target_arch = "wasm32")] - pub fn try_clone(&self) -> crate::io::Result { - Err(crate::io::const_io_error!( - crate::io::ErrorKind::Unsupported, - "operation not supported on WASI yet", - )) - } -} - -#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] -impl AsRawFd for BorrowedFd<'_> { - #[inline] - fn as_raw_fd(&self) -> RawFd { - self.fd - } -} - -#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] -impl AsRawFd for OwnedFd { - #[inline] - fn as_raw_fd(&self) -> RawFd { - self.fd - } -} - -#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] -impl IntoRawFd for OwnedFd { - #[inline] - fn into_raw_fd(self) -> RawFd { - let fd = self.fd; - forget(self); - fd - } -} - -#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] -impl FromRawFd for OwnedFd { - /// Constructs a new instance of `Self` from the given raw file descriptor. - /// - /// # Safety - /// - /// The resource pointed to by `fd` must be open and suitable for assuming - /// ownership. The resource must not require any cleanup other than `close`. - #[inline] - unsafe fn from_raw_fd(fd: RawFd) -> Self { - assert_ne!(fd, u32::MAX as RawFd); - // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) - #[allow(unused_unsafe)] - unsafe { - Self { fd } - } - } -} - -#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] -impl Drop for OwnedFd { - #[inline] - fn drop(&mut self) { - unsafe { - // Errors are ignored when closing a file descriptor. The reason - // for this is that if an error occurs we don't actually know if - // the file descriptor was closed or not, and if we retried (for - // something like EINTR), we might close another valid file - // descriptor opened after we closed ours. - close(self.fd as _); - } - } -} - -#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] -impl fmt::Debug for BorrowedFd<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("BorrowedFd").field("fd", &self.fd).finish() - } -} - -#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] -impl fmt::Debug for OwnedFd { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("OwnedFd").field("fd", &self.fd).finish() - } -} - -/// A trait to borrow the file descriptor from an underlying object. -/// -/// This is only available on unix platforms and must be imported in order to -/// call the method. Windows platforms have a corresponding `AsHandle` and -/// `AsSocket` set of traits. -#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] -pub trait AsFd { - /// Borrows the file descriptor. - /// - /// # Example - /// - /// ```no_run - /// # #![feature(io_safety)] - /// use std::fs::File; - /// # use std::io; - /// # #[cfg(target_os = "wasi")] - /// # use std::os::wasi::io::{AsFd, BorrowedFd}; - /// # #[cfg(unix)] - /// # use std::os::unix::io::{AsFd, BorrowedFd}; - /// - /// let mut f = File::open("foo.txt")?; - /// # #[cfg(any(unix, target_os = "wasi"))] - /// let borrowed_fd: BorrowedFd<'_> = f.as_fd(); - /// # Ok::<(), io::Error>(()) - /// ``` - #[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] - fn as_fd(&self) -> BorrowedFd<'_>; -} - -#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] -impl AsFd for &T { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - T::as_fd(self) - } -} - -#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] -impl AsFd for &mut T { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - T::as_fd(self) - } -} - -#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] -impl AsFd for BorrowedFd<'_> { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - *self - } -} - -#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] -impl AsFd for OwnedFd { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - // SAFETY: `OwnedFd` and `BorrowedFd` have the same validity - // invariants, and the `BorrowedFd` is bounded by the lifetime - // of `&self`. - unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } - } -} diff --git a/vendor/rustix/src/io/fd/raw.rs b/vendor/rustix/src/io/fd/raw.rs deleted file mode 100644 index a522c9794..000000000 --- a/vendor/rustix/src/io/fd/raw.rs +++ /dev/null @@ -1,159 +0,0 @@ -//! The following is derived from Rust's -//! library/std/src/os/fd/raw.rs at revision -//! fa68e73e9947be8ffc5b3b46d899e4953a44e7e9. -//! -//! Raw Unix-like file descriptors. - -#![cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] -#![allow(unsafe_code)] - -use crate::backend::c; - -/// Raw file descriptors. -#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] -pub type RawFd = c::c_int; - -/// A trait to extract the raw file descriptor from an underlying object. -/// -/// This is only available on unix and WASI platforms and must be imported in -/// order to call the method. Windows platforms have a corresponding -/// `AsRawHandle` and `AsRawSocket` set of traits. -#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] -pub trait AsRawFd { - /// Extracts the raw file descriptor. - /// - /// This function is typically used to **borrow** an owned file descriptor. - /// When used in this way, this method does **not** pass ownership of the - /// raw file descriptor to the caller, and the file descriptor is only - /// guaranteed to be valid while the original object has not yet been - /// destroyed. - /// - /// However, borrowing is not strictly required. See [`AsFd::as_fd`] - /// for an API which strictly borrows a file descriptor. - /// - /// # Example - /// - /// ```no_run - /// use std::fs::File; - /// # use std::io; - /// #[cfg(unix)] - /// use std::os::unix::io::{AsRawFd, RawFd}; - /// #[cfg(target_os = "wasi")] - /// use std::os::wasi::io::{AsRawFd, RawFd}; - /// - /// let mut f = File::open("foo.txt")?; - /// // `raw_fd` is only valid as long as `f` exists. - /// #[cfg(any(unix, target_os = "wasi"))] - /// let raw_fd: RawFd = f.as_raw_fd(); - /// # Ok::<(), io::Error>(()) - /// ``` - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - fn as_raw_fd(&self) -> RawFd; -} - -/// A trait to express the ability to construct an object from a raw file -/// descriptor. -#[cfg_attr(staged_api, stable(feature = "from_raw_os", since = "1.1.0"))] -pub trait FromRawFd { - /// Constructs a new instance of `Self` from the given raw file - /// descriptor. - /// - /// This function is typically used to **consume ownership** of the - /// specified file descriptor. When used in this way, the returned object - /// will take responsibility for closing it when the object goes out of - /// scope. - /// - /// However, consuming ownership is not strictly required. Use a - /// [`From::from`] implementation for an API which strictly - /// consumes ownership. - /// - /// # Safety - /// - /// The `fd` passed in must be a valid an open file descriptor. - /// - /// # Example - /// - /// ```no_run - /// use std::fs::File; - /// # use std::io; - /// #[cfg(unix)] - /// use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd}; - /// #[cfg(target_os = "wasi")] - /// use std::os::wasi::io::{FromRawFd, IntoRawFd, RawFd}; - /// - /// let f = File::open("foo.txt")?; - /// # #[cfg(any(unix, target_os = "wasi"))] - /// let raw_fd: RawFd = f.into_raw_fd(); - /// // SAFETY: no other functions should call `from_raw_fd`, so there - /// // is only one owner for the file descriptor. - /// # #[cfg(any(unix, target_os = "wasi"))] - /// let f = unsafe { File::from_raw_fd(raw_fd) }; - /// # Ok::<(), io::Error>(()) - /// ``` - #[cfg_attr(staged_api, stable(feature = "from_raw_os", since = "1.1.0"))] - unsafe fn from_raw_fd(fd: RawFd) -> Self; -} - -/// A trait to express the ability to consume an object and acquire ownership of -/// its raw file descriptor. -#[cfg_attr(staged_api, stable(feature = "into_raw_os", since = "1.4.0"))] -pub trait IntoRawFd { - /// Consumes this object, returning the raw underlying file descriptor. - /// - /// This function is typically used to **transfer ownership** of the underlying - /// file descriptor to the caller. When used in this way, callers are then the unique - /// owners of the file descriptor and must close it once it's no longer needed. - /// - /// However, transferring ownership is not strictly required. Use a - /// [`Into::into`] implementation for an API which strictly - /// transfers ownership. - /// - /// # Example - /// - /// ```no_run - /// use std::fs::File; - /// # use std::io; - /// #[cfg(unix)] - /// use std::os::unix::io::{IntoRawFd, RawFd}; - /// #[cfg(target_os = "wasi")] - /// use std::os::wasi::io::{IntoRawFd, RawFd}; - /// - /// let f = File::open("foo.txt")?; - /// #[cfg(any(unix, target_os = "wasi"))] - /// let raw_fd: RawFd = f.into_raw_fd(); - /// # Ok::<(), io::Error>(()) - /// ``` - #[cfg_attr(staged_api, stable(feature = "into_raw_os", since = "1.4.0"))] - fn into_raw_fd(self) -> RawFd; -} - -#[cfg_attr( - staged_api, - stable(feature = "raw_fd_reflexive_traits", since = "1.48.0") -)] -impl AsRawFd for RawFd { - #[inline] - fn as_raw_fd(&self) -> RawFd { - *self - } -} -#[cfg_attr( - staged_api, - stable(feature = "raw_fd_reflexive_traits", since = "1.48.0") -)] -impl IntoRawFd for RawFd { - #[inline] - fn into_raw_fd(self) -> RawFd { - self - } -} -#[cfg_attr( - staged_api, - stable(feature = "raw_fd_reflexive_traits", since = "1.48.0") -)] -impl FromRawFd for RawFd { - #[inline] - unsafe fn from_raw_fd(fd: RawFd) -> RawFd { - fd - } -} diff --git a/vendor/rustix/src/io/ioctl.rs b/vendor/rustix/src/io/ioctl.rs index fde652e19..59cbe1ab5 100644 --- a/vendor/rustix/src/io/ioctl.rs +++ b/vendor/rustix/src/io/ioctl.rs @@ -1,49 +1,14 @@ -//! The Unix `ioctl` function is effectively lots of different functions -//! hidden behind a single dynamic dispatch interface. In order to provide -//! a type-safe API, rustix makes them all separate functions so that they -//! can have dedicated static type signatures. +//! The Unix `ioctl` function is effectively lots of different functions hidden +//! behind a single dynamic dispatch interface. In order to provide a type-safe +//! API, rustix makes them all separate functions so that they can have +//! dedicated static type signatures. +//! +//! Some ioctls, such as those related to filesystems, terminals, and +//! processes, live in other top-level API modules. use crate::{backend, io}; use backend::fd::AsFd; -/// `ioctl(fd, TIOCEXCL)`—Enables exclusive mode on a terminal. -/// -/// # References -/// - [Linux] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// -/// [Linux]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=tty&sektion=4 -/// [NetBSD]: https://man.netbsd.org/tty.4 -/// [OpenBSD]: https://man.openbsd.org/tty.4 -#[cfg(not(any(windows, target_os = "haiku", target_os = "redox", target_os = "wasi")))] -#[inline] -#[doc(alias = "TIOCEXCL")] -pub fn ioctl_tiocexcl(fd: Fd) -> io::Result<()> { - backend::io::syscalls::ioctl_tiocexcl(fd.as_fd()) -} - -/// `ioctl(fd, TIOCNXCL)`—Disables exclusive mode on a terminal. -/// -/// # References -/// - [Linux] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// -/// [Linux]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=tty&sektion=4 -/// [NetBSD]: https://man.netbsd.org/tty.4 -/// [OpenBSD]: https://man.openbsd.org/tty.4 -#[cfg(not(any(windows, target_os = "haiku", target_os = "redox", target_os = "wasi")))] -#[inline] -#[doc(alias = "TIOCNXCL")] -pub fn ioctl_tiocnxcl(fd: Fd) -> io::Result<()> { - backend::io::syscalls::ioctl_tiocnxcl(fd.as_fd()) -} - /// `ioctl(fd, FIOCLEX, NULL)`—Set the close-on-exec flag. /// /// Also known as `fcntl(fd, F_SETFD, FD_CLOEXEC)`. @@ -97,42 +62,8 @@ pub fn ioctl_fionbio(fd: Fd, value: bool) -> io::Result<()> { /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=ioctl&sektion=2#GENERIC%09IOCTLS /// [NetBSD]: https://man.netbsd.org/ioctl.2#GENERIC%20IOCTLS /// [OpenBSD]: https://man.openbsd.org/ioctl.2#GENERIC_IOCTLS -#[cfg(not(target_os = "redox"))] #[inline] #[doc(alias = "FIONREAD")] pub fn ioctl_fionread(fd: Fd) -> io::Result { backend::io::syscalls::ioctl_fionread(fd.as_fd()) } - -/// `ioctl(fd, BLKSSZGET)`—Returns the logical block size of a block device. -/// -/// This is mentioned in the [Linux `openat` manual page]. -/// -/// [Linux `openat` manual page]: https://man7.org/linux/man-pages/man2/openat.2.html -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -#[doc(alias = "BLKSSZGET")] -pub fn ioctl_blksszget(fd: Fd) -> io::Result { - backend::io::syscalls::ioctl_blksszget(fd.as_fd()) -} - -/// `ioctl(fd, BLKPBSZGET)`—Returns the physical block size of a block device. -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -#[doc(alias = "BLKPBSZGET")] -pub fn ioctl_blkpbszget(fd: Fd) -> io::Result { - backend::io::syscalls::ioctl_blkpbszget(fd.as_fd()) -} - -/// `ioctl(fd, FICLONE, src_fd)`—Share data between open files. -/// -/// # References -/// - [Linux] -/// -/// [Linux]: https://man7.org/linux/man-pages/man2/ioctl_ficlone.2.html -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -#[doc(alias = "FICLONE")] -pub fn ioctl_ficlone(fd: Fd, src_fd: SrcFd) -> io::Result<()> { - backend::io::syscalls::ioctl_ficlone(fd.as_fd(), src_fd.as_fd()) -} diff --git a/vendor/rustix/src/io/is_read_write.rs b/vendor/rustix/src/io/is_read_write.rs index 39a2a03d4..af33806cb 100644 --- a/vendor/rustix/src/io/is_read_write.rs +++ b/vendor/rustix/src/io/is_read_write.rs @@ -2,9 +2,7 @@ //! //! [`is_read_write`]: https://docs.rs/rustix/*/rustix/io/fn.is_read_write.html -#[cfg(all(feature = "fs", feature = "net"))] use crate::{backend, io}; -#[cfg(all(feature = "fs", feature = "net"))] use backend::fd::AsFd; /// Returns a pair of booleans indicating whether the file descriptor is @@ -15,7 +13,6 @@ use backend::fd::AsFd; /// /// [`is_file_read_write`]: crate::fs::is_file_read_write #[inline] -#[cfg(all(feature = "fs", feature = "net"))] #[cfg_attr(doc_cfg, doc(cfg(all(feature = "fs", feature = "net"))))] pub fn is_read_write(fd: Fd) -> io::Result<(bool, bool)> { backend::io::syscalls::is_read_write(fd.as_fd()) diff --git a/vendor/rustix/src/io/kqueue.rs b/vendor/rustix/src/io/kqueue.rs deleted file mode 100644 index 55d2acabf..000000000 --- a/vendor/rustix/src/io/kqueue.rs +++ /dev/null @@ -1,431 +0,0 @@ -//! An API for interfacing with `kqueue`. - -use crate::fd::{AsFd, AsRawFd, OwnedFd, RawFd}; -use crate::{backend, io}; - -use backend::c::{self, intptr_t, kevent as kevent_t, uintptr_t}; -use backend::io::syscalls; - -use alloc::vec::Vec; -use core::ptr::slice_from_raw_parts_mut; -use core::time::Duration; - -/// A `kqueue` event. -#[repr(transparent)] -#[derive(Copy, Clone)] -pub struct Event { - // The layout varies between BSDs and macOS. - inner: kevent_t, -} - -impl Event { - /// Create a new `Event`. - #[allow(clippy::needless_update)] - pub fn new(filter: EventFilter, flags: EventFlags, udata: isize) -> Event { - let (ident, data, filter, fflags) = match filter { - EventFilter::Read(fd) => (fd.as_raw_fd() as uintptr_t, 0, c::EVFILT_READ, 0), - EventFilter::Write(fd) => (fd.as_raw_fd() as _, 0, c::EVFILT_WRITE, 0), - #[cfg(target_os = "freebsd")] - EventFilter::Empty(fd) => (fd.as_raw_fd() as _, 0, c::EVFILT_EMPTY, 0), - EventFilter::Vnode { vnode, flags } => { - (vnode.as_raw_fd() as _, 0, c::EVFILT_VNODE, flags.bits()) - } - #[cfg(feature = "process")] - EventFilter::Proc { pid, flags } => ( - crate::process::Pid::as_raw(Some(pid)) as _, - 0, - c::EVFILT_PROC, - flags.bits(), - ), - #[cfg(feature = "process")] - EventFilter::Signal { signal, times: _ } => (signal as _, 0, c::EVFILT_SIGNAL, 0), - EventFilter::Timer { ident, timer } => { - #[cfg(any(apple, target_os = "freebsd", target_os = "netbsd"))] - let (data, fflags) = match timer { - Some(timer) => { - if timer.subsec_millis() == 0 { - (timer.as_secs() as _, c::NOTE_SECONDS) - } else if timer.subsec_nanos() == 0 { - (timer.as_micros() as _, c::NOTE_USECONDS) - } else { - (timer.as_nanos() as _, c::NOTE_NSECONDS) - } - } - None => (intptr_t::MAX, c::NOTE_SECONDS), - }; - #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] - let (data, fflags) = match timer { - Some(timer) => (timer.as_millis() as _, 0), - None => (intptr_t::MAX, 0), - }; - - (ident as _, data, c::EVFILT_TIMER, fflags) - } - #[cfg(any(apple, freebsdlike))] - EventFilter::User { - ident, - flags, - user_flags, - } => (ident as _, 0, c::EVFILT_USER, flags.bits() | user_flags.0), - EventFilter::Unknown => panic!("unknown filter"), - }; - - Event { - inner: kevent_t { - ident, - filter: filter as _, - flags: flags.bits() as _, - fflags, - data: { - // On openbsd, data is an i64 and not an isize - data as _ - }, - udata: { - // On netbsd, udata is an isize and not a pointer. - // TODO: Strict provenance, prevent int-to-ptr cast. - udata as _ - }, - ..unsafe { core::mem::zeroed() } - }, - } - } - - /// Get the event flags for this event. - pub fn flags(&self) -> EventFlags { - EventFlags::from_bits_truncate(self.inner.flags as _) - } - - /// Get the user data for this event. - pub fn udata(&self) -> isize { - // On netbsd, udata is an isize and not a pointer. - // TODO: Strict provenance, prevent ptr-to-int cast. - - self.inner.udata as _ - } - - /// Get the filter of this event. - pub fn filter(&self) -> EventFilter { - match self.inner.filter as _ { - c::EVFILT_READ => EventFilter::Read(self.inner.ident as _), - c::EVFILT_WRITE => EventFilter::Write(self.inner.ident as _), - #[cfg(target_os = "freebsd")] - c::EVFILT_EMPTY => EventFilter::Empty(self.inner.ident as _), - c::EVFILT_VNODE => EventFilter::Vnode { - vnode: self.inner.ident as _, - flags: VnodeEvents::from_bits_truncate(self.inner.fflags), - }, - #[cfg(feature = "process")] - c::EVFILT_PROC => EventFilter::Proc { - pid: unsafe { crate::process::Pid::from_raw(self.inner.ident as _) }.unwrap(), - flags: ProcessEvents::from_bits_truncate(self.inner.fflags), - }, - #[cfg(feature = "process")] - c::EVFILT_SIGNAL => EventFilter::Signal { - signal: crate::process::Signal::from_raw(self.inner.ident as _).unwrap(), - times: self.inner.data as _, - }, - c::EVFILT_TIMER => EventFilter::Timer { - ident: self.inner.ident as _, - timer: { - let (data, fflags) = (self.inner.data, self.inner.fflags); - #[cfg(any(apple, target_os = "freebsd", target_os = "netbsd"))] - match fflags as _ { - c::NOTE_SECONDS => Some(Duration::from_secs(data as _)), - c::NOTE_USECONDS => Some(Duration::from_micros(data as _)), - c::NOTE_NSECONDS => Some(Duration::from_nanos(data as _)), - _ => { - // Unknown timer flags. - None - } - } - #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] - Some(Duration::from_millis(data as _)) - }, - }, - #[cfg(any(apple, freebsdlike))] - c::EVFILT_USER => EventFilter::User { - ident: self.inner.ident as _, - flags: UserFlags::from_bits_truncate(self.inner.fflags), - user_flags: UserDefinedFlags(self.inner.fflags & EVFILT_USER_FLAGS), - }, - _ => EventFilter::Unknown, - } - } -} - -/// Bottom 24 bits of a u32. -#[cfg(any(apple, freebsdlike))] -const EVFILT_USER_FLAGS: u32 = 0x00ff_ffff; - -/// The possible filters for a `kqueue`. -#[repr(i16)] -#[non_exhaustive] -pub enum EventFilter { - /// A read filter. - Read(RawFd), - - /// A write filter. - Write(RawFd), - - /// An empty filter. - #[cfg(target_os = "freebsd")] - Empty(RawFd), - - /// A VNode filter. - Vnode { - /// The file descriptor we looked for events in. - vnode: RawFd, - - /// The flags for this event. - flags: VnodeEvents, - }, - - /// A process filter. - #[cfg(feature = "process")] - Proc { - /// The process ID we waited on. - pid: crate::process::Pid, - - /// The flags for this event. - flags: ProcessEvents, - }, - - /// A signal filter. - #[cfg(feature = "process")] - Signal { - /// The signal number we waited on. - signal: crate::process::Signal, - - /// The number of times the signal has been - /// received since the last call to kevent. - times: usize, - }, - - /// A timer filter. - Timer { - /// The identifier for this event. - ident: intptr_t, - - /// The duration for this event. - timer: Option, - }, - - /// A user filter. - #[cfg(any(apple, freebsdlike))] - User { - /// The identifier for this event. - ident: intptr_t, - - /// The flags for this event. - flags: UserFlags, - - /// The user-defined flags for this event. - user_flags: UserDefinedFlags, - }, - - /// This filter is unknown. - /// - /// # Panics - /// - /// Passing this into `Event::new()` will result in a panic. - Unknown, -} - -bitflags::bitflags! { - /// The flags for a `kqueue` event. - pub struct EventFlags: u16 { - /// Add the event to the `kqueue`. - const ADD = c::EV_ADD as _; - - /// Enable the event. - const ENABLE = c::EV_ENABLE as _; - - /// Disable the event. - const DISABLE = c::EV_DISABLE as _; - - /// Delete the event from the `kqueue`. - const DELETE = c::EV_DELETE as _; - - /// TODO - const RECEIPT = c::EV_RECEIPT as _; - - /// Clear the event after it is triggered. - const ONESHOT = c::EV_ONESHOT as _; - - /// TODO - const CLEAR = c::EV_CLEAR as _; - - /// TODO - const EOF = c::EV_EOF as _; - - /// TODO - const ERROR = c::EV_ERROR as _; - } -} - -bitflags::bitflags! { - /// The flags for a virtual node event. - pub struct VnodeEvents: u32 { - /// The file was deleted. - const DELETE = c::NOTE_DELETE; - - /// The file was written to. - const WRITE = c::NOTE_WRITE; - - /// The file was extended. - const EXTEND = c::NOTE_EXTEND; - - /// The file had its attributes changed. - const ATTRIBUTES = c::NOTE_ATTRIB; - - /// The file was renamed. - const RENAME = c::NOTE_RENAME; - - /// Access to the file was revoked. - const REVOKE = c::NOTE_REVOKE; - - /// The link count of the file has changed. - const LINK = c::NOTE_LINK; - } -} - -#[cfg(feature = "process")] -bitflags::bitflags! { - /// The flags for a process event. - pub struct ProcessEvents: u32 { - /// The process exited. - const EXIT = c::NOTE_EXIT; - - /// The process forked itself. - const FORK = c::NOTE_FORK; - - /// The process executed a new process. - const EXEC = c::NOTE_EXEC; - - /// Follow the process through `fork()` calls (write only). - const TRACK = c::NOTE_TRACK; - - /// An error has occurred with following the process. - const TRACKERR = c::NOTE_TRACKERR; - } -} - -#[cfg(any(apple, freebsdlike))] -bitflags::bitflags! { - /// The flags for a user event. - pub struct UserFlags: u32 { - /// Ignore the user input flags. - const NOINPUT = c::NOTE_FFNOP; - - /// Bitwise AND `fflags`. - const AND = c::NOTE_FFAND; - - /// Bitwise OR `fflags`. - const OR = c::NOTE_FFOR; - - /// Copy `fflags`. - const COPY = c::NOTE_FFCOPY; - - /// Control mask for operations. - const CTRLMASK = c::NOTE_FFCTRLMASK; - - /// User defined flags for masks. - const UDFMASK = c::NOTE_FFLAGSMASK; - - /// Trigger the event. - const TRIGGER = c::NOTE_TRIGGER; - } -} - -/// User-defined flags. -/// -/// Only the lower 24 bits are used in this struct. -#[repr(transparent)] -#[cfg(any(apple, freebsdlike))] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct UserDefinedFlags(u32); - -#[cfg(any(apple, freebsdlike))] -impl UserDefinedFlags { - /// Create a new `UserDefinedFlags` from a `u32`. - pub fn new(flags: u32) -> Self { - Self(flags & EVFILT_USER_FLAGS) - } - - /// Get the underlying `u32`. - pub fn get(self) -> u32 { - self.0 - } -} - -/// `kqueue()`—Create a new `kqueue` file descriptor. -/// -/// # References -/// - [Apple] -/// - [FreeBSD] -/// - [OpenBSD] -/// - [NetBSD] -/// - [DragonFly BSD] -/// -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/kqueue.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2 -/// [OpenBSD]: https://man.openbsd.org/kqueue.2 -/// [NetBSD]: https://man.netbsd.org/kqueue.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=kqueue§ion=2 -pub fn kqueue() -> io::Result { - syscalls::kqueue() -} - -/// `kevent(kqueue, changelist, eventlist, timeout)`—Wait for events on a -/// `kqueue`. -/// -/// Note: in order to receive events, make sure to allocate capacity in the -/// eventlist! Otherwise, the function will return immediately. -/// -/// # Safety -/// -/// The file descriptors referred to by the `Event` structs must be valid for -/// the lifetime of the `kqueue` file descriptor. -/// -/// # References -/// - [Apple] -/// - [FreeBSD] -/// - [OpenBSD] -/// - [NetBSD] -/// - [DragonFly BSD] -/// -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/kevent.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=kevent&sektion=2 -/// [OpenBSD]: https://man.openbsd.org/kevent.2 -/// [NetBSD]: https://man.netbsd.org/kevent.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=kevent§ion=2 -pub unsafe fn kevent( - kqueue: impl AsFd, - changelist: &[Event], - eventlist: &mut Vec, - timeout: Option, -) -> io::Result { - let timeout = timeout.map(|timeout| crate::backend::c::timespec { - tv_sec: timeout.as_secs() as _, - tv_nsec: timeout.subsec_nanos() as _, - }); - - // Populate the event list with events. - eventlist.set_len(0); - let out_slice = - slice_from_raw_parts_mut(eventlist.as_mut_ptr() as *mut _, eventlist.capacity()); - let res = syscalls::kevent( - kqueue.as_fd(), - changelist, - &mut *out_slice, - timeout.as_ref(), - ) - .map(|res| res as _); - - // Update the event list. - if let Ok(len) = res { - eventlist.set_len(len); - } - - res -} diff --git a/vendor/rustix/src/io/mod.rs b/vendor/rustix/src/io/mod.rs index 1fe302a6e..bddd12acd 100644 --- a/vendor/rustix/src/io/mod.rs +++ b/vendor/rustix/src/io/mod.rs @@ -1,64 +1,32 @@ //! I/O operations. +//! +//! If you're looking for [`SeekFrom`], that's in the [`fs`] module. +//! +//! [`SeekFrom`]: https://docs.rs/rustix/*/rustix/fs/enum.SeekFrom.html +//! [`fs`]: https://docs.rs/rustix/*/rustix/fs/index.html mod close; #[cfg(not(windows))] mod dup; mod errno; -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "illumos", - target_os = "linux" -))] -mod eventfd; #[cfg(not(windows))] mod fcntl; -#[cfg(not(feature = "std"))] -pub(crate) mod fd; mod ioctl; #[cfg(not(any(windows, target_os = "redox")))] +#[cfg(all(feature = "fs", feature = "net"))] mod is_read_write; -#[cfg(bsd)] -pub mod kqueue; -#[cfg(not(any(windows, target_os = "wasi")))] -mod pipe; -mod poll; -#[cfg(solarish)] -pub mod port; -#[cfg(all(feature = "procfs", any(target_os = "android", target_os = "linux")))] -mod procfs; #[cfg(not(windows))] mod read_write; -mod seek_from; -#[cfg(not(windows))] -mod stdio; -#[cfg(any(target_os = "android", target_os = "linux"))] -pub use crate::backend::io::epoll; pub use close::close; #[cfg(not(windows))] pub use dup::*; pub use errno::{retry_on_intr, Errno, Result}; -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "illumos", - target_os = "linux" -))] -pub use eventfd::{eventfd, EventfdFlags}; #[cfg(not(windows))] pub use fcntl::*; pub use ioctl::*; #[cfg(not(any(windows, target_os = "redox")))] #[cfg(all(feature = "fs", feature = "net"))] -pub use is_read_write::is_read_write; -#[cfg(not(any(windows, target_os = "wasi")))] -pub use pipe::*; -pub use poll::{poll, PollFd, PollFlags}; -#[cfg(all(feature = "procfs", any(target_os = "android", target_os = "linux")))] -pub use procfs::*; +pub use is_read_write::*; #[cfg(not(windows))] pub use read_write::*; -pub use seek_from::SeekFrom; -#[cfg(not(windows))] -pub use stdio::*; diff --git a/vendor/rustix/src/io/pipe.rs b/vendor/rustix/src/io/pipe.rs deleted file mode 100644 index 40acc814d..000000000 --- a/vendor/rustix/src/io/pipe.rs +++ /dev/null @@ -1,156 +0,0 @@ -//! `pipe` and related APIs. -//! -//! # Safety -//! -//! `vmsplice` is an unsafe function. - -#![allow(unsafe_code)] - -use crate::fd::OwnedFd; -use crate::{backend, io}; -#[cfg(any(target_os = "android", target_os = "linux"))] -use backend::fd::AsFd; - -#[cfg(not(apple))] -pub use backend::io::types::PipeFlags; - -#[cfg(any(target_os = "android", target_os = "linux"))] -pub use backend::io::types::{IoSliceRaw, SpliceFlags}; - -/// `PIPE_BUF`—The maximum length at which writes to a pipe are atomic. -/// -/// # References -/// - [Linux] -/// - [POSIX] -/// -/// [Linux]: https://man7.org/linux/man-pages/man7/pipe.7.html -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html -#[cfg(not(any( - solarish, - windows, - target_os = "haiku", - target_os = "redox", - target_os = "wasi", -)))] -pub const PIPE_BUF: usize = backend::io::types::PIPE_BUF; - -/// `pipe()`—Creates a pipe. -/// -/// This function creates a pipe and returns two file descriptors, for the -/// reading and writing ends of the pipe, respectively. -/// -/// # References -/// - [POSIX] -/// - [Linux] -/// - [Apple] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html -/// [Linux]: https://man7.org/linux/man-pages/man2/pipe.2.html -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/pipe.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=pipe&sektion=2 -/// [NetBSD]: https://man.netbsd.org/pipe.2 -/// [OpenBSD]: https://man.openbsd.org/pipe.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=pipe§ion=2 -/// [illumos]: https://illumos.org/man/2/pipe -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Creating-a-Pipe.html -#[inline] -pub fn pipe() -> io::Result<(OwnedFd, OwnedFd)> { - backend::io::syscalls::pipe() -} - -/// `pipe2(flags)`—Creates a pipe, with flags. -/// -/// This function creates a pipe and returns two file descriptors, for the -/// reading and writing ends of the pipe, respectively. -/// -/// # References -/// - [Linux] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// -/// [Linux]: https://man7.org/linux/man-pages/man2/pipe2.2.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=pipe2&sektion=2 -/// [NetBSD]: https://man.netbsd.org/pipe2.2 -/// [OpenBSD]: https://man.openbsd.org/pipe2.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=pipe2§ion=2 -/// [illumos]: https://illumos.org/man/2/pipe2 -#[cfg(not(any(apple, target_os = "aix", target_os = "haiku")))] -#[inline] -#[doc(alias = "pipe2")] -pub fn pipe_with(flags: PipeFlags) -> io::Result<(OwnedFd, OwnedFd)> { - backend::io::syscalls::pipe_with(flags) -} - -/// `splice(fd_in, off_in, fd_out, off_out, len, flags)`—Transfer data between -/// a file and a pipe. -/// -/// This function transfers up to `len` bytes of data from the file descriptor -/// `fd_in` to the file descriptor `fd_out`, where one of the file descriptors -/// must refer to a pipe. -/// -/// `off_*` must be `None` if the corresponding fd refers to a pipe. -/// Otherwise its value points to the starting offset to the file, -/// from which the data is read/written. -/// on success the number of bytes read/written is added to the offset. -/// -/// passing `None` causes the read/write to start from the file offset, -/// and the file offset is adjusted appropriately. -/// -/// # References -/// - [Linux] -/// -/// [Linux]: https://man7.org/linux/man-pages/man2/splice.2.html -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -pub fn splice( - fd_in: FdIn, - off_in: Option<&mut u64>, - fd_out: FdOut, - off_out: Option<&mut u64>, - len: usize, - flags: SpliceFlags, -) -> io::Result { - backend::io::syscalls::splice(fd_in.as_fd(), off_in, fd_out.as_fd(), off_out, len, flags) -} - -/// `vmsplice(fd, bufs, flags)`—Transfer data between memory and a pipe. -/// -/// If `fd` is the write end of the pipe, -/// the function maps the memory pointer at by `bufs` to the pipe. -/// -/// If `fd` is the read end of the pipe, -/// the function writes data from the pipe to said memory. -/// -/// # Safety -/// -/// If the memory must not be mutated (such as when `bufs` were originally -/// immutable slices), it is up to the caller to ensure that the write end of -/// the pipe is placed in `fd`. -/// -/// Additionally if `SpliceFlags::GIFT` is set, the caller must also ensure -/// that the contents of `bufs` in never modified following the call, -/// and that all of the pointers in `bufs` are page aligned, -/// and the lengths are multiples of a page size in bytes. -/// -/// # References -/// - [Linux] -/// -/// [Linux]: https://man7.org/linux/man-pages/man2/vmsplice.2.html -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -pub unsafe fn vmsplice( - fd: PipeFd, - bufs: &[io::IoSliceRaw], - flags: SpliceFlags, -) -> io::Result { - backend::io::syscalls::vmsplice(fd.as_fd(), bufs, flags) -} diff --git a/vendor/rustix/src/io/poll.rs b/vendor/rustix/src/io/poll.rs deleted file mode 100644 index 3f25d5ec3..000000000 --- a/vendor/rustix/src/io/poll.rs +++ /dev/null @@ -1,32 +0,0 @@ -use crate::{backend, io}; - -pub use backend::io::poll_fd::{PollFd, PollFlags}; - -/// `poll(self.fds, timeout)` -/// -/// # References -/// - [Beej's Guide to Network Programming] -/// - [POSIX] -/// - [Linux] -/// - [Apple] -/// - [Winsock2] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// -/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/slightly-advanced-techniques.html#poll -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html -/// [Linux]: https://man7.org/linux/man-pages/man2/poll.2.html -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/poll.2.html -/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsapoll -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=poll&sektion=2 -/// [NetBSD]: https://man.netbsd.org/poll.2 -/// [OpenBSD]: https://man.openbsd.org/poll.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=poll§ion=2 -/// [illumos]: https://illumos.org/man/2/poll -#[inline] -pub fn poll(fds: &mut [PollFd<'_>], timeout: i32) -> io::Result { - backend::io::syscalls::poll(fds, timeout) -} diff --git a/vendor/rustix/src/io/port.rs b/vendor/rustix/src/io/port.rs deleted file mode 100644 index 4eb0bcd9e..000000000 --- a/vendor/rustix/src/io/port.rs +++ /dev/null @@ -1,151 +0,0 @@ -//! Solaris/illumos event ports. - -use crate::backend::c; -use crate::backend::io::syscalls; -use crate::fd::{AsFd, AsRawFd, OwnedFd}; -use crate::io; - -use super::PollFlags; - -use core::convert::TryInto; -use core::time::Duration; - -/// The structure representing a port event. -#[repr(transparent)] -pub struct Event(pub(crate) c::port_event); - -impl Event { - /// Get the events associated with this event. - pub fn events(&self) -> i32 { - self.0.portev_events - } - - /// Get the event source associated with this event. - pub fn object(&self) -> usize { - self.0.portev_object - } - - /// Get the userdata associated with this event. - pub fn userdata(&self) -> *mut c::c_void { - self.0.portev_user - } -} - -/// `port_create()`—Creates a new port. -/// -/// # References -/// - [OpenSolaris] -/// - [illumos] -/// -/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_create/ -/// [illumos]: https://illumos.org/man/3C/port_create -pub fn port_create() -> io::Result { - syscalls::port_create() -} - -/// `port_associate(_, PORT_SOURCE_FD, _, _, _)`—Associates a file descriptor -/// with a port. -/// -/// # Safety -/// -/// Any `object`s passed into the `port` must be valid for the lifetime of the -/// `port`. Logically, `port` keeps a borrowed reference to the `object` until -/// it is removed via `port_dissociate_fd`. -/// -/// # References -/// - [OpenSolaris] -/// - [illumos] -/// -/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_associate/ -/// [illumos]: https://illumos.org/man/3C/port_associate -pub unsafe fn port_associate_fd( - port: impl AsFd, - object: impl AsRawFd, - events: PollFlags, - userdata: *mut c::c_void, -) -> io::Result<()> { - syscalls::port_associate( - port.as_fd(), - c::PORT_SOURCE_FD, - object.as_raw_fd() as _, - events.bits() as _, - userdata.cast(), - ) -} - -/// `port_dissociate(_, PORT_SOURCE_FD, _)`—Dissociates a file descriptor from -/// a port. -/// -/// # Safety -/// -/// The file descriptor passed into this function must have been previously -/// associated with the port via [`port_associate_fd`]. -/// -/// # References -/// - [OpenSolaris] -/// - [illumos] -/// -/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_dissociate -/// [illumos]: https://illumos.org/man/3C/port_dissociate -pub unsafe fn port_dissociate_fd(port: impl AsFd, object: impl AsRawFd) -> io::Result<()> { - syscalls::port_dissociate(port.as_fd(), c::PORT_SOURCE_FD, object.as_raw_fd() as _) -} - -/// `port_get(port, timeout)`—Gets an event from a port. -/// -/// # References -/// - [OpenSolaris] -/// - [illumos] -/// -/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_get/ -/// [illumos]: https://illumos.org/man/3C/port_get -pub fn port_get(port: impl AsFd, timeout: Option) -> io::Result { - let mut timeout = timeout.map(|timeout| c::timespec { - tv_sec: timeout.as_secs().try_into().unwrap(), - tv_nsec: timeout.subsec_nanos() as _, - }); - - syscalls::port_get(port.as_fd(), timeout.as_mut()) -} - -/// `port_getn(port, events, min_events, timeout)`—Gets multiple events from a -/// port. -/// -/// # References -/// - [OpenSolaris] -/// - [illumos] -/// -/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_getn/ -/// [illumos]: https://illumos.org/man/3C/port_getn -pub fn port_getn( - port: impl AsFd, - events: &mut Vec, - min_events: usize, - timeout: Option, -) -> io::Result<()> { - events.clear(); - - let mut timeout = timeout.map(|timeout| c::timespec { - tv_sec: timeout.as_secs().try_into().unwrap(), - tv_nsec: timeout.subsec_nanos() as _, - }); - - syscalls::port_getn( - port.as_fd(), - timeout.as_mut(), - events, - min_events.try_into().unwrap(), - ) -} - -/// `port_send(port, events, userdata)`—Sends an event to a port. -/// -/// # References -/// - [OpenSolaris] -/// - [illumos] -/// -/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_send/ -/// [illumos]: https://illumos.org/man/3C/port_send -pub fn port_send(port: impl AsFd, events: i32, userdata: *mut c::c_void) -> io::Result<()> { - syscalls::port_send(port.as_fd(), events, userdata.cast()) -} diff --git a/vendor/rustix/src/io/procfs.rs b/vendor/rustix/src/io/procfs.rs deleted file mode 100644 index 605354759..000000000 --- a/vendor/rustix/src/io/procfs.rs +++ /dev/null @@ -1,464 +0,0 @@ -//! Utilities for working with `/proc`, where Linux's `procfs` is typically -//! mounted. `/proc` serves as an adjunct to Linux's main syscall surface area, -//! providing additional features with an awkward interface. -//! -//! This module does a considerable amount of work to determine whether `/proc` -//! is mounted, with actual `procfs`, and without any additional mount points -//! on top of the paths we open. -//! -//! Why all the effort to detect bind mount points? People are doing all kinds -//! of things with Linux containers these days, with many different privilege -//! schemes, and we want to avoid making any unnecessary assumptions. Rustix -//! and its users will sometimes use procfs *implicitly* (when Linux gives them -//! no better options), in ways that aren't obvious from their public APIs. -//! These filesystem accesses might not be visible to someone auditing the main -//! code of an application for places which may be influenced by the filesystem -//! namespace. So with the checking here, they may fail, but they won't be able -//! to succeed with bogus results. - -use crate::fd::{AsFd, BorrowedFd, OwnedFd}; -use crate::ffi::CStr; -use crate::fs::{ - cwd, fstat, fstatfs, major, openat, renameat, Dir, FileType, Mode, OFlags, Stat, - PROC_SUPER_MAGIC, -}; -use crate::io; -use crate::path::DecInt; -use crate::process::getpid; -#[cfg(feature = "rustc-dep-of-std")] -use core::lazy::OnceCell; -#[cfg(not(feature = "rustc-dep-of-std"))] -use once_cell::sync::OnceCell; - -/// Linux's procfs always uses inode 1 for its root directory. -const PROC_ROOT_INO: u64 = 1; - -// Identify an entry within "/proc", to determine which anomalies to check for. -#[derive(Copy, Clone, Debug)] -enum Kind { - Proc, - Pid, - Fd, - File, -} - -/// Check a subdirectory of "/proc" for anomalies. -fn check_proc_entry( - kind: Kind, - entry: BorrowedFd<'_>, - proc_stat: Option<&Stat>, -) -> io::Result { - let entry_stat = fstat(entry)?; - check_proc_entry_with_stat(kind, entry, entry_stat, proc_stat) -} - -/// Check a subdirectory of "/proc" for anomalies, using the provided `Stat`. -fn check_proc_entry_with_stat( - kind: Kind, - entry: BorrowedFd<'_>, - entry_stat: Stat, - proc_stat: Option<&Stat>, -) -> io::Result { - // Check the filesystem magic. - check_procfs(entry)?; - - match kind { - Kind::Proc => check_proc_root(entry, &entry_stat)?, - Kind::Pid | Kind::Fd => check_proc_subdir(entry, &entry_stat, proc_stat)?, - Kind::File => check_proc_file(&entry_stat, proc_stat)?, - } - - // "/proc" directories are typically mounted r-xr-xr-x. - // "/proc/self/fd" is r-x------. Allow them to have fewer permissions, but - // not more. - let expected_mode = if let Kind::Fd = kind { 0o500 } else { 0o555 }; - if entry_stat.st_mode & 0o777 & !expected_mode != 0 { - return Err(io::Errno::NOTSUP); - } - - match kind { - Kind::Fd => { - // Check that the "/proc/self/fd" directory doesn't have any extraneous - // links into it (which might include unexpected subdirectories). - if entry_stat.st_nlink != 2 { - return Err(io::Errno::NOTSUP); - } - } - Kind::Pid | Kind::Proc => { - // Check that the "/proc" and "/proc/self" directories aren't empty. - if entry_stat.st_nlink <= 2 { - return Err(io::Errno::NOTSUP); - } - } - Kind::File => { - // Check that files in procfs don't have extraneous hard links to - // them (which might indicate hard links to other things). - if entry_stat.st_nlink != 1 { - return Err(io::Errno::NOTSUP); - } - } - } - - Ok(entry_stat) -} - -fn check_proc_root(entry: BorrowedFd<'_>, stat: &Stat) -> io::Result<()> { - // We use `O_DIRECTORY` for proc directories, so open should fail if we - // don't get a directory when we expect one. - assert_eq!(FileType::from_raw_mode(stat.st_mode), FileType::Directory); - - // Check the root inode number. - if stat.st_ino != PROC_ROOT_INO { - return Err(io::Errno::NOTSUP); - } - - // Proc is a non-device filesystem, so check for major number 0. - // - if major(stat.st_dev) != 0 { - return Err(io::Errno::NOTSUP); - } - - // Check that "/proc" is a mountpoint. - if !is_mountpoint(entry) { - return Err(io::Errno::NOTSUP); - } - - Ok(()) -} - -fn check_proc_subdir( - entry: BorrowedFd<'_>, - stat: &Stat, - proc_stat: Option<&Stat>, -) -> io::Result<()> { - // We use `O_DIRECTORY` for proc directories, so open should fail if we - // don't get a directory when we expect one. - assert_eq!(FileType::from_raw_mode(stat.st_mode), FileType::Directory); - - check_proc_nonroot(stat, proc_stat)?; - - // Check that subdirectories of "/proc" are not mount points. - if is_mountpoint(entry) { - return Err(io::Errno::NOTSUP); - } - - Ok(()) -} - -fn check_proc_file(stat: &Stat, proc_stat: Option<&Stat>) -> io::Result<()> { - // Check that we have a regular file. - if FileType::from_raw_mode(stat.st_mode) != FileType::RegularFile { - return Err(io::Errno::NOTSUP); - } - - check_proc_nonroot(stat, proc_stat)?; - - Ok(()) -} - -fn check_proc_nonroot(stat: &Stat, proc_stat: Option<&Stat>) -> io::Result<()> { - // Check that we haven't been linked back to the root of "/proc". - if stat.st_ino == PROC_ROOT_INO { - return Err(io::Errno::NOTSUP); - } - - // Check that we're still in procfs. - if stat.st_dev != proc_stat.unwrap().st_dev { - return Err(io::Errno::NOTSUP); - } - - Ok(()) -} - -/// Check that `file` is opened on a `procfs` filesystem. -fn check_procfs(file: BorrowedFd<'_>) -> io::Result<()> { - let statfs = fstatfs(file)?; - let f_type = statfs.f_type; - if f_type != PROC_SUPER_MAGIC { - return Err(io::Errno::NOTSUP); - } - - Ok(()) -} - -/// Check whether the given directory handle is a mount point. -fn is_mountpoint(file: BorrowedFd<'_>) -> bool { - // We use a `renameat` call that would otherwise fail, but which fails with - // `XDEV` first if it would cross a mount point. - let err = renameat(file, cstr!("../."), file, cstr!(".")).unwrap_err(); - match err { - io::Errno::XDEV => true, // the rename failed due to crossing a mount point - io::Errno::BUSY => false, // the rename failed normally - _ => panic!("Unexpected error from `renameat`: {:?}", err), - } -} - -/// Open a directory in `/proc`, mapping all errors to `io::Errno::NOTSUP`. -fn proc_opendirat(dirfd: Fd, path: P) -> io::Result { - // We could add `PATH`|`NOATIME` here but Linux 2.6.32 doesn't support it. - // Also for `NOATIME` see the comment in `open_and_check_file`. - let oflags = OFlags::NOFOLLOW | OFlags::DIRECTORY | OFlags::CLOEXEC | OFlags::NOCTTY; - openat(dirfd, path, oflags, Mode::empty()).map_err(|_err| io::Errno::NOTSUP) -} - -/// Returns a handle to Linux's `/proc` directory. -/// -/// This ensures that `/proc` is procfs, that nothing is mounted on top of it, -/// and that it looks normal. It also returns the `Stat` of `/proc`. -/// -/// # References -/// - [Linux] -/// -/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html -fn proc() -> io::Result<(BorrowedFd<'static>, &'static Stat)> { - static PROC: StaticFd = StaticFd::new(); - - // `OnceBox` is "racey" in that the initialization function may run - // multiple times. We're ok with that, since the initialization function - // has no side effects. - PROC.get_or_try_init(|| { - // Open "/proc". - let proc = proc_opendirat(cwd(), cstr!("/proc"))?; - let proc_stat = - check_proc_entry(Kind::Proc, proc.as_fd(), None).map_err(|_err| io::Errno::NOTSUP)?; - - Ok(new_static_fd(proc, proc_stat)) - }) - .map(|(fd, stat)| (fd.as_fd(), stat)) -} - -/// Returns a handle to Linux's `/proc/self` directory. -/// -/// This ensures that `/proc/self` is procfs, that nothing is mounted on top of -/// it, and that it looks normal. It also returns the `Stat` of `/proc/self`. -/// -/// # References -/// - [Linux] -/// -/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html -fn proc_self() -> io::Result<(BorrowedFd<'static>, &'static Stat)> { - static PROC_SELF: StaticFd = StaticFd::new(); - - // The init function here may run multiple times; see above. - PROC_SELF - .get_or_try_init(|| { - let (proc, proc_stat) = proc()?; - - let pid = getpid(); - - // Open "/proc/self". Use our pid to compute the name rather than literally - // using "self", as "self" is a symlink. - let proc_self = proc_opendirat(proc, DecInt::new(pid.as_raw_nonzero().get()))?; - let proc_self_stat = check_proc_entry(Kind::Pid, proc_self.as_fd(), Some(proc_stat)) - .map_err(|_err| io::Errno::NOTSUP)?; - - Ok(new_static_fd(proc_self, proc_self_stat)) - }) - .map(|(owned, stat)| (owned.as_fd(), stat)) -} - -/// Returns a handle to Linux's `/proc/self/fd` directory. -/// -/// This ensures that `/proc/self/fd` is `procfs`, that nothing is mounted on -/// top of it, and that it looks normal. -/// -/// # References -/// - [Linux] -/// -/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html -#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))] -pub fn proc_self_fd() -> io::Result> { - static PROC_SELF_FD: StaticFd = StaticFd::new(); - - // The init function here may run multiple times; see above. - PROC_SELF_FD - .get_or_try_init(|| { - let (_, proc_stat) = proc()?; - - let (proc_self, _proc_self_stat) = proc_self()?; - - // Open "/proc/self/fd". - let proc_self_fd = proc_opendirat(proc_self, cstr!("fd"))?; - let proc_self_fd_stat = - check_proc_entry(Kind::Fd, proc_self_fd.as_fd(), Some(proc_stat)) - .map_err(|_err| io::Errno::NOTSUP)?; - - Ok(new_static_fd(proc_self_fd, proc_self_fd_stat)) - }) - .map(|(owned, _stat)| owned.as_fd()) -} - -type StaticFd = OnceCell<(OwnedFd, Stat)>; - -#[inline] -fn new_static_fd(fd: OwnedFd, stat: Stat) -> (OwnedFd, Stat) { - (fd, stat) -} - -/// Returns a handle to Linux's `/proc/self/fdinfo` directory. -/// -/// This ensures that `/proc/self/fdinfo` is `procfs`, that nothing is mounted -/// on top of it, and that it looks normal. It also returns the `Stat` of -/// `/proc/self/fd`. -/// -/// # References -/// - [Linux] -/// -/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html -fn proc_self_fdinfo() -> io::Result<(BorrowedFd<'static>, &'static Stat)> { - static PROC_SELF_FDINFO: StaticFd = StaticFd::new(); - - PROC_SELF_FDINFO - .get_or_try_init(|| { - let (_, proc_stat) = proc()?; - - let (proc_self, _proc_self_stat) = proc_self()?; - - // Open "/proc/self/fdinfo". - let proc_self_fdinfo = proc_opendirat(proc_self, cstr!("fdinfo"))?; - let proc_self_fdinfo_stat = - check_proc_entry(Kind::Fd, proc_self_fdinfo.as_fd(), Some(proc_stat)) - .map_err(|_err| io::Errno::NOTSUP)?; - - Ok((proc_self_fdinfo, proc_self_fdinfo_stat)) - }) - .map(|(owned, stat)| (owned.as_fd(), stat)) -} - -/// Returns a handle to a Linux `/proc/self/fdinfo/` file. -/// -/// This ensures that `/proc/self/fdinfo/` is `procfs`, that nothing is -/// mounted on top of it, and that it looks normal. -/// -/// # References -/// - [Linux] -/// -/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html -#[inline] -#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))] -pub fn proc_self_fdinfo_fd(fd: Fd) -> io::Result { - _proc_self_fdinfo(fd.as_fd()) -} - -fn _proc_self_fdinfo(fd: BorrowedFd<'_>) -> io::Result { - let (proc_self_fdinfo, proc_self_fdinfo_stat) = proc_self_fdinfo()?; - let fd_str = DecInt::from_fd(fd); - open_and_check_file(proc_self_fdinfo, proc_self_fdinfo_stat, fd_str.as_c_str()) -} - -/// Returns a handle to a Linux `/proc/self/pagemap` file. -/// -/// This ensures that `/proc/self/pagemap` is `procfs`, that nothing is -/// mounted on top of it, and that it looks normal. -/// -/// # References -/// - [Linux] -/// - [Linux pagemap] -/// -/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html -/// [Linux pagemap]: https://www.kernel.org/doc/Documentation/vm/pagemap.txt -#[inline] -#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))] -pub fn proc_self_pagemap() -> io::Result { - proc_self_file(cstr!("pagemap")) -} - -/// Returns a handle to a Linux `/proc/self/maps` file. -/// -/// This ensures that `/proc/self/maps` is `procfs`, that nothing is -/// mounted on top of it, and that it looks normal. -/// -/// # References -/// - [Linux] -/// -/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html -#[inline] -#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))] -pub fn proc_self_maps() -> io::Result { - proc_self_file(cstr!("maps")) -} - -/// Returns a handle to a Linux `/proc/self/status` file. -/// -/// This ensures that `/proc/self/status` is `procfs`, that nothing is -/// mounted on top of it, and that it looks normal. -/// -/// # References -/// - [Linux] -/// -/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html -#[inline] -#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))] -pub fn proc_self_status() -> io::Result { - proc_self_file(cstr!("status")) -} - -/// Open a file under `/proc/self`. -fn proc_self_file(name: &CStr) -> io::Result { - let (proc_self, proc_self_stat) = proc_self()?; - open_and_check_file(proc_self, proc_self_stat, name) -} - -/// Open a procfs file within in `dir` and check it for bind mounts. -fn open_and_check_file(dir: BorrowedFd, dir_stat: &Stat, name: &CStr) -> io::Result { - let (_, proc_stat) = proc()?; - - // Don't use `NOATIME`, because it [requires us to own the file], and when - // a process sets itself non-dumpable Linux changes the user:group of its - // `/proc/` files [to root:root]. - // - // [requires us to own the file]: https://man7.org/linux/man-pages/man2/openat.2.html - // [to root:root]: https://man7.org/linux/man-pages/man5/proc.5.html - let oflags = OFlags::RDONLY | OFlags::CLOEXEC | OFlags::NOFOLLOW | OFlags::NOCTTY; - let file = openat(dir, name, oflags, Mode::empty()).map_err(|_err| io::Errno::NOTSUP)?; - let file_stat = fstat(&file)?; - - // `is_mountpoint` only works on directory mount points, not file mount - // points. To detect file mount points, scan the parent directory to see - // if we can find a regular file with an inode and name that matches the - // file we just opened. If we can't find it, there could be a file bind - // mount on top of the file we want. - // - // As we scan, we also check for ".", to make sure it's the same directory - // as our original directory, to detect mount points, since - // `Dir::read_from` reopens ".". - // - // TODO: With Linux 5.8 we might be able to use `statx` and - // `STATX_ATTR_MOUNT_ROOT` to detect mountpoints directly instead of doing - // this scanning. - let dir = Dir::read_from(dir).map_err(|_err| io::Errno::NOTSUP)?; - - // Confirm that we got the same inode. - let dot_stat = dir.stat().map_err(|_err| io::Errno::NOTSUP)?; - if (dot_stat.st_dev, dot_stat.st_ino) != (dir_stat.st_dev, dir_stat.st_ino) { - return Err(io::Errno::NOTSUP); - } - - let mut found_file = false; - let mut found_dot = false; - for entry in dir { - let entry = entry.map_err(|_err| io::Errno::NOTSUP)?; - if entry.ino() == file_stat.st_ino - && entry.file_type() == FileType::RegularFile - && entry.file_name() == name - { - // We found the file. Proceed to check the file handle. - let _ = - check_proc_entry_with_stat(Kind::File, file.as_fd(), file_stat, Some(proc_stat))?; - - found_file = true; - } else if entry.ino() == dir_stat.st_ino - && entry.file_type() == FileType::Directory - && entry.file_name() == cstr!(".") - { - // We found ".", and it's the right ".". - found_dot = true; - } - } - - if found_file && found_dot { - Ok(file) - } else { - Err(io::Errno::NOTSUP) - } -} diff --git a/vendor/rustix/src/io/read_write.rs b/vendor/rustix/src/io/read_write.rs index 918bb9323..32cbda225 100644 --- a/vendor/rustix/src/io/read_write.rs +++ b/vendor/rustix/src/io/read_write.rs @@ -5,13 +5,9 @@ use backend::fd::AsFd; // Declare `IoSlice` and `IoSliceMut`. #[cfg(not(windows))] -#[cfg(not(feature = "std"))] -pub use backend::io::io_slice::{IoSlice, IoSliceMut}; -#[cfg(not(windows))] -#[cfg(feature = "std")] -pub use std::io::{IoSlice, IoSliceMut}; +pub use crate::maybe_polyfill::io::{IoSlice, IoSliceMut}; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use backend::io::types::ReadWriteFlags; /// `read(fd, buf)`—Reads from a stream. @@ -230,7 +226,7 @@ pub fn pwritev(fd: Fd, bufs: &[IoSlice<'_>], offset: u64) -> io::Resul /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/preadv2.2.html -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] pub fn preadv2( fd: Fd, @@ -249,7 +245,7 @@ pub fn preadv2( /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/pwritev2.2.html -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] pub fn pwritev2( fd: Fd, diff --git a/vendor/rustix/src/io/seek_from.rs b/vendor/rustix/src/io/seek_from.rs deleted file mode 100644 index cca23ed62..000000000 --- a/vendor/rustix/src/io/seek_from.rs +++ /dev/null @@ -1,48 +0,0 @@ -//! The following is derived from Rust's -//! library/std/src/io/mod.rs at revision -//! dca3f1b786efd27be3b325ed1e01e247aa589c3b. - -/// Enumeration of possible methods to seek within an I/O object. -/// -/// It is used by the [`Seek`] trait. -/// -/// [`Seek`]: std::io::Seek -#[derive(Copy, PartialEq, Eq, Clone, Debug)] -#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] -pub enum SeekFrom { - /// Sets the offset to the provided number of bytes. - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - Start(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] u64), - - /// Sets the offset to the size of this object plus the specified number of - /// bytes. - /// - /// It is possible to seek beyond the end of an object, but it's an error - /// to seek before byte 0. - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - End(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] i64), - - /// Sets the offset to the current position plus the specified number of - /// bytes. - /// - /// It is possible to seek beyond the end of an object, but it's an error - /// to seek before byte 0. - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - Current(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] i64), - - /// Sets the offset to the current position plus the specified number of bytes, - /// plus the distance to the next byte which is not in a hole. - /// - /// If the offset is in a hole at the end of the file, the seek will produce - /// an `NXIO` error. - #[cfg(any(freebsdlike, target_os = "linux", target_os = "solaris"))] - Data(i64), - - /// Sets the offset to the current position plus the specified number of bytes, - /// plus the distance to the next byte which is in a hole. - /// - /// If there is no hole past the offset, it will be set to the end of the file - /// i.e. there is an implicit hole at the end of any file. - #[cfg(any(freebsdlike, target_os = "linux", target_os = "solaris"))] - Hole(i64), -} diff --git a/vendor/rustix/src/io/stdio.rs b/vendor/rustix/src/io/stdio.rs deleted file mode 100644 index adfb776d5..000000000 --- a/vendor/rustix/src/io/stdio.rs +++ /dev/null @@ -1,509 +0,0 @@ -//! Functions returning the stdio file descriptors. -//! -//! # Safety -//! -//! These access the file descriptors by absolute index value, and nothing -//! prevents them from being closed and reused. They should only be used in -//! `main` or other situations where one is in control of the process' -//! stdio streams. -#![allow(unsafe_code)] - -use crate::backend; -use crate::fd::OwnedFd; -use backend::fd::{BorrowedFd, FromRawFd, RawFd}; - -#[cfg(not(any(windows, target_os = "wasi")))] -use crate::io; -#[cfg(not(any(windows, target_os = "wasi")))] -use backend::fd::AsFd; - -/// `STDIN_FILENO`—Standard input, borrowed. -/// -/// In `std`-using configurations, this is a safe function, because the -/// standard library already assumes that the stdin file descriptor is always -/// valid. In `no_std` configurations, it is `unsafe`. -/// -/// # Warning -/// -/// This function allows reading directly from stdin without coordinating -/// with the buffering performed by [`std::io::Stdin`], so it could cause -/// corrupted input. -/// -/// # References -/// - [POSIX] -/// - [Linux] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html -/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdin&sektion=4 -/// [NetBSD]: https://man.netbsd.org/stdin.4 -/// [OpenBSD]: https://man.openbsd.org/stdin.4 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdin§ion=4 -/// [illumos]: https://illumos.org/man/4FS/stdin -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stdin -#[cfg(feature = "std")] -#[doc(alias = "STDIN_FILENO")] -#[inline] -pub const fn stdin() -> BorrowedFd<'static> { - // SAFETY: When "std" is enabled, the standard library assumes that the stdio - // file descriptors are all valid. - unsafe { BorrowedFd::borrow_raw(backend::io::types::STDIN_FILENO as RawFd) } -} - -/// `STDIN_FILENO`—Standard input, borrowed. -/// -/// In `std`-using configurations, this is a safe function, because the -/// standard library already assumes that the stdin file descriptor is always -/// valid. In `no_std` configurations, it is `unsafe`. -/// -/// # Safety -/// -/// In `no_std` configurations, the stdin file descriptor can be closed, -/// potentially on other threads, in which case the file descriptor index -/// value could be dynamically reused for other purposes, potentially on -/// different threads. -/// -/// # Warning -/// -/// This function allows reading directly from stdin without coordinating -/// with the buffering performed by [`std::io::Stdin`], so it could cause -/// corrupted input. -/// -/// # References -/// - [POSIX] -/// - [Linux] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html -/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdin&sektion=4 -/// [NetBSD]: https://man.netbsd.org/stdin.4 -/// [OpenBSD]: https://man.openbsd.org/stdin.4 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdin§ion=4 -/// [illumos]: https://illumos.org/man/4FS/stdin -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stdin -#[cfg(not(feature = "std"))] -#[doc(alias = "STDIN_FILENO")] -#[inline] -pub const unsafe fn stdin() -> BorrowedFd<'static> { - BorrowedFd::borrow_raw(backend::io::types::STDIN_FILENO as RawFd) -} - -/// `STDIN_FILENO`—Standard input, owned. -/// -/// This is similar to [`stdin`], however it returns an `OwnedFd` which closes -/// standard input when it is dropped. -/// -/// # Safety -/// -/// Safe `std`-using Rust code is permitted to assume that the stdin file -/// descriptor is always valid. This function returns an `OwnedFd` which will -/// close the stdin file descriptor when dropped. -/// -/// # Warning -/// -/// This has the same hazards as [`stdin`]. -/// -/// # References -/// - [POSIX] -/// - [Linux] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html -/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdin&sektion=4 -/// [NetBSD]: https://man.netbsd.org/stdin.4 -/// [OpenBSD]: https://man.openbsd.org/stdin.4 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdin§ion=4 -/// [illumos]: https://illumos.org/man/4FS/stdin -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stdin -#[doc(alias = "STDIN_FILENO")] -#[inline] -pub unsafe fn take_stdin() -> OwnedFd { - backend::fd::OwnedFd::from_raw_fd(backend::io::types::STDIN_FILENO as RawFd) -} - -/// `STDOUT_FILENO`—Standard output, borrowed. -/// -/// In `std`-using configurations, this is a safe function, because the -/// standard library already assumes that the stdout file descriptor is always -/// valid. In `no_std` configurations, it is `unsafe`. -/// -/// # Warning -/// -/// This function allows reading directly from stdout without coordinating -/// with the buffering performed by [`std::io::Stdout`], so it could cause -/// corrupted input. -/// -/// # References -/// - [POSIX] -/// - [Linux] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdout.html -/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdout&sektion=4 -/// [NetBSD]: https://man.netbsd.org/stdout.4 -/// [OpenBSD]: https://man.openbsd.org/stdout.4 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdout§ion=4 -/// [illumos]: https://illumos.org/man/4FS/stdout -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stdout -#[cfg(feature = "std")] -#[doc(alias = "STDOUT_FILENO")] -#[inline] -pub const fn stdout() -> BorrowedFd<'static> { - // SAFETY: When "std" is enabled, the standard library assumes that the stdio - // file descriptors are all valid. - unsafe { BorrowedFd::borrow_raw(backend::io::types::STDOUT_FILENO as RawFd) } -} - -/// `STDOUT_FILENO`—Standard output, borrowed. -/// -/// In `std`-using configurations, this is a safe function, because the -/// standard library already assumes that the stdout file descriptor is always -/// valid. In `no_std` configurations, it is `unsafe`. -/// -/// # Safety -/// -/// In `no_std` configurations, the stdout file descriptor can be closed, -/// potentially on other threads, in which case the file descriptor index -/// value could be dynamically reused for other purposes, potentially on -/// different threads. -/// -/// # Warning -/// -/// This function allows reading directly from stdout without coordinating -/// with the buffering performed by [`std::io::Stdout`], so it could cause -/// corrupted input. -/// -/// # References -/// - [POSIX] -/// - [Linux] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdout.html -/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdout&sektion=4 -/// [NetBSD]: https://man.netbsd.org/stdout.4 -/// [OpenBSD]: https://man.openbsd.org/stdout.4 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdout§ion=4 -/// [illumos]: https://illumos.org/man/4FS/stdout -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stdout -#[cfg(not(feature = "std"))] -#[doc(alias = "STDOUT_FILENO")] -#[inline] -pub const unsafe fn stdout() -> BorrowedFd<'static> { - BorrowedFd::borrow_raw(backend::io::types::STDOUT_FILENO as RawFd) -} - -/// `STDOUT_FILENO`—Standard output, owned. -/// -/// This is similar to [`stdout`], however it returns an `OwnedFd` which closes -/// standard output when it is dropped. -/// -/// # Safety -/// -/// Safe `std`-using Rust code is permitted to assume that the stdout file -/// descriptor is always valid. This function returns an `OwnedFd` which will -/// close the stdout file descriptor when dropped. -/// -/// # Warning -/// -/// This has the same hazards as [`stdout`]. -/// -/// # References -/// - [POSIX] -/// - [Linux] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdout.html -/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdout&sektion=4 -/// [NetBSD]: https://man.netbsd.org/stdout.4 -/// [OpenBSD]: https://man.openbsd.org/stdout.4 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdout§ion=4 -/// [illumos]: https://illumos.org/man/4FS/stdout -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stdout -#[doc(alias = "STDOUT_FILENO")] -#[inline] -pub unsafe fn take_stdout() -> OwnedFd { - backend::fd::OwnedFd::from_raw_fd(backend::io::types::STDOUT_FILENO as RawFd) -} - -/// `STDERR_FILENO`—Standard error, borrowed. -/// -/// In `std`-using configurations, this is a safe function, because the -/// standard library already assumes that the stderr file descriptor is always -/// valid. In `no_std` configurations, it is `unsafe`. -/// -/// # References -/// - [POSIX] -/// - [Linux] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stderr.html -/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stderr&sektion=4 -/// [NetBSD]: https://man.netbsd.org/stderr.4 -/// [OpenBSD]: https://man.openbsd.org/stderr.4 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stderr§ion=4 -/// [illumos]: https://illumos.org/man/4FS/stderr -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stderr -#[cfg(feature = "std")] -#[doc(alias = "STDERR_FILENO")] -#[inline] -pub const fn stderr() -> BorrowedFd<'static> { - // SAFETY: When "std" is enabled, the standard library assumes that the stdio - // file descriptors are all valid. - unsafe { BorrowedFd::borrow_raw(backend::io::types::STDERR_FILENO as RawFd) } -} - -/// `STDERR_FILENO`—Standard error, borrowed. -/// -/// In `std`-using configurations, this is a safe function, because the -/// standard library already assumes that the stderr file descriptor is always -/// valid. In `no_std` configurations, it is `unsafe`. -/// -/// # Safety -/// -/// In `no_std` configurations, the stderr file descriptor can be closed, -/// potentially on other threads, in which case the file descriptor index -/// value could be dynamically reused for other purposes, potentially on -/// different threads. -/// -/// # References -/// - [POSIX] -/// - [Linux] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stderr.html -/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stderr&sektion=4 -/// [NetBSD]: https://man.netbsd.org/stderr.4 -/// [OpenBSD]: https://man.openbsd.org/stderr.4 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stderr§ion=4 -/// [illumos]: https://illumos.org/man/4FS/stderr -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stderr -#[cfg(not(feature = "std"))] -#[doc(alias = "STDERR_FILENO")] -#[inline] -pub const unsafe fn stderr() -> BorrowedFd<'static> { - BorrowedFd::borrow_raw(backend::io::types::STDERR_FILENO as RawFd) -} - -/// `STDERR_FILENO`—Standard error, owned. -/// -/// This is similar to [`stderr`], however it returns an `OwnedFd` which closes -/// standard output when it is dropped. -/// -/// # Safety -/// -/// Safe std-using Rust code is permitted to assume that the stderr file -/// descriptor is always valid. This function returns an `OwnedFd` which will -/// close the stderr file descriptor when dropped. -/// -/// # Other hazards -/// -/// This has the same hazards as [`stderr`]. -/// -/// And, when the `OwnedFd` is dropped, subsequent newly created file -/// descriptors may unknowingly reuse the stderr file descriptor number, which -/// may break common assumptions, so it should typically only be dropped at the -/// end of a program when no more file descriptors will be created. -/// -/// # References -/// - [POSIX] -/// - [Linux] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stderr.html -/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stderr&sektion=4 -/// [NetBSD]: https://man.netbsd.org/stderr.4 -/// [OpenBSD]: https://man.openbsd.org/stderr.4 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stderr§ion=4 -/// [illumos]: https://illumos.org/man/4FS/stderr -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stderr -#[doc(alias = "STDERR_FILENO")] -#[inline] -pub unsafe fn take_stderr() -> OwnedFd { - backend::fd::OwnedFd::from_raw_fd(backend::io::types::STDERR_FILENO as RawFd) -} - -/// `STDIN_FILENO`—Standard input, raw. -/// -/// This is similar to [`stdin`], however it returns a `RawFd`. -/// -/// # Other hazards -/// -/// This has the same hazards as [`stdin`]. -/// -/// # References -/// - [POSIX] -/// - [Linux] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html -/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdin&sektion=4 -/// [NetBSD]: https://man.netbsd.org/stdin.4 -/// [OpenBSD]: https://man.openbsd.org/stdin.4 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdin§ion=4 -/// [illumos]: https://illumos.org/man/4FS/stdin -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stdin -#[doc(alias = "STDIN_FILENO")] -#[inline] -pub const fn raw_stdin() -> RawFd { - backend::io::types::STDIN_FILENO as RawFd -} - -/// `STDOUT_FILENO`—Standard output, raw. -/// -/// This is similar to [`stdout`], however it returns a `RawFd`. -/// -/// # Other hazards -/// -/// This has the same hazards as [`stdout`]. -/// -/// # References -/// - [POSIX] -/// - [Linux] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdout.html -/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdout&sektion=4 -/// [NetBSD]: https://man.netbsd.org/stdout.4 -/// [OpenBSD]: https://man.openbsd.org/stdout.4 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdout§ion=4 -/// [illumos]: https://illumos.org/man/4FS/stdout -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stdout -#[doc(alias = "STDOUT_FILENO")] -#[inline] -pub const fn raw_stdout() -> RawFd { - backend::io::types::STDOUT_FILENO as RawFd -} - -/// `STDERR_FILENO`—Standard error, raw. -/// -/// This is similar to [`stderr`], however it returns a `RawFd`. -/// -/// # Other hazards -/// -/// This has the same hazards as [`stderr`]. -/// -/// # References -/// - [POSIX] -/// - [Linux] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stderr.html -/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stderr&sektion=4 -/// [NetBSD]: https://man.netbsd.org/stderr.4 -/// [OpenBSD]: https://man.openbsd.org/stderr.4 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stderr§ion=4 -/// [illumos]: https://illumos.org/man/4FS/stderr -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stderr -#[doc(alias = "STDERR_FILENO")] -#[inline] -pub const fn raw_stderr() -> RawFd { - backend::io::types::STDERR_FILENO as RawFd -} - -/// Utility function to safely `dup2` over stdin (fd 0). -#[cfg(not(any(windows, target_os = "wasi")))] -#[inline] -pub fn dup2_stdin(fd: Fd) -> io::Result<()> { - // SAFETY: We pass the returned `OwnedFd` to `forget` so that it isn't - // dropped. - let mut target = unsafe { io::take_stdin() }; - backend::io::syscalls::dup2(fd.as_fd(), &mut target)?; - core::mem::forget(target); - Ok(()) -} - -/// Utility function to safely `dup2` over stdout (fd 1). -#[cfg(not(any(windows, target_os = "wasi")))] -#[inline] -pub fn dup2_stdout(fd: Fd) -> io::Result<()> { - // SAFETY: We pass the returned `OwnedFd` to `forget` so that it isn't - // dropped. - let mut target = unsafe { io::take_stdout() }; - backend::io::syscalls::dup2(fd.as_fd(), &mut target)?; - core::mem::forget(target); - Ok(()) -} - -/// Utility function to safely `dup2` over stderr (fd 2). -#[cfg(not(any(windows, target_os = "wasi")))] -#[inline] -pub fn dup2_stderr(fd: Fd) -> io::Result<()> { - // SAFETY: We pass the returned `OwnedFd` to `forget` so that it isn't - // dropped. - let mut target = unsafe { io::take_stderr() }; - backend::io::syscalls::dup2(fd.as_fd(), &mut target)?; - core::mem::forget(target); - Ok(()) -} diff --git a/vendor/rustix/src/io_uring.rs b/vendor/rustix/src/io_uring.rs index b94b458f5..93feb2780 100644 --- a/vendor/rustix/src/io_uring.rs +++ b/vendor/rustix/src/io_uring.rs @@ -5,6 +5,8 @@ //! `Result`, `OwnedFd`, `AsFd`, `RawFd`, and `*mut c_void` in place of plain //! integers. //! +//! For a higher-level API built on top of this, see the [rustix-uring] crate. +//! //! # Safety //! //! io_uring operates on raw pointers and raw file descriptors. Rustix does not @@ -19,13 +21,21 @@ //! [Linux]: https://man.archlinux.org/man/io_uring.7.en //! [io_uring]: https://en.wikipedia.org/wiki/Io_uring //! [io_uring header]: https://github.com/torvalds/linux/blob/master/include/uapi/linux/io_uring.h +//! [rustix-uring]: https://crates.io/crates/rustix-uring #![allow(unsafe_code)] use crate::fd::{AsFd, BorrowedFd, OwnedFd, RawFd}; use crate::{backend, io}; use core::ffi::c_void; -use core::ptr::null_mut; -use linux_raw_sys::general as sys; +use core::mem::{zeroed, MaybeUninit}; +use core::ptr::{null_mut, write_bytes}; +use linux_raw_sys::net; + +mod sys { + pub(super) use linux_raw_sys::io_uring::*; + #[cfg(test)] + pub(super) use {crate::backend::c::iovec, linux_raw_sys::general::open_how}; +} /// `io_uring_setup(entries, params)`—Setup a context for performing /// asynchronous I/O. @@ -96,7 +106,8 @@ pub unsafe fn io_uring_enter( bitflags::bitflags! { /// `IORING_ENTER_*` flags for use with [`io_uring_enter`]. - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringEnterFlags: u32 { /// `IORING_ENTER_GETEVENTS` const GETEVENTS = sys::IORING_ENTER_GETEVENTS; @@ -400,7 +411,8 @@ pub enum IoringMsgringCmds { bitflags::bitflags! { /// `IORING_SETUP_*` flags for use with [`io_uring_params`]. - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringSetupFlags: u32 { /// `IORING_SETUP_ATTACH_WQ` const ATTACH_WQ = sys::IORING_SETUP_ATTACH_WQ; @@ -448,7 +460,8 @@ bitflags::bitflags! { bitflags::bitflags! { /// `IOSQE_*` flags for use with [`io_uring_sqe`]. - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringSqeFlags: u8 { /// `1 << IOSQE_ASYNC_BIT` const ASYNC = 1 << sys::IOSQE_ASYNC_BIT as u8; @@ -475,25 +488,27 @@ bitflags::bitflags! { bitflags::bitflags! { /// `IORING_CQE_F_*` flags for use with [`io_uring_cqe`]. - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringCqeFlags: u32 { /// `IORING_CQE_F_BUFFER` - const BUFFER = sys::IORING_CQE_F_BUFFER as _; + const BUFFER = bitcast!(sys::IORING_CQE_F_BUFFER); /// `IORING_CQE_F_MORE` - const MORE = sys::IORING_CQE_F_MORE as _; + const MORE = bitcast!(sys::IORING_CQE_F_MORE); /// `IORING_CQE_F_SOCK_NONEMPTY` - const SOCK_NONEMPTY = sys::IORING_CQE_F_SOCK_NONEMPTY as _; + const SOCK_NONEMPTY = bitcast!(sys::IORING_CQE_F_SOCK_NONEMPTY); /// `IORING_CQE_F_NOTIF` - const NOTIF = sys::IORING_CQE_F_NOTIF as _; + const NOTIF = bitcast!(sys::IORING_CQE_F_NOTIF); } } bitflags::bitflags! { /// `IORING_FSYNC_*` flags for use with [`io_uring_sqe`]. - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringFsyncFlags: u32 { /// `IORING_FSYNC_DATASYNC` const DATASYNC = sys::IORING_FSYNC_DATASYNC; @@ -503,7 +518,8 @@ bitflags::bitflags! { bitflags::bitflags! { /// `IORING_TIMEOUT_*` and `IORING_LINK_TIMEOUT_UPDATE` flags for use with /// [`io_uring_sqe`]. - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringTimeoutFlags: u32 { /// `IORING_TIMEOUT_ABS` const ABS = sys::IORING_TIMEOUT_ABS; @@ -533,7 +549,8 @@ bitflags::bitflags! { bitflags::bitflags! { /// `SPLICE_F_*` flags for use with [`io_uring_sqe`]. - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct SpliceFlags: u32 { /// `SPLICE_F_FD_IN_FIXED` const FD_IN_FIXED = sys::SPLICE_F_FD_IN_FIXED; @@ -542,7 +559,8 @@ bitflags::bitflags! { bitflags::bitflags! { /// `IORING_MSG_RING_*` flags for use with [`io_uring_sqe`]. - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringMsgringFlags: u32 { /// `IORING_MSG_RING_CQE_SKIP` const CQE_SKIP = sys::IORING_MSG_RING_CQE_SKIP; @@ -551,7 +569,8 @@ bitflags::bitflags! { bitflags::bitflags! { /// `IORING_ASYNC_CANCEL_*` flags for use with [`io_uring_sqe`]. - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringAsyncCancelFlags: u32 { /// `IORING_ASYNC_CANCEL_ALL` const ALL = sys::IORING_ASYNC_CANCEL_ALL; @@ -569,7 +588,8 @@ bitflags::bitflags! { bitflags::bitflags! { /// `IORING_FEAT_*` flags for use with [`io_uring_params`]. - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringFeatureFlags: u32 { /// `IORING_FEAT_CQE_SKIP` const CQE_SKIP = sys::IORING_FEAT_CQE_SKIP; @@ -614,7 +634,8 @@ bitflags::bitflags! { bitflags::bitflags! { /// `IO_URING_OP_*` flags for use with [`io_uring_probe_op`]. - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringOpFlags: u16 { /// `IO_URING_OP_SUPPORTED` const SUPPORTED = sys::IO_URING_OP_SUPPORTED as _; @@ -623,7 +644,8 @@ bitflags::bitflags! { bitflags::bitflags! { /// `IORING_RSRC_*` flags for use with [`io_uring_rsrc_register`]. - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringRsrcFlags: u32 { /// `IORING_RSRC_REGISTER_SPARSE` const REGISTER_SPARSE = sys::IORING_RSRC_REGISTER_SPARSE as _; @@ -632,7 +654,8 @@ bitflags::bitflags! { bitflags::bitflags! { /// `IORING_SQ_*` flags. - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringSqFlags: u32 { /// `IORING_SQ_NEED_WAKEUP` const NEED_WAKEUP = sys::IORING_SQ_NEED_WAKEUP; @@ -647,7 +670,8 @@ bitflags::bitflags! { bitflags::bitflags! { /// `IORING_CQ_*` flags. - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringCqFlags: u32 { /// `IORING_CQ_EVENTFD_DISABLED` const EVENTFD_DISABLED = sys::IORING_CQ_EVENTFD_DISABLED; @@ -656,7 +680,8 @@ bitflags::bitflags! { bitflags::bitflags! { /// `IORING_POLL_*` flags. - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringPollFlags: u32 { /// `IORING_POLL_ADD_MULTI` const ADD_MULTI = sys::IORING_POLL_ADD_MULTI; @@ -674,7 +699,8 @@ bitflags::bitflags! { bitflags::bitflags! { /// send/sendmsg flags (`sqe.ioprio`) - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringSendFlags: u16 { /// `IORING_RECVSEND_POLL_FIRST`. /// @@ -693,7 +719,8 @@ bitflags::bitflags! { bitflags::bitflags! { /// recv/recvmsg flags (`sqe.ioprio`) - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringRecvFlags: u16 { /// `IORING_RECVSEND_POLL_FIRST` /// @@ -712,7 +739,8 @@ bitflags::bitflags! { bitflags::bitflags! { /// accept flags (`sqe.ioprio`) - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct IoringAcceptFlags: u16 { /// `IORING_ACCEPT_MULTISHOT` const MULTISHOT = sys::IORING_ACCEPT_MULTISHOT as _; @@ -721,22 +749,23 @@ bitflags::bitflags! { bitflags::bitflags! { /// recvmsg out flags - #[derive(Default)] + #[repr(transparent)] + #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct RecvmsgOutFlags: u32 { /// `MSG_EOR` - const EOR = sys::MSG_EOR; + const EOR = net::MSG_EOR; /// `MSG_TRUNC` - const TRUNC = sys::MSG_TRUNC; + const TRUNC = net::MSG_TRUNC; /// `MSG_CTRUNC` - const CTRUNC = sys::MSG_CTRUNC; + const CTRUNC = net::MSG_CTRUNC; /// `MSG_OOB` - const OOB = sys::MSG_OOB; + const OOB = net::MSG_OOB; /// `MSG_ERRQUEUE` - const ERRQUEUE = sys::MSG_ERRQUEUE; + const ERRQUEUE = net::MSG_ERRQUEUE; } } @@ -863,10 +892,10 @@ impl io_uring_user_data { impl Default for io_uring_user_data { #[inline] fn default() -> Self { - let mut s = ::core::mem::MaybeUninit::::uninit(); + let mut s = MaybeUninit::::uninit(); // SAFETY: All of Linux's io_uring structs may be zero-initialized. unsafe { - ::core::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + write_bytes(s.as_mut_ptr(), 0, 1); s.assume_init() } } @@ -1007,13 +1036,17 @@ pub union splice_fd_in_or_file_index_union { } /// An io_uring Completion Queue Entry. +/// +/// This does not derive `Copy` or `Clone` because the `big_cqe` field is not +/// automatically copyable. #[allow(missing_docs)] #[repr(C)] -#[derive(Debug, Copy, Clone, Default)] +#[derive(Debug, Default)] pub struct io_uring_cqe { pub user_data: io_uring_user_data, pub res: i32, pub flags: IoringCqeFlags, + pub big_cqe: sys::__IncompleteArrayField, } #[allow(missing_docs)] @@ -1213,7 +1246,7 @@ impl Default for ioprio_union { #[inline] fn default() -> Self { // SAFETY: All of Linux's io_uring structs may be zero-initialized. - unsafe { ::core::mem::zeroed::() } + unsafe { zeroed::() } } } @@ -1221,7 +1254,7 @@ impl Default for len_union { #[inline] fn default() -> Self { // SAFETY: All of Linux's io_uring structs may be zero-initialized. - unsafe { ::core::mem::zeroed::() } + unsafe { zeroed::() } } } @@ -1229,7 +1262,7 @@ impl Default for off_or_addr2_union { #[inline] fn default() -> Self { // SAFETY: All of Linux's io_uring structs may be zero-initialized. - unsafe { ::core::mem::zeroed::() } + unsafe { zeroed::() } } } @@ -1237,7 +1270,7 @@ impl Default for addr_or_splice_off_in_union { #[inline] fn default() -> Self { // SAFETY: All of Linux's io_uring structs may be zero-initialized. - unsafe { ::core::mem::zeroed::() } + unsafe { zeroed::() } } } @@ -1245,7 +1278,7 @@ impl Default for addr3_or_cmd_union { #[inline] fn default() -> Self { // SAFETY: All of Linux's io_uring structs may be zero-initialized. - unsafe { ::core::mem::zeroed::() } + unsafe { zeroed::() } } } @@ -1253,7 +1286,7 @@ impl Default for op_flags_union { #[inline] fn default() -> Self { // SAFETY: All of Linux's io_uring structs may be zero-initialized. - unsafe { ::core::mem::zeroed::() } + unsafe { zeroed::() } } } @@ -1261,7 +1294,7 @@ impl Default for buf_union { #[inline] fn default() -> Self { // SAFETY: All of Linux's io_uring structs may be zero-initialized. - unsafe { ::core::mem::zeroed::() } + unsafe { zeroed::() } } } @@ -1269,7 +1302,7 @@ impl Default for splice_fd_in_or_file_index_union { #[inline] fn default() -> Self { // SAFETY: All of Linux's io_uring structs may be zero-initialized. - unsafe { ::core::mem::zeroed::() } + unsafe { zeroed::() } } } @@ -1277,7 +1310,7 @@ impl Default for register_or_sqe_op_or_sqe_flags_union { #[inline] fn default() -> Self { // SAFETY: All of Linux's io_uring structs may be zero-initialized. - unsafe { ::core::mem::zeroed::() } + unsafe { zeroed::() } } } @@ -1285,67 +1318,7 @@ impl Default for register_or_sqe_op_or_sqe_flags_union { /// kernel's versions. #[test] fn io_uring_layouts() { - use core::mem::{align_of, size_of}; - use memoffset::{offset_of, span_of}; - - // Check that the size and alignment of a type match the `sys` bindings. - macro_rules! check_type { - ($struct:ident) => { - assert_eq!( - (size_of::<$struct>(), align_of::<$struct>()), - (size_of::(), align_of::()) - ); - }; - } - - // The same as `check_type`, but for unions and anonymous structs we've - // renamed to avoid having types like "bindgen_ty_1" in the API. - macro_rules! check_renamed_type { - ($to:ident, $from:ident) => { - assert_eq!( - (size_of::<$to>(), align_of::<$to>()), - (size_of::(), align_of::()) - ); - }; - } - - // Check that the field of a struct has the same offset as the - // corresponding field in the `sys` bindings. - macro_rules! check_struct_field { - ($struct:ident, $field:ident) => { - assert_eq!( - offset_of!($struct, $field), - offset_of!(sys::$struct, $field) - ); - assert_eq!(span_of!($struct, $field), span_of!(sys::$struct, $field)); - }; - } - - // The same as `check_struct_field`, but for unions and anonymous structs - // we've renamed to avoid having types like "bindgen_ty_1" in the API. - macro_rules! check_struct_renamed_field { - ($struct:ident, $to:ident, $from:ident) => { - assert_eq!(offset_of!($struct, $to), offset_of!(sys::$struct, $from)); - assert_eq!(span_of!($struct, $to), span_of!(sys::$struct, $from)); - }; - } - - // For the common case of no renaming, check all fields of a struct. - macro_rules! check_struct { - ($name:ident, $($field:ident),*) => { - // Check the size and alignment. - check_type!($name); - - // Check that we have all the fields. - let _test = $name { - // SAFETY: All of io_uring's types can be zero-initialized. - $($field: unsafe { core::mem::zeroed() }),* - }; - - // Check that the fields have the right sizes and offsets. - $(check_struct_field!($name, $field));* - }; - } + use sys as c; check_renamed_type!(off_or_addr2_union, io_uring_sqe__bindgen_ty_1); check_renamed_type!(addr_or_splice_off_in_union, io_uring_sqe__bindgen_ty_2); @@ -1386,7 +1359,7 @@ fn io_uring_layouts() { check_struct_field!(io_uring_restriction, resv); check_struct_field!(io_uring_restriction, resv2); - check_struct!(io_uring_cqe, user_data, res, flags); + check_struct!(io_uring_cqe, user_data, res, flags, big_cqe); check_struct!( io_uring_params, sq_entries, diff --git a/vendor/rustix/src/lib.rs b/vendor/rustix/src/lib.rs index f0e093585..3fcf92544 100644 --- a/vendor/rustix/src/lib.rs +++ b/vendor/rustix/src/lib.rs @@ -19,7 +19,6 @@ //! ``` //! # #[cfg(feature = "net")] //! # fn read(sock: std::net::TcpStream, buf: &mut [u8]) -> std::io::Result<()> { -//! # use std::convert::TryInto; //! # #[cfg(unix)] //! # use std::os::unix::io::AsRawFd; //! # #[cfg(target_os = "wasi")] @@ -59,6 +58,8 @@ //! - Constants use `enum`s and [`bitflags`] types. //! - Multiplexed functions (eg. `fcntl`, `ioctl`, etc.) are de-multiplexed. //! - Variadic functions (eg. `openat`, etc.) are presented as non-variadic. +//! - Functions that return strings automatically allocate sufficient memory +//! and retry the syscall as needed to determine the needed length. //! - Functions and types which need `l` prefixes or `64` suffixes to enable //! large-file support (LFS) are used automatically. File sizes and offsets //! are always presented as `u64` and `i64`. @@ -71,7 +72,8 @@ //! running under seccomp. //! //! Things they don't do include: -//! - Detecting whether functions are supported at runtime. +//! - Detecting whether functions are supported at runtime, except in specific +//! cases where new interfaces need to be detected to support y2038 and LFS. //! - Hiding significant differences between platforms. //! - Restricting ambient authorities. //! - Imposing sandboxing features such as filesystem path or network address @@ -102,28 +104,24 @@ all(linux_raw, naked_functions, target_arch = "x86"), feature(naked_functions) )] -#![cfg_attr(io_lifetimes_use_std, feature(io_safety))] #![cfg_attr(core_ffi_c, feature(core_ffi_c))] #![cfg_attr(core_c_str, feature(core_c_str))] #![cfg_attr(alloc_c_string, feature(alloc_ffi))] #![cfg_attr(alloc_c_string, feature(alloc_c_string))] #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(feature = "rustc-dep-of-std", feature(core_intrinsics))] #![cfg_attr(feature = "rustc-dep-of-std", feature(ip))] #![cfg_attr( - all(not(feature = "rustc-dep-of-std"), core_intrinsics), + any(feature = "rustc-dep-of-std", core_intrinsics), feature(core_intrinsics) )] #![cfg_attr(asm_experimental_arch, feature(asm_experimental_arch))] #![cfg_attr(not(feature = "all-apis"), allow(dead_code))] -// Clamp depends on Rust 1.50 which is newer than our MSRV. -#![allow(clippy::manual_clamp)] // It is common in linux and libc APIs for types to vary between platforms. #![allow(clippy::unnecessary_cast)] // It is common in linux and libc APIs for types to vary between platforms. #![allow(clippy::useless_conversion)] -// Redox and WASI have enough differences that it isn't worth -// precisely conditionallizing all the `use`s for them. +// Redox and WASI have enough differences that it isn't worth precisely +// conditionalizing all the `use`s for them. #![cfg_attr(any(target_os = "redox", target_os = "wasi"), allow(unused_imports))] #[cfg(not(feature = "rustc-dep-of-std"))] @@ -133,9 +131,16 @@ extern crate alloc; #[cfg(not(windows))] #[macro_use] pub(crate) mod cstr; -#[macro_use] -pub(crate) mod const_assert; pub(crate) mod utils; +// Polyfill for `std` in `no_std` builds. +#[cfg_attr(feature = "std", path = "maybe_polyfill/std/mod.rs")] +#[cfg_attr(not(feature = "std"), path = "maybe_polyfill/no_std/mod.rs")] +pub(crate) mod maybe_polyfill; +#[cfg(test)] +#[macro_use] +pub(crate) mod check_types; +#[macro_use] +pub(crate) mod bitcast; // linux_raw: Weak symbols are used by the use-libc-auxv feature for // glibc 2.15 support. @@ -161,20 +166,41 @@ mod backend; /// versions of these types and traits. pub mod fd { use super::backend; + + // Re-export `AsSocket` etc. too, as users can't implement `AsFd` etc. on + // Windows due to them having blanket impls on Windows, so users must + // implement `AsSocket` etc. #[cfg(windows)] - pub use backend::fd::AsSocket; + pub use backend::fd::{AsRawSocket, AsSocket, FromRawSocket, IntoRawSocket}; + pub use backend::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; } // The public API modules. +#[cfg(feature = "event")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "event")))] +pub mod event; #[cfg(not(windows))] pub mod ffi; #[cfg(not(windows))] -#[cfg(feature = "fs")] +#[cfg(any( + feature = "fs", + all( + linux_raw, + not(feature = "use-libc-auxv"), + not(target_vendor = "mustang"), + any( + feature = "param", + feature = "runtime", + feature = "time", + target_arch = "x86", + ) + ) +))] #[cfg_attr(doc_cfg, doc(cfg(feature = "fs")))] pub mod fs; pub mod io; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[cfg(feature = "io_uring")] #[cfg_attr(doc_cfg, doc(cfg(feature = "io_uring")))] pub mod io_uring; @@ -191,18 +217,53 @@ pub mod net; #[cfg_attr(doc_cfg, doc(cfg(feature = "param")))] pub mod param; #[cfg(not(windows))] -#[cfg(any(feature = "fs", feature = "net"))] +#[cfg(any( + feature = "fs", + feature = "net", + all( + linux_raw, + not(feature = "use-libc-auxv"), + not(target_vendor = "mustang"), + any( + feature = "param", + feature = "runtime", + feature = "time", + target_arch = "x86", + ) + ) +))] #[cfg_attr(doc_cfg, doc(cfg(any(feature = "fs", feature = "net"))))] pub mod path; +#[cfg(feature = "pipe")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "pipe")))] +#[cfg(not(any(windows, target_os = "wasi")))] +pub mod pipe; #[cfg(not(windows))] #[cfg(feature = "process")] #[cfg_attr(doc_cfg, doc(cfg(feature = "process")))] pub mod process; +#[cfg(feature = "procfs")] +#[cfg(linux_kernel)] +#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))] +pub mod procfs; +#[cfg(not(windows))] +#[cfg(not(target_os = "wasi"))] +#[cfg(feature = "pty")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "pty")))] +pub mod pty; #[cfg(not(windows))] #[cfg(feature = "rand")] #[cfg_attr(doc_cfg, doc(cfg(feature = "rand")))] pub mod rand; #[cfg(not(windows))] +#[cfg(feature = "stdio")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "stdio")))] +pub mod stdio; +#[cfg(feature = "system")] +#[cfg(not(any(windows, target_os = "wasi")))] +#[cfg_attr(doc_cfg, doc(cfg(feature = "system")))] +pub mod system; +#[cfg(not(windows))] #[cfg(feature = "termios")] #[cfg_attr(doc_cfg, doc(cfg(feature = "termios")))] pub mod termios; @@ -218,23 +279,65 @@ pub mod time; // "runtime" is also a public API module, but it's only for libc-like users. #[cfg(not(windows))] #[cfg(feature = "runtime")] +#[cfg(linux_raw)] #[doc(hidden)] #[cfg_attr(doc_cfg, doc(cfg(feature = "runtime")))] pub mod runtime; -// We have some internal interdependencies in the API features, so for now, -// for API features that aren't enabled, declare them as `pub(crate)` so -// that they're not public, but still available for internal use. - +// Private modules used by multiple public modules. #[cfg(not(windows))] -#[cfg(all( - not(feature = "param"), - any(feature = "runtime", feature = "time", target_arch = "x86"), +#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))] +mod clockid; +#[cfg(not(any(windows, target_os = "wasi")))] +#[cfg(any( + feature = "procfs", + feature = "process", + feature = "runtime", + feature = "termios", + feature = "thread", + all(bsd, feature = "event") ))] -pub(crate) mod param; -#[cfg(not(windows))] -#[cfg(not(any(feature = "fs", feature = "net")))] -pub(crate) mod path; +mod pid; +#[cfg(any(feature = "process", feature = "thread"))] +#[cfg(linux_kernel)] +mod prctl; +#[cfg(not(any(windows, target_os = "wasi")))] +#[cfg(any(feature = "process", feature = "runtime", all(bsd, feature = "event")))] +mod signal; #[cfg(not(windows))] -#[cfg(not(feature = "process"))] -pub(crate) mod process; +#[cfg(any( + feature = "fs", + feature = "runtime", + feature = "thread", + feature = "time", + all( + linux_raw, + not(feature = "use-libc-auxv"), + not(target_vendor = "mustang"), + any( + feature = "param", + feature = "runtime", + feature = "time", + target_arch = "x86", + ) + ) +))] +mod timespec; +#[cfg(not(any(windows, target_os = "wasi")))] +#[cfg(any( + feature = "fs", + feature = "process", + feature = "thread", + all( + linux_raw, + not(feature = "use-libc-auxv"), + not(target_vendor = "mustang"), + any( + feature = "param", + feature = "runtime", + feature = "time", + target_arch = "x86", + ) + ) +))] +mod ugid; diff --git a/vendor/rustix/src/maybe_polyfill/no_std/io/mod.rs b/vendor/rustix/src/maybe_polyfill/no_std/io/mod.rs new file mode 100644 index 000000000..f0ad7504f --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/io/mod.rs @@ -0,0 +1,107 @@ +//! The following is derived from Rust's +//! library/std/src/sys/unix/io.rs +//! dca3f1b786efd27be3b325ed1e01e247aa589c3b. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. + +#![allow(unsafe_code)] +use crate::backend::c; +#[cfg(not(linux_raw))] +use c::size_t as __kernel_size_t; +use core::marker::PhantomData; +use core::slice; +#[cfg(linux_raw)] +use linux_raw_sys::general::__kernel_size_t; + +/// +#[derive(Copy, Clone)] +#[repr(transparent)] +pub struct IoSlice<'a> { + vec: c::iovec, + _p: PhantomData<&'a [u8]>, +} + +impl<'a> IoSlice<'a> { + /// + #[inline] + pub fn new(buf: &'a [u8]) -> IoSlice<'a> { + IoSlice { + vec: c::iovec { + iov_base: buf.as_ptr() as *mut u8 as *mut c::c_void, + iov_len: buf.len() as _, + }, + _p: PhantomData, + } + } + + /// + #[inline] + pub fn advance(&mut self, n: usize) { + if self.vec.iov_len < n as _ { + panic!("advancing IoSlice beyond its length"); + } + + unsafe { + // `__kernel_size_t` will always have the same size as `usize`, but it is a `u32` on + // 32-bit platforms and `u64` on 64-bit platforms when using `linux_raw` backend + self.vec.iov_len -= n as __kernel_size_t; + self.vec.iov_base = self.vec.iov_base.add(n); + } + } + + /// + #[inline] + pub fn as_slice(&self) -> &[u8] { + unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len as usize) } + } +} + +/// +#[repr(transparent)] +pub struct IoSliceMut<'a> { + vec: c::iovec, + _p: PhantomData<&'a mut [u8]>, +} + +impl<'a> IoSliceMut<'a> { + /// + #[inline] + pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { + IoSliceMut { + vec: c::iovec { + iov_base: buf.as_mut_ptr() as *mut c::c_void, + iov_len: buf.len() as _, + }, + _p: PhantomData, + } + } + + /// + #[inline] + pub fn advance(&mut self, n: usize) { + if self.vec.iov_len < n as _ { + panic!("advancing IoSliceMut beyond its length"); + } + + unsafe { + // `__kernel_size_t` will always have the same size as `usize`, but it is a `u32` on + // 32-bit platforms and `u64` on 64-bit platforms when using `linux_raw` backend + self.vec.iov_len -= n as __kernel_size_t; + self.vec.iov_base = self.vec.iov_base.add(n); + } + } + + /// + #[inline] + pub fn as_slice(&self) -> &[u8] { + unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len as usize) } + } + + /// + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len as usize) + } + } +} diff --git a/vendor/rustix/src/maybe_polyfill/no_std/mod.rs b/vendor/rustix/src/maybe_polyfill/no_std/mod.rs new file mode 100644 index 000000000..ab088d862 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/mod.rs @@ -0,0 +1,15 @@ +//! Polyfill of parts of the standard library for `no_std` builds. +//! +//! All code in this subtree is derived from the standard library and licensed MIT or Apache 2.0 +//! at your option. +//! +//! This implementation is used when `std` is not available and polyfills the necessary items from +//! `std`. When the `std` feature is specified (so the standard library is available), the file +//! `src/polyfill/std` is used instead, which just imports the respective items from `std`. + +#[cfg(not(windows))] +pub mod io; +#[cfg(not(any(target_os = "redox", target_os = "wasi")))] +#[cfg(feature = "net")] +pub mod net; +pub mod os; diff --git a/vendor/rustix/src/maybe_polyfill/no_std/net/ip_addr.rs b/vendor/rustix/src/maybe_polyfill/no_std/net/ip_addr.rs new file mode 100644 index 000000000..ffa5302e3 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/net/ip_addr.rs @@ -0,0 +1,2068 @@ +//! The following is derived from Rust's +//! library/std/src/net/ip_addr.rs at revision +//! bd20fc1fd657b32f7aa1d70d8723f04c87f21606. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. +//! +//! This defines `IpAddr`, `Ipv4Addr`, and `Ipv6Addr`. Ideally, these should be +//! defined in `core`. See [RFC 2832]. +//! +//! [RFC 2832]: https://github.com/rust-lang/rfcs/pull/2832 + +#![allow(unsafe_code)] + +use core::cmp::Ordering; +use core::mem::transmute; + +/// An IP address, either IPv4 or IPv6. +/// +/// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their +/// respective documentation for more details. +/// +/// # Examples +/// +/// ``` +/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +/// +/// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); +/// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); +/// +/// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4)); +/// assert_eq!("::1".parse(), Ok(localhost_v6)); +/// +/// assert_eq!(localhost_v4.is_ipv6(), false); +/// assert_eq!(localhost_v4.is_ipv4(), true); +/// ``` +#[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] +#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] +pub enum IpAddr { + /// An IPv4 address. + #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] + V4(#[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] Ipv4Addr), + /// An IPv6 address. + #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] + V6(#[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] Ipv6Addr), +} + +/// An IPv4 address. +/// +/// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791]. +/// They are usually represented as four octets. +/// +/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses. +/// +/// [IETF RFC 791]: https://tools.ietf.org/html/rfc791 +/// +/// # Textual representation +/// +/// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal +/// notation, divided by `.` (this is called "dot-decimal notation"). +/// Notably, octal numbers (which are indicated with a leading `0`) and hexadecimal numbers (which +/// are indicated with a leading `0x`) are not allowed per [IETF RFC 6943]. +/// +/// [IETF RFC 6943]: https://tools.ietf.org/html/rfc6943#section-3.1.1 +/// [`FromStr`]: core::str::FromStr +/// +/// # Examples +/// +/// ``` +/// use std::net::Ipv4Addr; +/// +/// let localhost = Ipv4Addr::new(127, 0, 0, 1); +/// assert_eq!("127.0.0.1".parse(), Ok(localhost)); +/// assert_eq!(localhost.is_loopback(), true); +/// assert!("012.004.002.000".parse::().is_err()); // all octets are in octal +/// assert!("0000000.0.0.0".parse::().is_err()); // first octet is a zero in octal +/// assert!("0xcb.0x0.0x71.0x00".parse::().is_err()); // all octets are in hex +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub struct Ipv4Addr { + octets: [u8; 4], +} + +/// An IPv6 address. +/// +/// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291]. +/// They are usually represented as eight 16-bit segments. +/// +/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 +/// +/// # Embedding IPv4 Addresses +/// +/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses. +/// +/// To assist in the transition from IPv4 to IPv6 two types of IPv6 addresses that embed an IPv4 address were defined: +/// IPv4-compatible and IPv4-mapped addresses. Of these IPv4-compatible addresses have been officially deprecated. +/// +/// Both types of addresses are not assigned any special meaning by this implementation, +/// other than what the relevant standards prescribe. This means that an address like `::ffff:127.0.0.1`, +/// while representing an IPv4 loopback address, is not itself an IPv6 loopback address; only `::1` is. +/// To handle these so called "IPv4-in-IPv6" addresses, they have to first be converted to their canonical IPv4 address. +/// +/// ### IPv4-Compatible IPv6 Addresses +/// +/// IPv4-compatible IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.1], and have been officially deprecated. +/// The RFC describes the format of an "IPv4-Compatible IPv6 address" as follows: +/// +/// ```text +/// | 80 bits | 16 | 32 bits | +/// +--------------------------------------+--------------------------+ +/// |0000..............................0000|0000| IPv4 address | +/// +--------------------------------------+----+---------------------+ +/// ``` +/// So `::a.b.c.d` would be an IPv4-compatible IPv6 address representing the IPv4 address `a.b.c.d`. +/// +/// To convert from an IPv4 address to an IPv4-compatible IPv6 address, use [`Ipv4Addr::to_ipv6_compatible`]. +/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-compatible IPv6 address to the canonical IPv4 address. +/// +/// [IETF RFC 4291 Section 2.5.5.1]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.1 +/// +/// ### IPv4-Mapped IPv6 Addresses +/// +/// IPv4-mapped IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.2]. +/// The RFC describes the format of an "IPv4-Mapped IPv6 address" as follows: +/// +/// ```text +/// | 80 bits | 16 | 32 bits | +/// +--------------------------------------+--------------------------+ +/// |0000..............................0000|FFFF| IPv4 address | +/// +--------------------------------------+----+---------------------+ +/// ``` +/// So `::ffff:a.b.c.d` would be an IPv4-mapped IPv6 address representing the IPv4 address `a.b.c.d`. +/// +/// To convert from an IPv4 address to an IPv4-mapped IPv6 address, use [`Ipv4Addr::to_ipv6_mapped`]. +/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-mapped IPv6 address to the canonical IPv4 address. +/// Note that this will also convert the IPv6 loopback address `::1` to `0.0.0.1`. Use +/// [`Ipv6Addr::to_ipv4_mapped`] to avoid this. +/// +/// [IETF RFC 4291 Section 2.5.5.2]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2 +/// +/// # Textual representation +/// +/// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent +/// an IPv6 address in text, but in general, each segments is written in hexadecimal +/// notation, and segments are separated by `:`. For more information, see +/// [IETF RFC 5952]. +/// +/// [`FromStr`]: core::str::FromStr +/// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952 +/// +/// # Examples +/// +/// ``` +/// use std::net::Ipv6Addr; +/// +/// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); +/// assert_eq!("::1".parse(), Ok(localhost)); +/// assert_eq!(localhost.is_loopback(), true); +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub struct Ipv6Addr { + octets: [u8; 16], +} + +/// Scope of an [IPv6 multicast address] as defined in [IETF RFC 7346 section 2]. +/// +/// # Stability Guarantees +/// +/// Not all possible values for a multicast scope have been assigned. +/// Future RFCs may introduce new scopes, which will be added as variants to this enum; +/// because of this the enum is marked as `#[non_exhaustive]`. +/// +/// # Examples +/// ``` +/// #![feature(ip)] +/// +/// use std::net::Ipv6Addr; +/// use std::net::Ipv6MulticastScope::*; +/// +/// // An IPv6 multicast address with global scope (`ff0e::`). +/// let address = Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0); +/// +/// // Will print "Global scope". +/// match address.multicast_scope() { +/// Some(InterfaceLocal) => println!("Interface-Local scope"), +/// Some(LinkLocal) => println!("Link-Local scope"), +/// Some(RealmLocal) => println!("Realm-Local scope"), +/// Some(AdminLocal) => println!("Admin-Local scope"), +/// Some(SiteLocal) => println!("Site-Local scope"), +/// Some(OrganizationLocal) => println!("Organization-Local scope"), +/// Some(Global) => println!("Global scope"), +/// Some(_) => println!("Unknown scope"), +/// None => println!("Not a multicast address!") +/// } +/// +/// ``` +/// +/// [IPv6 multicast address]: Ipv6Addr +/// [IETF RFC 7346 section 2]: https://tools.ietf.org/html/rfc7346#section-2 +#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)] +#[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] +#[non_exhaustive] +pub enum Ipv6MulticastScope { + /// Interface-Local scope. + InterfaceLocal, + /// Link-Local scope. + LinkLocal, + /// Realm-Local scope. + RealmLocal, + /// Admin-Local scope. + AdminLocal, + /// Site-Local scope. + SiteLocal, + /// Organization-Local scope. + OrganizationLocal, + /// Global scope. + Global, +} + +impl IpAddr { + /// Returns [`true`] for the special 'unspecified' address. + /// + /// See the documentation for [`Ipv4Addr::is_unspecified()`] and + /// [`Ipv6Addr::is_unspecified()`] for more details. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(feature = "ip_shared", since = "1.12.0"))] + #[must_use] + #[inline] + pub const fn is_unspecified(&self) -> bool { + match self { + IpAddr::V4(ip) => ip.is_unspecified(), + IpAddr::V6(ip) => ip.is_unspecified(), + } + } + + /// Returns [`true`] if this is a loopback address. + /// + /// See the documentation for [`Ipv4Addr::is_loopback()`] and + /// [`Ipv6Addr::is_loopback()`] for more details. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(feature = "ip_shared", since = "1.12.0"))] + #[must_use] + #[inline] + pub const fn is_loopback(&self) -> bool { + match self { + IpAddr::V4(ip) => ip.is_loopback(), + IpAddr::V6(ip) => ip.is_loopback(), + } + } + + /// Returns [`true`] if the address appears to be globally routable. + /// + /// See the documentation for [`Ipv4Addr::is_global()`] and + /// [`Ipv6Addr::is_global()`] for more details. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_ip", issue = "76205") + )] + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + #[must_use] + #[inline] + pub const fn is_global(&self) -> bool { + match self { + IpAddr::V4(ip) => ip.is_global(), + IpAddr::V6(ip) => ip.is_global(), + } + } + + /// Returns [`true`] if this is a multicast address. + /// + /// See the documentation for [`Ipv4Addr::is_multicast()`] and + /// [`Ipv6Addr::is_multicast()`] for more details. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(feature = "ip_shared", since = "1.12.0"))] + #[must_use] + #[inline] + pub const fn is_multicast(&self) -> bool { + match self { + IpAddr::V4(ip) => ip.is_multicast(), + IpAddr::V6(ip) => ip.is_multicast(), + } + } + + /// Returns [`true`] if this address is in a range designated for documentation. + /// + /// See the documentation for [`Ipv4Addr::is_documentation()`] and + /// [`Ipv6Addr::is_documentation()`] for more details. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true); + /// assert_eq!( + /// IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_documentation(), + /// true + /// ); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_ip", issue = "76205") + )] + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + #[must_use] + #[inline] + pub const fn is_documentation(&self) -> bool { + match self { + IpAddr::V4(ip) => ip.is_documentation(), + IpAddr::V6(ip) => ip.is_documentation(), + } + } + + /// Returns [`true`] if this address is in a range designated for benchmarking. + /// + /// See the documentation for [`Ipv4Addr::is_benchmarking()`] and + /// [`Ipv6Addr::is_benchmarking()`] for more details. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(198, 19, 255, 255)).is_benchmarking(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0)).is_benchmarking(), true); + /// ``` + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + #[must_use] + #[inline] + pub const fn is_benchmarking(&self) -> bool { + match self { + IpAddr::V4(ip) => ip.is_benchmarking(), + IpAddr::V6(ip) => ip.is_benchmarking(), + } + } + + /// Returns [`true`] if this address is an [`IPv4` address], and [`false`] + /// otherwise. + /// + /// [`IPv4` address]: IpAddr::V4 + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(feature = "ipaddr_checker", since = "1.16.0"))] + #[must_use] + #[inline] + pub const fn is_ipv4(&self) -> bool { + matches!(self, IpAddr::V4(_)) + } + + /// Returns [`true`] if this address is an [`IPv6` address], and [`false`] + /// otherwise. + /// + /// [`IPv6` address]: IpAddr::V6 + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(feature = "ipaddr_checker", since = "1.16.0"))] + #[must_use] + #[inline] + pub const fn is_ipv6(&self) -> bool { + matches!(self, IpAddr::V6(_)) + } + + /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped IPv6 addresses, otherwise it + /// return `self` as-is. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).to_canonical().is_loopback(), true); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).is_loopback(), false); + /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).to_canonical().is_loopback(), true); + /// ``` + #[inline] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_ip", issue = "76205") + )] + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + pub const fn to_canonical(&self) -> IpAddr { + match self { + &v4 @ IpAddr::V4(_) => v4, + IpAddr::V6(v6) => v6.to_canonical(), + } + } +} + +impl Ipv4Addr { + /// Creates a new IPv4 address from four eight-bit octets. + /// + /// The result will represent the IP address `a`.`b`.`c`.`d`. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::new(127, 0, 0, 1); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_32", since = "1.32.0") + )] + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + #[must_use] + #[inline] + pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { + Ipv4Addr { + octets: [a, b, c, d], + } + } + + /// An IPv4 address with the address pointing to localhost: `127.0.0.1` + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::LOCALHOST; + /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1)); + /// ``` + #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))] + pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1); + + /// An IPv4 address representing an unspecified address: `0.0.0.0` + /// + /// This corresponds to the constant `INADDR_ANY` in other languages. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::UNSPECIFIED; + /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0)); + /// ``` + #[doc(alias = "INADDR_ANY")] + #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))] + pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0); + + /// An IPv4 address representing the broadcast address: `255.255.255.255` + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::BROADCAST; + /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255)); + /// ``` + #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))] + pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255); + + /// Returns the four eight-bit integers that make up this address. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::new(127, 0, 0, 1); + /// assert_eq!(addr.octets(), [127, 0, 0, 1]); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + #[must_use] + #[inline] + pub const fn octets(&self) -> [u8; 4] { + self.octets + } + + /// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`). + /// + /// This property is defined in _UNIX Network Programming, Second Edition_, + /// W. Richard Stevens, p. 891; see also [ip7]. + /// + /// [ip7]: https://man7.org/linux/man-pages/man7/ip.7.html + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true); + /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_32", since = "1.32.0") + )] + #[cfg_attr(staged_api, stable(feature = "ip_shared", since = "1.12.0"))] + #[must_use] + #[inline] + pub const fn is_unspecified(&self) -> bool { + u32::from_be_bytes(self.octets) == 0 + } + + /// Returns [`true`] if this is a loopback address (`127.0.0.0/8`). + /// + /// This property is defined by [IETF RFC 1122]. + /// + /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true); + /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] + #[must_use] + #[inline] + pub const fn is_loopback(&self) -> bool { + self.octets()[0] == 127 + } + + /// Returns [`true`] if this is a private address. + /// + /// The private address ranges are defined in [IETF RFC 1918] and include: + /// + /// - `10.0.0.0/8` + /// - `172.16.0.0/12` + /// - `192.168.0.0/16` + /// + /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(10, 0, 0, 1).is_private(), true); + /// assert_eq!(Ipv4Addr::new(10, 10, 10, 10).is_private(), true); + /// assert_eq!(Ipv4Addr::new(172, 16, 10, 10).is_private(), true); + /// assert_eq!(Ipv4Addr::new(172, 29, 45, 14).is_private(), true); + /// assert_eq!(Ipv4Addr::new(172, 32, 0, 2).is_private(), false); + /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true); + /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] + #[must_use] + #[inline] + pub const fn is_private(&self) -> bool { + match self.octets() { + [10, ..] => true, + [172, b, ..] if b >= 16 && b <= 31 => true, + [192, 168, ..] => true, + _ => false, + } + } + + /// Returns [`true`] if the address is link-local (`169.254.0.0/16`). + /// + /// This property is defined by [IETF RFC 3927]. + /// + /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(169, 254, 0, 0).is_link_local(), true); + /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true); + /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] + #[must_use] + #[inline] + pub const fn is_link_local(&self) -> bool { + matches!(self.octets(), [169, 254, ..]) + } + + /// Returns [`true`] if the address appears to be globally reachable + /// as specified by the [IANA IPv4 Special-Purpose Address Registry]. + /// Whether or not an address is practically reachable will depend on your network configuration. + /// + /// Most IPv4 addresses are globally reachable; + /// unless they are specifically defined as *not* globally reachable. + /// + /// Non-exhaustive list of notable addresses that are not globally reachable: + /// + /// - The [unspecified address] ([`is_unspecified`](Ipv4Addr::is_unspecified)) + /// - Addresses reserved for private use ([`is_private`](Ipv4Addr::is_private)) + /// - Addresses in the shared address space ([`is_shared`](Ipv4Addr::is_shared)) + /// - Loopback addresses ([`is_loopback`](Ipv4Addr::is_loopback)) + /// - Link-local addresses ([`is_link_local`](Ipv4Addr::is_link_local)) + /// - Addresses reserved for documentation ([`is_documentation`](Ipv4Addr::is_documentation)) + /// - Addresses reserved for benchmarking ([`is_benchmarking`](Ipv4Addr::is_benchmarking)) + /// - Reserved addresses ([`is_reserved`](Ipv4Addr::is_reserved)) + /// - The [broadcast address] ([`is_broadcast`](Ipv4Addr::is_broadcast)) + /// + /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv4 Special-Purpose Address Registry]. + /// + /// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml + /// [unspecified address]: Ipv4Addr::UNSPECIFIED + /// [broadcast address]: Ipv4Addr::BROADCAST + + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv4Addr; + /// + /// // Most IPv4 addresses are globally reachable: + /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true); + /// + /// // However some addresses have been assigned a special meaning + /// // that makes them not globally reachable. Some examples are: + /// + /// // The unspecified address (`0.0.0.0`) + /// assert_eq!(Ipv4Addr::UNSPECIFIED.is_global(), false); + /// + /// // Addresses reserved for private use (`10.0.0.0/8`, `172.16.0.0/12`, 192.168.0.0/16) + /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false); + /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false); + /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false); + /// + /// // Addresses in the shared address space (`100.64.0.0/10`) + /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false); + /// + /// // The loopback addresses (`127.0.0.0/8`) + /// assert_eq!(Ipv4Addr::LOCALHOST.is_global(), false); + /// + /// // Link-local addresses (`169.254.0.0/16`) + /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false); + /// + /// // Addresses reserved for documentation (`192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`) + /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false); + /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false); + /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false); + /// + /// // Addresses reserved for benchmarking (`198.18.0.0/15`) + /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false); + /// + /// // Reserved addresses (`240.0.0.0/4`) + /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false); + /// + /// // The broadcast address (`255.255.255.255`) + /// assert_eq!(Ipv4Addr::BROADCAST.is_global(), false); + /// + /// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry. + /// ``` + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_ipv4", issue = "76205") + )] + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + #[must_use] + #[inline] + pub const fn is_global(&self) -> bool { + !(self.octets()[0] == 0 // "This network" + || self.is_private() + || self.is_shared() + || self.is_loopback() + || self.is_link_local() + // addresses reserved for future protocols (`192.0.0.0/24`) + ||(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0) + || self.is_documentation() + || self.is_benchmarking() + || self.is_reserved() + || self.is_broadcast()) + } + + /// Returns [`true`] if this address is part of the Shared Address Space defined in + /// [IETF RFC 6598] (`100.64.0.0/10`). + /// + /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598 + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true); + /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true); + /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_ipv4", issue = "76205") + )] + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + #[must_use] + #[inline] + pub const fn is_shared(&self) -> bool { + self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000) + } + + /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for + /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0` + /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`. + /// + /// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544 + /// [errata 423]: https://www.rfc-editor.org/errata/eid423 + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false); + /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true); + /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true); + /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_ipv4", issue = "76205") + )] + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + #[must_use] + #[inline] + pub const fn is_benchmarking(&self) -> bool { + self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18 + } + + /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112] + /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the + /// broadcast address `255.255.255.255`, but this implementation explicitly excludes it, since + /// it is obviously not reserved for future use. + /// + /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112 + /// + /// # Warning + /// + /// As IANA assigns new addresses, this method will be + /// updated. This may result in non-reserved addresses being + /// treated as reserved in code that relies on an outdated version + /// of this method. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true); + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true); + /// + /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false); + /// // The broadcast address is not considered as reserved for future use by this implementation + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_ipv4", issue = "76205") + )] + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + #[must_use] + #[inline] + pub const fn is_reserved(&self) -> bool { + self.octets()[0] & 240 == 240 && !self.is_broadcast() + } + + /// Returns [`true`] if this is a multicast address (`224.0.0.0/4`). + /// + /// Multicast addresses have a most significant octet between `224` and `239`, + /// and is defined by [IETF RFC 5771]. + /// + /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(224, 254, 0, 0).is_multicast(), true); + /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true); + /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] + #[must_use] + #[inline] + pub const fn is_multicast(&self) -> bool { + self.octets()[0] >= 224 && self.octets()[0] <= 239 + } + + /// Returns [`true`] if this is a broadcast address (`255.255.255.255`). + /// + /// A broadcast address has all octets set to `255` as defined in [IETF RFC 919]. + /// + /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true); + /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] + #[must_use] + #[inline] + pub const fn is_broadcast(&self) -> bool { + u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets()) + } + + /// Returns [`true`] if this address is in a range designated for documentation. + /// + /// This is defined in [IETF RFC 5737]: + /// + /// - `192.0.2.0/24` (TEST-NET-1) + /// - `198.51.100.0/24` (TEST-NET-2) + /// - `203.0.113.0/24` (TEST-NET-3) + /// + /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_documentation(), true); + /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_documentation(), true); + /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true); + /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] + #[must_use] + #[inline] + pub const fn is_documentation(&self) -> bool { + matches!( + self.octets(), + [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _] + ) + } + + /// Converts this address to an [IPv4-compatible] [`IPv6` address]. + /// + /// `a.b.c.d` becomes `::a.b.c.d` + /// + /// Note that IPv4-compatible addresses have been officially deprecated. + /// If you don't explicitly need an IPv4-compatible address for legacy reasons, consider using `to_ipv6_mapped` instead. + /// + /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses + /// [`IPv6` address]: Ipv6Addr + /// + /// # Examples + /// + /// ``` + /// use std::net::{Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!( + /// Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(), + /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x2ff) + /// ); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_ipv6_compatible(&self) -> Ipv6Addr { + let [a, b, c, d] = self.octets(); + Ipv6Addr { + octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d], + } + } + + /// Converts this address to an [IPv4-mapped] [`IPv6` address]. + /// + /// `a.b.c.d` becomes `::ffff:a.b.c.d` + /// + /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses + /// [`IPv6` address]: Ipv6Addr + /// + /// # Examples + /// + /// ``` + /// use std::net::{Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(), + /// Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff)); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_ipv6_mapped(&self) -> Ipv6Addr { + let [a, b, c, d] = self.octets(); + Ipv6Addr { + octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d], + } + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_from_ip", since = "1.16.0"))] +impl From for IpAddr { + /// Copies this address to a new `IpAddr::V4`. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr}; + /// + /// let addr = Ipv4Addr::new(127, 0, 0, 1); + /// + /// assert_eq!( + /// IpAddr::V4(addr), + /// IpAddr::from(addr) + /// ) + /// ``` + #[inline] + fn from(ipv4: Ipv4Addr) -> IpAddr { + IpAddr::V4(ipv4) + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_from_ip", since = "1.16.0"))] +impl From for IpAddr { + /// Copies this address to a new `IpAddr::V6`. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv6Addr}; + /// + /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); + /// + /// assert_eq!( + /// IpAddr::V6(addr), + /// IpAddr::from(addr) + /// ); + /// ``` + #[inline] + fn from(ipv6: Ipv6Addr) -> IpAddr { + IpAddr::V6(ipv6) + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] +impl PartialEq for IpAddr { + #[inline] + fn eq(&self, other: &Ipv4Addr) -> bool { + match self { + IpAddr::V4(v4) => v4 == other, + IpAddr::V6(_) => false, + } + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] +impl PartialEq for Ipv4Addr { + #[inline] + fn eq(&self, other: &IpAddr) -> bool { + match other { + IpAddr::V4(v4) => self == v4, + IpAddr::V6(_) => false, + } + } +} + +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +impl PartialOrd for Ipv4Addr { + #[inline] + fn partial_cmp(&self, other: &Ipv4Addr) -> Option { + Some(self.cmp(other)) + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] +impl PartialOrd for IpAddr { + #[inline] + fn partial_cmp(&self, other: &Ipv4Addr) -> Option { + match self { + IpAddr::V4(v4) => v4.partial_cmp(other), + IpAddr::V6(_) => Some(Ordering::Greater), + } + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] +impl PartialOrd for Ipv4Addr { + #[inline] + fn partial_cmp(&self, other: &IpAddr) -> Option { + match other { + IpAddr::V4(v4) => self.partial_cmp(v4), + IpAddr::V6(_) => Some(Ordering::Less), + } + } +} + +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +impl Ord for Ipv4Addr { + #[inline] + fn cmp(&self, other: &Ipv4Addr) -> Ordering { + self.octets.cmp(&other.octets) + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_u32", since = "1.1.0"))] +impl From for u32 { + /// Converts an `Ipv4Addr` into a host byte order `u32`. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78); + /// assert_eq!(0x12345678, u32::from(addr)); + /// ``` + #[inline] + fn from(ip: Ipv4Addr) -> u32 { + u32::from_be_bytes(ip.octets) + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_u32", since = "1.1.0"))] +impl From for Ipv4Addr { + /// Converts a host byte order `u32` into an `Ipv4Addr`. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::from(0x12345678); + /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr); + /// ``` + #[inline] + fn from(ip: u32) -> Ipv4Addr { + Ipv4Addr { + octets: ip.to_be_bytes(), + } + } +} + +#[cfg_attr(staged_api, stable(feature = "from_slice_v4", since = "1.9.0"))] +impl From<[u8; 4]> for Ipv4Addr { + /// Creates an `Ipv4Addr` from a four element byte array. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]); + /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr); + /// ``` + #[inline] + fn from(octets: [u8; 4]) -> Ipv4Addr { + Ipv4Addr { octets } + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_from_slice", since = "1.17.0"))] +impl From<[u8; 4]> for IpAddr { + /// Creates an `IpAddr::V4` from a four element byte array. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr}; + /// + /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]); + /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr); + /// ``` + #[inline] + fn from(octets: [u8; 4]) -> IpAddr { + IpAddr::V4(Ipv4Addr::from(octets)) + } +} + +impl Ipv6Addr { + /// Creates a new IPv6 address from eight 16-bit segments. + /// + /// The result will represent the IP address `a:b:c:d:e:f:g:h`. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_32", since = "1.32.0") + )] + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + #[allow(clippy::too_many_arguments)] + #[must_use] + #[inline] + pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { + let addr16 = [ + a.to_be(), + b.to_be(), + c.to_be(), + d.to_be(), + e.to_be(), + f.to_be(), + g.to_be(), + h.to_be(), + ]; + Ipv6Addr { + // All elements in `addr16` are big endian. + // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`. + octets: unsafe { transmute::<_, [u8; 16]>(addr16) }, + } + } + + /// An IPv6 address representing localhost: `::1`. + /// + /// This corresponds to constant `IN6ADDR_LOOPBACK_INIT` or `in6addr_loopback` in other + /// languages. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::LOCALHOST; + /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); + /// ``` + #[doc(alias = "IN6ADDR_LOOPBACK_INIT")] + #[doc(alias = "in6addr_loopback")] + #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))] + pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); + + /// An IPv6 address representing the unspecified address: `::` + /// + /// This corresponds to constant `IN6ADDR_ANY_INIT` or `in6addr_any` in other languages. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::UNSPECIFIED; + /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); + /// ``` + #[doc(alias = "IN6ADDR_ANY_INIT")] + #[doc(alias = "in6addr_any")] + #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))] + pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0); + + /// Returns the eight 16-bit segments that make up this address. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(), + /// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + #[must_use] + #[inline] + pub const fn segments(&self) -> [u16; 8] { + // All elements in `self.octets` must be big endian. + // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`. + let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.octets) }; + // We want native endian u16 + [ + u16::from_be(a), + u16::from_be(b), + u16::from_be(c), + u16::from_be(d), + u16::from_be(e), + u16::from_be(f), + u16::from_be(g), + u16::from_be(h), + ] + } + + /// Returns [`true`] for the special 'unspecified' address (`::`). + /// + /// This property is defined in [IETF RFC 4291]. + /// + /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] + #[must_use] + #[inline] + pub const fn is_unspecified(&self) -> bool { + u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets()) + } + + /// Returns [`true`] if this is the [loopback address] (`::1`), + /// as defined in [IETF RFC 4291 section 2.5.3]. + /// + /// Contrary to IPv4, in IPv6 there is only one loopback address. + /// + /// [loopback address]: Ipv6Addr::LOCALHOST + /// [IETF RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] + #[must_use] + #[inline] + pub const fn is_loopback(&self) -> bool { + u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets()) + } + + /// Returns [`true`] if the address appears to be globally reachable + /// as specified by the [IANA IPv6 Special-Purpose Address Registry]. + /// Whether or not an address is practically reachable will depend on your network configuration. + /// + /// Most IPv6 addresses are globally reachable; + /// unless they are specifically defined as *not* globally reachable. + /// + /// Non-exhaustive list of notable addresses that are not globally reachable: + /// - The [unspecified address] ([`is_unspecified`](Ipv6Addr::is_unspecified)) + /// - The [loopback address] ([`is_loopback`](Ipv6Addr::is_loopback)) + /// - IPv4-mapped addresses + /// - Addresses reserved for benchmarking + /// - Addresses reserved for documentation ([`is_documentation`](Ipv6Addr::is_documentation)) + /// - Unique local addresses ([`is_unique_local`](Ipv6Addr::is_unique_local)) + /// - Unicast addresses with link-local scope ([`is_unicast_link_local`](Ipv6Addr::is_unicast_link_local)) + /// + /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv6 Special-Purpose Address Registry]. + /// + /// Note that an address having global scope is not the same as being globally reachable, + /// and there is no direct relation between the two concepts: There exist addresses with global scope + /// that are not globally reachable (for example unique local addresses), + /// and addresses that are globally reachable without having global scope + /// (multicast addresses with non-global scope). + /// + /// [IANA IPv6 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml + /// [unspecified address]: Ipv6Addr::UNSPECIFIED + /// [loopback address]: Ipv6Addr::LOCALHOST + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv6Addr; + /// + /// // Most IPv6 addresses are globally reachable: + /// assert_eq!(Ipv6Addr::new(0x26, 0, 0x1c9, 0, 0, 0xafc8, 0x10, 0x1).is_global(), true); + /// + /// // However some addresses have been assigned a special meaning + /// // that makes them not globally reachable. Some examples are: + /// + /// // The unspecified address (`::`) + /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_global(), false); + /// + /// // The loopback address (`::1`) + /// assert_eq!(Ipv6Addr::LOCALHOST.is_global(), false); + /// + /// // IPv4-mapped addresses (`::ffff:0:0/96`) + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), false); + /// + /// // Addresses reserved for benchmarking (`2001:2::/48`) + /// assert_eq!(Ipv6Addr::new(0x2001, 2, 0, 0, 0, 0, 0, 1,).is_global(), false); + /// + /// // Addresses reserved for documentation (`2001:db8::/32`) + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1).is_global(), false); + /// + /// // Unique local addresses (`fc00::/7`) + /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 1).is_global(), false); + /// + /// // Unicast addresses with link-local scope (`fe80::/10`) + /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 1).is_global(), false); + /// + /// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry. + /// ``` + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_ipv6", issue = "76205") + )] + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + #[must_use] + #[inline] + pub const fn is_global(&self) -> bool { + !(self.is_unspecified() + || self.is_loopback() + // IPv4-mapped Address (`::ffff:0:0/96`) + || matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _]) + // IPv4-IPv6 Translat. (`64:ff9b:1::/48`) + || matches!(self.segments(), [0x64, 0xff9b, 1, _, _, _, _, _]) + // Discard-Only Address Block (`100::/64`) + || matches!(self.segments(), [0x100, 0, 0, 0, _, _, _, _]) + // IETF Protocol Assignments (`2001::/23`) + || (matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200) + && !( + // Port Control Protocol Anycast (`2001:1::1`) + u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001 + // Traversal Using Relays around NAT Anycast (`2001:1::2`) + || u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002 + // AMT (`2001:3::/32`) + || matches!(self.segments(), [0x2001, 3, _, _, _, _, _, _]) + // AS112-v6 (`2001:4:112::/48`) + || matches!(self.segments(), [0x2001, 4, 0x112, _, _, _, _, _]) + // ORCHIDv2 (`2001:20::/28`) + || matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x2F) + )) + || self.is_documentation() + || self.is_unique_local() + || self.is_unicast_link_local()) + } + + /// Returns [`true`] if this is a unique local address (`fc00::/7`). + /// + /// This property is defined in [IETF RFC 4193]. + /// + /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193 + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false); + /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_ipv6", issue = "76205") + )] + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + #[must_use] + #[inline] + pub const fn is_unique_local(&self) -> bool { + (self.segments()[0] & 0xfe00) == 0xfc00 + } + + /// Returns [`true`] if this is a unicast address, as defined by [IETF RFC 4291]. + /// Any address that is not a [multicast address] (`ff00::/8`) is unicast. + /// + /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 + /// [multicast address]: Ipv6Addr::is_multicast + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv6Addr; + /// + /// // The unspecified and loopback addresses are unicast. + /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_unicast(), true); + /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast(), true); + /// + /// // Any address that is not a multicast address (`ff00::/8`) is unicast. + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast(), true); + /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_unicast(), false); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_ipv6", issue = "76205") + )] + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + #[must_use] + #[inline] + pub const fn is_unicast(&self) -> bool { + !self.is_multicast() + } + + /// Returns `true` if the address is a unicast address with link-local scope, + /// as defined in [RFC 4291]. + /// + /// A unicast address has link-local scope if it has the prefix `fe80::/10`, as per [RFC 4291 section 2.4]. + /// Note that this encompasses more addresses than those defined in [RFC 4291 section 2.5.6], + /// which describes "Link-Local IPv6 Unicast Addresses" as having the following stricter format: + /// + /// ```text + /// | 10 bits | 54 bits | 64 bits | + /// +----------+-------------------------+----------------------------+ + /// |1111111010| 0 | interface ID | + /// +----------+-------------------------+----------------------------+ + /// ``` + /// So while currently the only addresses with link-local scope an application will encounter are all in `fe80::/64`, + /// this might change in the future with the publication of new standards. More addresses in `fe80::/10` could be allocated, + /// and those addresses will have link-local scope. + /// + /// Also note that while [RFC 4291 section 2.5.3] mentions about the [loopback address] (`::1`) that "it is treated as having Link-Local scope", + /// this does not mean that the loopback address actually has link-local scope and this method will return `false` on it. + /// + /// [RFC 4291]: https://tools.ietf.org/html/rfc4291 + /// [RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4 + /// [RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3 + /// [RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6 + /// [loopback address]: Ipv6Addr::LOCALHOST + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv6Addr; + /// + /// // The loopback address (`::1`) does not actually have link-local scope. + /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast_link_local(), false); + /// + /// // Only addresses in `fe80::/10` have link-local scope. + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), false); + /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true); + /// + /// // Addresses outside the stricter `fe80::/64` also have link-local scope. + /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0).is_unicast_link_local(), true); + /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_ipv6", issue = "76205") + )] + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + #[must_use] + #[inline] + pub const fn is_unicast_link_local(&self) -> bool { + (self.segments()[0] & 0xffc0) == 0xfe80 + } + + /// Returns [`true`] if this is an address reserved for documentation + /// (`2001:db8::/32`). + /// + /// This property is defined in [IETF RFC 3849]. + /// + /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849 + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false); + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_ipv6", issue = "76205") + )] + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + #[must_use] + #[inline] + pub const fn is_documentation(&self) -> bool { + (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8) + } + + /// Returns [`true`] if this is an address reserved for benchmarking (`2001:2::/48`). + /// + /// This property is defined in [IETF RFC 5180], where it is mistakenly specified as covering the range `2001:0200::/48`. + /// This is corrected in [IETF RFC Errata 1752] to `2001:0002::/48`. + /// + /// [IETF RFC 5180]: https://tools.ietf.org/html/rfc5180 + /// [IETF RFC Errata 1752]: https://www.rfc-editor.org/errata_search.php?eid=1752 + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc613, 0x0).is_benchmarking(), false); + /// assert_eq!(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0).is_benchmarking(), true); + /// ``` + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + #[must_use] + #[inline] + pub const fn is_benchmarking(&self) -> bool { + (self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) && (self.segments()[2] == 0) + } + + /// Returns [`true`] if the address is a globally routable unicast address. + /// + /// The following return false: + /// + /// - the loopback address + /// - the link-local addresses + /// - unique local addresses + /// - the unspecified address + /// - the address range reserved for documentation + /// + /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7] + /// + /// ```no_rust + /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer + /// be supported in new implementations (i.e., new implementations must treat this prefix as + /// Global Unicast). + /// ``` + /// + /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7 + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_ipv6", issue = "76205") + )] + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + #[must_use] + #[inline] + pub const fn is_unicast_global(&self) -> bool { + self.is_unicast() + && !self.is_loopback() + && !self.is_unicast_link_local() + && !self.is_unique_local() + && !self.is_unspecified() + && !self.is_documentation() + && !self.is_benchmarking() + } + + /// Returns the address's multicast scope if the address is multicast. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::{Ipv6Addr, Ipv6MulticastScope}; + /// + /// assert_eq!( + /// Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(), + /// Some(Ipv6MulticastScope::Global) + /// ); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_ipv6", issue = "76205") + )] + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + #[must_use] + #[inline] + pub const fn multicast_scope(&self) -> Option { + if self.is_multicast() { + match self.segments()[0] & 0x000f { + 1 => Some(Ipv6MulticastScope::InterfaceLocal), + 2 => Some(Ipv6MulticastScope::LinkLocal), + 3 => Some(Ipv6MulticastScope::RealmLocal), + 4 => Some(Ipv6MulticastScope::AdminLocal), + 5 => Some(Ipv6MulticastScope::SiteLocal), + 8 => Some(Ipv6MulticastScope::OrganizationLocal), + 14 => Some(Ipv6MulticastScope::Global), + _ => None, + } + } else { + None + } + } + + /// Returns [`true`] if this is a multicast address (`ff00::/8`). + /// + /// This property is defined by [IETF RFC 4291]. + /// + /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] + #[must_use] + #[inline] + pub const fn is_multicast(&self) -> bool { + (self.segments()[0] & 0xff00) == 0xff00 + } + + /// Converts this address to an [`IPv4` address] if it's an [IPv4-mapped] address, + /// as defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`]. + /// + /// `::ffff:a.b.c.d` becomes `a.b.c.d`. + /// All addresses *not* starting with `::ffff` will return `None`. + /// + /// [`IPv4` address]: Ipv4Addr + /// [IPv4-mapped]: Ipv6Addr + /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2 + /// + /// # Examples + /// + /// ``` + /// use std::net::{Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(), + /// Some(Ipv4Addr::new(192, 10, 2, 255))); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_ipv6", issue = "76205") + )] + #[cfg_attr(staged_api, stable(feature = "ipv6_to_ipv4_mapped", since = "1.63.0"))] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_ipv4_mapped(&self) -> Option { + match self.octets() { + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => { + Some(Ipv4Addr::new(a, b, c, d)) + } + _ => None, + } + } + + /// Converts this address to an [`IPv4` address] if it is either + /// an [IPv4-compatible] address as defined in [IETF RFC 4291 section 2.5.5.1], + /// or an [IPv4-mapped] address as defined in [IETF RFC 4291 section 2.5.5.2], + /// otherwise returns [`None`]. + /// + /// Note that this will return an [`IPv4` address] for the IPv6 loopback address `::1`. Use + /// [`Ipv6Addr::to_ipv4_mapped`] to avoid this. + /// + /// `::a.b.c.d` and `::ffff:a.b.c.d` become `a.b.c.d`. `::1` becomes `0.0.0.1`. + /// All addresses *not* starting with either all zeroes or `::ffff` will return `None`. + /// + /// [`IPv4` address]: Ipv4Addr + /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses + /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses + /// [IETF RFC 4291 section 2.5.5.1]: https://tools.ietf.org/html/rfc4291#section-2.5.5.1 + /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2 + /// + /// # Examples + /// + /// ``` + /// use std::net::{Ipv4Addr, Ipv6Addr}; + /// + /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(), + /// Some(Ipv4Addr::new(192, 10, 2, 255))); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(), + /// Some(Ipv4Addr::new(0, 0, 0, 1))); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_50", since = "1.50.0") + )] + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_ipv4(&self) -> Option { + if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() { + let [a, b] = ab.to_be_bytes(); + let [c, d] = cd.to_be_bytes(); + Some(Ipv4Addr::new(a, b, c, d)) + } else { + None + } + } + + /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped addresses, otherwise it + /// returns self wrapped in an `IpAddr::V6`. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false); + /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).to_canonical().is_loopback(), true); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_ipv6", issue = "76205") + )] + #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn to_canonical(&self) -> IpAddr { + if let Some(mapped) = self.to_ipv4_mapped() { + return IpAddr::V4(mapped); + } + IpAddr::V6(*self) + } + + /// Returns the sixteen eight-bit integers the IPv6 address consists of. + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(), + /// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + /// ``` + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "const_ip_32", since = "1.32.0") + )] + #[cfg_attr(staged_api, stable(feature = "ipv6_to_octets", since = "1.12.0"))] + #[must_use] + #[inline] + pub const fn octets(&self) -> [u8; 16] { + self.octets + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] +impl PartialEq for Ipv6Addr { + #[inline] + fn eq(&self, other: &IpAddr) -> bool { + match other { + IpAddr::V4(_) => false, + IpAddr::V6(v6) => self == v6, + } + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] +impl PartialEq for IpAddr { + #[inline] + fn eq(&self, other: &Ipv6Addr) -> bool { + match self { + IpAddr::V4(_) => false, + IpAddr::V6(v6) => v6 == other, + } + } +} + +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +impl PartialOrd for Ipv6Addr { + #[inline] + fn partial_cmp(&self, other: &Ipv6Addr) -> Option { + Some(self.cmp(other)) + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] +impl PartialOrd for IpAddr { + #[inline] + fn partial_cmp(&self, other: &Ipv6Addr) -> Option { + match self { + IpAddr::V4(_) => Some(Ordering::Less), + IpAddr::V6(v6) => v6.partial_cmp(other), + } + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] +impl PartialOrd for Ipv6Addr { + #[inline] + fn partial_cmp(&self, other: &IpAddr) -> Option { + match other { + IpAddr::V4(_) => Some(Ordering::Greater), + IpAddr::V6(v6) => self.partial_cmp(v6), + } + } +} + +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +impl Ord for Ipv6Addr { + #[inline] + fn cmp(&self, other: &Ipv6Addr) -> Ordering { + self.segments().cmp(&other.segments()) + } +} + +#[cfg_attr(staged_api, stable(feature = "i128", since = "1.26.0"))] +impl From for u128 { + /// Convert an `Ipv6Addr` into a host byte order `u128`. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::new( + /// 0x1020, 0x3040, 0x5060, 0x7080, + /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D, + /// ); + /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr)); + /// ``` + #[inline] + fn from(ip: Ipv6Addr) -> u128 { + u128::from_be_bytes(ip.octets) + } +} +#[cfg_attr(staged_api, stable(feature = "i128", since = "1.26.0"))] +impl From for Ipv6Addr { + /// Convert a host byte order `u128` into an `Ipv6Addr`. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128); + /// assert_eq!( + /// Ipv6Addr::new( + /// 0x1020, 0x3040, 0x5060, 0x7080, + /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D, + /// ), + /// addr); + /// ``` + #[inline] + fn from(ip: u128) -> Ipv6Addr { + Ipv6Addr::from(ip.to_be_bytes()) + } +} + +#[cfg_attr(staged_api, stable(feature = "ipv6_from_octets", since = "1.9.0"))] +impl From<[u8; 16]> for Ipv6Addr { + /// Creates an `Ipv6Addr` from a sixteen element byte array. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::from([ + /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8, + /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8, + /// ]); + /// assert_eq!( + /// Ipv6Addr::new( + /// 0x1918, 0x1716, + /// 0x1514, 0x1312, + /// 0x1110, 0x0f0e, + /// 0x0d0c, 0x0b0a + /// ), + /// addr + /// ); + /// ``` + #[inline] + fn from(octets: [u8; 16]) -> Ipv6Addr { + Ipv6Addr { octets } + } +} + +#[cfg_attr(staged_api, stable(feature = "ipv6_from_segments", since = "1.16.0"))] +impl From<[u16; 8]> for Ipv6Addr { + /// Creates an `Ipv6Addr` from an eight element 16-bit array. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv6Addr; + /// + /// let addr = Ipv6Addr::from([ + /// 525u16, 524u16, 523u16, 522u16, + /// 521u16, 520u16, 519u16, 518u16, + /// ]); + /// assert_eq!( + /// Ipv6Addr::new( + /// 0x20d, 0x20c, + /// 0x20b, 0x20a, + /// 0x209, 0x208, + /// 0x207, 0x206 + /// ), + /// addr + /// ); + /// ``` + #[inline] + fn from(segments: [u16; 8]) -> Ipv6Addr { + let [a, b, c, d, e, f, g, h] = segments; + Ipv6Addr::new(a, b, c, d, e, f, g, h) + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_from_slice", since = "1.17.0"))] +impl From<[u8; 16]> for IpAddr { + /// Creates an `IpAddr::V6` from a sixteen element byte array. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv6Addr}; + /// + /// let addr = IpAddr::from([ + /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8, + /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8, + /// ]); + /// assert_eq!( + /// IpAddr::V6(Ipv6Addr::new( + /// 0x1918, 0x1716, + /// 0x1514, 0x1312, + /// 0x1110, 0x0f0e, + /// 0x0d0c, 0x0b0a + /// )), + /// addr + /// ); + /// ``` + #[inline] + fn from(octets: [u8; 16]) -> IpAddr { + IpAddr::V6(Ipv6Addr::from(octets)) + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_from_slice", since = "1.17.0"))] +impl From<[u16; 8]> for IpAddr { + /// Creates an `IpAddr::V6` from an eight element 16-bit array. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv6Addr}; + /// + /// let addr = IpAddr::from([ + /// 525u16, 524u16, 523u16, 522u16, + /// 521u16, 520u16, 519u16, 518u16, + /// ]); + /// assert_eq!( + /// IpAddr::V6(Ipv6Addr::new( + /// 0x20d, 0x20c, + /// 0x20b, 0x20a, + /// 0x209, 0x208, + /// 0x207, 0x206 + /// )), + /// addr + /// ); + /// ``` + #[inline] + fn from(segments: [u16; 8]) -> IpAddr { + IpAddr::V6(Ipv6Addr::from(segments)) + } +} diff --git a/vendor/rustix/src/maybe_polyfill/no_std/net/mod.rs b/vendor/rustix/src/maybe_polyfill/no_std/net/mod.rs new file mode 100644 index 000000000..ff3356482 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/net/mod.rs @@ -0,0 +1,5 @@ +mod ip_addr; +mod socket_addr; + +pub use self::ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; +pub use self::socket_addr::{SocketAddr, SocketAddrV4, SocketAddrV6}; diff --git a/vendor/rustix/src/maybe_polyfill/no_std/net/socket_addr.rs b/vendor/rustix/src/maybe_polyfill/no_std/net/socket_addr.rs new file mode 100644 index 000000000..053d8f670 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/net/socket_addr.rs @@ -0,0 +1,641 @@ +//! The following is derived from Rust's +//! library/std/src/net/socket_addr.rs at revision +//! bd20fc1fd657b32f7aa1d70d8723f04c87f21606. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. +//! +//! This defines `SocketAddr`, `SocketAddrV4`, and `SocketAddrV6` in a +//! platform-independent way. It is not the native representation. + +use super::ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr}; +use core::cmp::Ordering; +use core::hash; + +/// An internet socket address, either IPv4 or IPv6. +/// +/// Internet socket addresses consist of an [IP address], a 16-bit port number, as well +/// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and +/// [`SocketAddrV6`]'s respective documentation for more details. +/// +/// The size of a `SocketAddr` instance may vary depending on the target operating +/// system. +/// +/// [IP address]: IpAddr +/// +/// # Examples +/// +/// ``` +/// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; +/// +/// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); +/// +/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket)); +/// assert_eq!(socket.port(), 8080); +/// assert_eq!(socket.is_ipv4(), true); +/// ``` +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub enum SocketAddr { + /// An IPv4 socket address. + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + V4(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] SocketAddrV4), + /// An IPv6 socket address. + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + V6(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] SocketAddrV6), +} + +/// An IPv4 socket address. +/// +/// IPv4 socket addresses consist of an [`IPv4` address] and a 16-bit port number, as +/// stated in [IETF RFC 793]. +/// +/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses. +/// +/// The size of a `SocketAddrV4` struct may vary depending on the target operating +/// system. Do not assume that this type has the same memory layout as the underlying +/// system representation. +/// +/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793 +/// [`IPv4` address]: Ipv4Addr +/// +/// # Examples +/// +/// ``` +/// use std::net::{Ipv4Addr, SocketAddrV4}; +/// +/// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); +/// +/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket)); +/// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); +/// assert_eq!(socket.port(), 8080); +/// ``` +#[derive(Copy, Clone, Eq, PartialEq)] +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub struct SocketAddrV4 { + ip: Ipv4Addr, + port: u16, +} + +/// An IPv6 socket address. +/// +/// IPv6 socket addresses consist of an [`IPv6` address], a 16-bit port number, as well +/// as fields containing the traffic class, the flow label, and a scope identifier +/// (see [IETF RFC 2553, Section 3.3] for more details). +/// +/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses. +/// +/// The size of a `SocketAddrV6` struct may vary depending on the target operating +/// system. Do not assume that this type has the same memory layout as the underlying +/// system representation. +/// +/// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 +/// [`IPv6` address]: Ipv6Addr +/// +/// # Examples +/// +/// ``` +/// use std::net::{Ipv6Addr, SocketAddrV6}; +/// +/// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0); +/// +/// assert_eq!("[2001:db8::1]:8080".parse(), Ok(socket)); +/// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); +/// assert_eq!(socket.port(), 8080); +/// ``` +#[derive(Copy, Clone, Eq, PartialEq)] +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub struct SocketAddrV6 { + ip: Ipv6Addr, + port: u16, + flowinfo: u32, + scope_id: u32, +} + +impl SocketAddr { + /// Creates a new socket address from an [IP address] and a port number. + /// + /// [IP address]: IpAddr + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); + /// assert_eq!(socket.port(), 8080); + /// ``` + #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] + #[must_use] + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_socketaddr", issue = "82485") + )] + pub const fn new(ip: IpAddr, port: u16) -> SocketAddr { + match ip { + IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)), + IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)), + } + } + + /// Returns the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); + /// ``` + #[must_use] + #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_socketaddr", issue = "82485") + )] + pub const fn ip(&self) -> IpAddr { + match *self { + SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()), + SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()), + } + } + + /// Changes the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); + /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); + /// ``` + #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] + pub fn set_ip(&mut self, new_ip: IpAddr) { + // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away. + match (self, new_ip) { + (&mut SocketAddr::V4(ref mut a), IpAddr::V4(new_ip)) => a.set_ip(new_ip), + (&mut SocketAddr::V6(ref mut a), IpAddr::V6(new_ip)) => a.set_ip(new_ip), + (self_, new_ip) => *self_ = Self::new(new_ip, self_.port()), + } + } + + /// Returns the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.port(), 8080); + /// ``` + #[must_use] + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_socketaddr", issue = "82485") + )] + pub const fn port(&self) -> u16 { + match *self { + SocketAddr::V4(ref a) => a.port(), + SocketAddr::V6(ref a) => a.port(), + } + } + + /// Changes the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// socket.set_port(1025); + /// assert_eq!(socket.port(), 1025); + /// ``` + #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] + pub fn set_port(&mut self, new_port: u16) { + match *self { + SocketAddr::V4(ref mut a) => a.set_port(new_port), + SocketAddr::V6(ref mut a) => a.set_port(new_port), + } + } + + /// Returns [`true`] if the [IP address] in this `SocketAddr` is an + /// [`IPv4` address], and [`false`] otherwise. + /// + /// [IP address]: IpAddr + /// [`IPv4` address]: IpAddr::V4 + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.is_ipv4(), true); + /// assert_eq!(socket.is_ipv6(), false); + /// ``` + #[must_use] + #[cfg_attr(staged_api, stable(feature = "sockaddr_checker", since = "1.16.0"))] + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_socketaddr", issue = "82485") + )] + pub const fn is_ipv4(&self) -> bool { + matches!(*self, SocketAddr::V4(_)) + } + + /// Returns [`true`] if the [IP address] in this `SocketAddr` is an + /// [`IPv6` address], and [`false`] otherwise. + /// + /// [IP address]: IpAddr + /// [`IPv6` address]: IpAddr::V6 + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv6Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080); + /// assert_eq!(socket.is_ipv4(), false); + /// assert_eq!(socket.is_ipv6(), true); + /// ``` + #[must_use] + #[cfg_attr(staged_api, stable(feature = "sockaddr_checker", since = "1.16.0"))] + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_socketaddr", issue = "82485") + )] + pub const fn is_ipv6(&self) -> bool { + matches!(*self, SocketAddr::V6(_)) + } +} + +impl SocketAddrV4 { + /// Creates a new socket address from an [`IPv4` address] and a port number. + /// + /// [`IPv4` address]: Ipv4Addr + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV4, Ipv4Addr}; + /// + /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); + /// ``` + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + #[must_use] + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_socketaddr", issue = "82485") + )] + pub const fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 { + SocketAddrV4 { ip, port } + } + + /// Returns the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV4, Ipv4Addr}; + /// + /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); + /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); + /// ``` + #[must_use] + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_socketaddr", issue = "82485") + )] + pub const fn ip(&self) -> &Ipv4Addr { + &self.ip + } + + /// Changes the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV4, Ipv4Addr}; + /// + /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); + /// socket.set_ip(Ipv4Addr::new(192, 168, 0, 1)); + /// assert_eq!(socket.ip(), &Ipv4Addr::new(192, 168, 0, 1)); + /// ``` + #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] + pub fn set_ip(&mut self, new_ip: Ipv4Addr) { + self.ip = new_ip; + } + + /// Returns the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV4, Ipv4Addr}; + /// + /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); + /// assert_eq!(socket.port(), 8080); + /// ``` + #[must_use] + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_socketaddr", issue = "82485") + )] + pub const fn port(&self) -> u16 { + self.port + } + + /// Changes the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV4, Ipv4Addr}; + /// + /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); + /// socket.set_port(4242); + /// assert_eq!(socket.port(), 4242); + /// ``` + #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] + pub fn set_port(&mut self, new_port: u16) { + self.port = new_port; + } +} + +impl SocketAddrV6 { + /// Creates a new socket address from an [`IPv6` address], a 16-bit port number, + /// and the `flowinfo` and `scope_id` fields. + /// + /// For more information on the meaning and layout of the `flowinfo` and `scope_id` + /// parameters, see [IETF RFC 2553, Section 3.3]. + /// + /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 + /// [`IPv6` address]: Ipv6Addr + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); + /// ``` + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + #[must_use] + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_socketaddr", issue = "82485") + )] + pub const fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 { + SocketAddrV6 { + ip, + port, + flowinfo, + scope_id, + } + } + + /// Returns the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); + /// assert_eq!(socket.ip(), &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); + /// ``` + #[must_use] + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_socketaddr", issue = "82485") + )] + pub const fn ip(&self) -> &Ipv6Addr { + &self.ip + } + + /// Changes the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); + /// socket.set_ip(Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0)); + /// assert_eq!(socket.ip(), &Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0)); + /// ``` + #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] + pub fn set_ip(&mut self, new_ip: Ipv6Addr) { + self.ip = new_ip; + } + + /// Returns the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); + /// assert_eq!(socket.port(), 8080); + /// ``` + #[must_use] + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_socketaddr", issue = "82485") + )] + pub const fn port(&self) -> u16 { + self.port + } + + /// Changes the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); + /// socket.set_port(4242); + /// assert_eq!(socket.port(), 4242); + /// ``` + #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] + pub fn set_port(&mut self, new_port: u16) { + self.port = new_port; + } + + /// Returns the flow information associated with this address. + /// + /// This information corresponds to the `sin6_flowinfo` field in C's `netinet/in.h`, + /// as specified in [IETF RFC 2553, Section 3.3]. + /// It combines information about the flow label and the traffic class as specified + /// in [IETF RFC 2460], respectively [Section 6] and [Section 7]. + /// + /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 + /// [IETF RFC 2460]: https://tools.ietf.org/html/rfc2460 + /// [Section 6]: https://tools.ietf.org/html/rfc2460#section-6 + /// [Section 7]: https://tools.ietf.org/html/rfc2460#section-7 + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0); + /// assert_eq!(socket.flowinfo(), 10); + /// ``` + #[must_use] + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_socketaddr", issue = "82485") + )] + pub const fn flowinfo(&self) -> u32 { + self.flowinfo + } + + /// Changes the flow information associated with this socket address. + /// + /// See [`SocketAddrV6::flowinfo`]'s documentation for more details. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0); + /// socket.set_flowinfo(56); + /// assert_eq!(socket.flowinfo(), 56); + /// ``` + #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] + pub fn set_flowinfo(&mut self, new_flowinfo: u32) { + self.flowinfo = new_flowinfo; + } + + /// Returns the scope ID associated with this address. + /// + /// This information corresponds to the `sin6_scope_id` field in C's `netinet/in.h`, + /// as specified in [IETF RFC 2553, Section 3.3]. + /// + /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78); + /// assert_eq!(socket.scope_id(), 78); + /// ``` + #[must_use] + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + #[cfg_attr( + staged_api, + rustc_const_unstable(feature = "const_socketaddr", issue = "82485") + )] + pub const fn scope_id(&self) -> u32 { + self.scope_id + } + + /// Changes the scope ID associated with this socket address. + /// + /// See [`SocketAddrV6::scope_id`]'s documentation for more details. + /// + /// # Examples + /// + /// ``` + /// use std::net::{SocketAddrV6, Ipv6Addr}; + /// + /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78); + /// socket.set_scope_id(42); + /// assert_eq!(socket.scope_id(), 42); + /// ``` + #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] + pub fn set_scope_id(&mut self, new_scope_id: u32) { + self.scope_id = new_scope_id; + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_from_ip", since = "1.16.0"))] +impl From for SocketAddr { + /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`]. + fn from(sock4: SocketAddrV4) -> SocketAddr { + SocketAddr::V4(sock4) + } +} + +#[cfg_attr(staged_api, stable(feature = "ip_from_ip", since = "1.16.0"))] +impl From for SocketAddr { + /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`]. + fn from(sock6: SocketAddrV6) -> SocketAddr { + SocketAddr::V6(sock6) + } +} + +#[cfg_attr(staged_api, stable(feature = "addr_from_into_ip", since = "1.17.0"))] +impl> From<(I, u16)> for SocketAddr { + /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`]. + /// + /// This conversion creates a [`SocketAddr::V4`] for an [`IpAddr::V4`] + /// and creates a [`SocketAddr::V6`] for an [`IpAddr::V6`]. + /// + /// `u16` is treated as port of the newly created [`SocketAddr`]. + fn from(pieces: (I, u16)) -> SocketAddr { + SocketAddr::new(pieces.0.into(), pieces.1) + } +} + +#[cfg_attr(staged_api, stable(feature = "socketaddr_ordering", since = "1.45.0"))] +impl PartialOrd for SocketAddrV4 { + fn partial_cmp(&self, other: &SocketAddrV4) -> Option { + Some(self.cmp(other)) + } +} + +#[cfg_attr(staged_api, stable(feature = "socketaddr_ordering", since = "1.45.0"))] +impl PartialOrd for SocketAddrV6 { + fn partial_cmp(&self, other: &SocketAddrV6) -> Option { + Some(self.cmp(other)) + } +} + +#[cfg_attr(staged_api, stable(feature = "socketaddr_ordering", since = "1.45.0"))] +impl Ord for SocketAddrV4 { + fn cmp(&self, other: &SocketAddrV4) -> Ordering { + self.ip() + .cmp(other.ip()) + .then(self.port().cmp(&other.port())) + } +} + +#[cfg_attr(staged_api, stable(feature = "socketaddr_ordering", since = "1.45.0"))] +impl Ord for SocketAddrV6 { + fn cmp(&self, other: &SocketAddrV6) -> Ordering { + self.ip() + .cmp(other.ip()) + .then(self.port().cmp(&other.port())) + } +} + +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +impl hash::Hash for SocketAddrV4 { + fn hash(&self, s: &mut H) { + (self.port, self.ip).hash(s) + } +} +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +impl hash::Hash for SocketAddrV6 { + fn hash(&self, s: &mut H) { + (self.port, &self.ip, self.flowinfo, self.scope_id).hash(s) + } +} diff --git a/vendor/rustix/src/maybe_polyfill/no_std/os/fd/mod.rs b/vendor/rustix/src/maybe_polyfill/no_std/os/fd/mod.rs new file mode 100644 index 000000000..2d88fb076 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/os/fd/mod.rs @@ -0,0 +1,19 @@ +//! The following is derived from Rust's +//! library/std/src/os/fd/mod.rs at revision +//! fa68e73e9947be8ffc5b3b46d899e4953a44e7e9. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. +//! +//! Owned and borrowed Unix-like file descriptors. + +#![cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +#![deny(unsafe_op_in_unsafe_fn)] + +// `RawFd`, `AsRawFd`, etc. +mod raw; + +// `OwnedFd`, `AsFd`, etc. +mod owned; + +pub use owned::*; +pub use raw::*; diff --git a/vendor/rustix/src/maybe_polyfill/no_std/os/fd/owned.rs b/vendor/rustix/src/maybe_polyfill/no_std/os/fd/owned.rs new file mode 100644 index 000000000..90b6f4712 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/os/fd/owned.rs @@ -0,0 +1,254 @@ +//! The following is derived from Rust's +//! library/std/src/os/fd/owned.rs at revision +//! fa68e73e9947be8ffc5b3b46d899e4953a44e7e9. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. +//! +//! Owned and borrowed Unix-like file descriptors. + +#![cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +#![deny(unsafe_op_in_unsafe_fn)] +#![allow(unsafe_code)] + +use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; +use crate::io::close; +use core::fmt; +use core::marker::PhantomData; +use core::mem::forget; + +/// A borrowed file descriptor. +/// +/// This has a lifetime parameter to tie it to the lifetime of something that +/// owns the file descriptor. +/// +/// This uses `repr(transparent)` and has the representation of a host file +/// descriptor, so it can be used in FFI in places where a file descriptor is +/// passed as an argument, it is not captured or consumed, and it never has the +/// value `-1`. +/// +/// This type's `.to_owned()` implementation returns another `BorrowedFd` +/// rather than an `OwnedFd`. It just makes a trivial copy of the raw file +/// descriptor, which is then borrowed under the same lifetime. +#[derive(Copy, Clone)] +#[repr(transparent)] +#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0))] +// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a +// 32-bit c_int. Below is -2, in two's complement, but that only works out +// because c_int is 32 bits. +#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))] +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +#[cfg_attr(rustc_attrs, rustc_nonnull_optimization_guaranteed)] +pub struct BorrowedFd<'fd> { + fd: RawFd, + _phantom: PhantomData<&'fd OwnedFd>, +} + +/// An owned file descriptor. +/// +/// This closes the file descriptor on drop. +/// +/// This uses `repr(transparent)` and has the representation of a host file +/// descriptor, so it can be used in FFI in places where a file descriptor is +/// passed as a consumed argument or returned as an owned value, and it never +/// has the value `-1`. +#[repr(transparent)] +#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0))] +// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a +// 32-bit c_int. Below is -2, in two's complement, but that only works out +// because c_int is 32 bits. +#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))] +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +#[cfg_attr(rustc_attrs, rustc_nonnull_optimization_guaranteed)] +pub struct OwnedFd { + fd: RawFd, +} + +impl BorrowedFd<'_> { + /// Return a `BorrowedFd` holding the given raw file descriptor. + /// + /// # Safety + /// + /// The resource pointed to by `fd` must remain open for the duration of + /// the returned `BorrowedFd`, and it must not have the value `-1`. + #[inline] + #[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] + pub const unsafe fn borrow_raw(fd: RawFd) -> Self { + assert!(fd != u32::MAX as RawFd); + // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) + #[allow(unused_unsafe)] + unsafe { + Self { + fd, + _phantom: PhantomData, + } + } + } +} + +impl OwnedFd { + /// Creates a new `OwnedFd` instance that shares the same underlying file handle + /// as the existing `OwnedFd` instance. + #[cfg(not(target_arch = "wasm32"))] + pub fn try_clone(&self) -> crate::io::Result { + // We want to atomically duplicate this file descriptor and set the + // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This + // is a POSIX flag that was added to Linux in 2.6.24. + #[cfg(not(target_os = "espidf"))] + let fd = crate::io::fcntl_dupfd_cloexec(self, 0)?; + + // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics + // will never be supported, as this is a bare metal framework with + // no capabilities for multi-process execution. While F_DUPFD is also + // not supported yet, it might be (currently it returns ENOSYS). + #[cfg(target_os = "espidf")] + let fd = crate::io::fcntl_dupfd(self)?; + + Ok(fd.into()) + } + + #[cfg(target_arch = "wasm32")] + pub fn try_clone(&self) -> crate::io::Result { + Err(crate::io::const_io_error!( + crate::io::ErrorKind::Unsupported, + "operation not supported on WASI yet", + )) + } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl AsRawFd for BorrowedFd<'_> { + #[inline] + fn as_raw_fd(&self) -> RawFd { + self.fd + } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl AsRawFd for OwnedFd { + #[inline] + fn as_raw_fd(&self) -> RawFd { + self.fd + } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl IntoRawFd for OwnedFd { + #[inline] + fn into_raw_fd(self) -> RawFd { + let fd = self.fd; + forget(self); + fd + } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl FromRawFd for OwnedFd { + /// Constructs a new instance of `Self` from the given raw file descriptor. + /// + /// # Safety + /// + /// The resource pointed to by `fd` must be open and suitable for assuming + /// ownership. The resource must not require any cleanup other than `close`. + #[inline] + unsafe fn from_raw_fd(fd: RawFd) -> Self { + assert_ne!(fd, u32::MAX as RawFd); + // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) + #[allow(unused_unsafe)] + unsafe { + Self { fd } + } + } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl Drop for OwnedFd { + #[inline] + fn drop(&mut self) { + unsafe { + // Errors are ignored when closing a file descriptor. The reason + // for this is that if an error occurs we don't actually know if + // the file descriptor was closed or not, and if we retried (for + // something like EINTR), we might close another valid file + // descriptor opened after we closed ours. + close(self.fd as _); + } + } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl fmt::Debug for BorrowedFd<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("BorrowedFd").field("fd", &self.fd).finish() + } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl fmt::Debug for OwnedFd { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OwnedFd").field("fd", &self.fd).finish() + } +} + +/// A trait to borrow the file descriptor from an underlying object. +/// +/// This is only available on unix platforms and must be imported in order to +/// call the method. Windows platforms have a corresponding `AsHandle` and +/// `AsSocket` set of traits. +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +pub trait AsFd { + /// Borrows the file descriptor. + /// + /// # Example + /// + /// ```no_run + /// # #![feature(io_safety)] + /// use std::fs::File; + /// # use std::io; + /// # #[cfg(target_os = "wasi")] + /// # use std::os::wasi::io::{AsFd, BorrowedFd}; + /// # #[cfg(unix)] + /// # use std::os::unix::io::{AsFd, BorrowedFd}; + /// + /// let mut f = File::open("foo.txt")?; + /// # #[cfg(any(unix, target_os = "wasi"))] + /// let borrowed_fd: BorrowedFd<'_> = f.as_fd(); + /// # Ok::<(), io::Error>(()) + /// ``` + #[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] + fn as_fd(&self) -> BorrowedFd<'_>; +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl AsFd for &T { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + T::as_fd(self) + } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl AsFd for &mut T { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + T::as_fd(self) + } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl AsFd for BorrowedFd<'_> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + *self + } +} + +#[cfg_attr(staged_api, unstable(feature = "io_safety", issue = "87074"))] +impl AsFd for OwnedFd { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + // SAFETY: `OwnedFd` and `BorrowedFd` have the same validity + // invariants, and the `BorrowedFd` is bounded by the lifetime + // of `&self`. + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } +} diff --git a/vendor/rustix/src/maybe_polyfill/no_std/os/fd/raw.rs b/vendor/rustix/src/maybe_polyfill/no_std/os/fd/raw.rs new file mode 100644 index 000000000..41968ab04 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/os/fd/raw.rs @@ -0,0 +1,161 @@ +//! The following is derived from Rust's +//! library/std/src/os/fd/raw.rs at revision +//! fa68e73e9947be8ffc5b3b46d899e4953a44e7e9. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. +//! +//! Raw Unix-like file descriptors. + +#![cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +#![allow(unsafe_code)] + +use crate::backend::c; + +/// Raw file descriptors. +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub type RawFd = c::c_int; + +/// A trait to extract the raw file descriptor from an underlying object. +/// +/// This is only available on unix and WASI platforms and must be imported in +/// order to call the method. Windows platforms have a corresponding +/// `AsRawHandle` and `AsRawSocket` set of traits. +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub trait AsRawFd { + /// Extracts the raw file descriptor. + /// + /// This function is typically used to **borrow** an owned file descriptor. + /// When used in this way, this method does **not** pass ownership of the + /// raw file descriptor to the caller, and the file descriptor is only + /// guaranteed to be valid while the original object has not yet been + /// destroyed. + /// + /// However, borrowing is not strictly required. See [`AsFd::as_fd`] + /// for an API which strictly borrows a file descriptor. + /// + /// # Example + /// + /// ```no_run + /// use std::fs::File; + /// # use std::io; + /// #[cfg(unix)] + /// use std::os::unix::io::{AsRawFd, RawFd}; + /// #[cfg(target_os = "wasi")] + /// use std::os::wasi::io::{AsRawFd, RawFd}; + /// + /// let mut f = File::open("foo.txt")?; + /// // `raw_fd` is only valid as long as `f` exists. + /// #[cfg(any(unix, target_os = "wasi"))] + /// let raw_fd: RawFd = f.as_raw_fd(); + /// # Ok::<(), io::Error>(()) + /// ``` + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + fn as_raw_fd(&self) -> RawFd; +} + +/// A trait to express the ability to construct an object from a raw file +/// descriptor. +#[cfg_attr(staged_api, stable(feature = "from_raw_os", since = "1.1.0"))] +pub trait FromRawFd { + /// Constructs a new instance of `Self` from the given raw file + /// descriptor. + /// + /// This function is typically used to **consume ownership** of the + /// specified file descriptor. When used in this way, the returned object + /// will take responsibility for closing it when the object goes out of + /// scope. + /// + /// However, consuming ownership is not strictly required. Use a + /// [`From::from`] implementation for an API which strictly + /// consumes ownership. + /// + /// # Safety + /// + /// The `fd` passed in must be a valid an open file descriptor. + /// + /// # Example + /// + /// ```no_run + /// use std::fs::File; + /// # use std::io; + /// #[cfg(unix)] + /// use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd}; + /// #[cfg(target_os = "wasi")] + /// use std::os::wasi::io::{FromRawFd, IntoRawFd, RawFd}; + /// + /// let f = File::open("foo.txt")?; + /// # #[cfg(any(unix, target_os = "wasi"))] + /// let raw_fd: RawFd = f.into_raw_fd(); + /// // SAFETY: no other functions should call `from_raw_fd`, so there + /// // is only one owner for the file descriptor. + /// # #[cfg(any(unix, target_os = "wasi"))] + /// let f = unsafe { File::from_raw_fd(raw_fd) }; + /// # Ok::<(), io::Error>(()) + /// ``` + #[cfg_attr(staged_api, stable(feature = "from_raw_os", since = "1.1.0"))] + unsafe fn from_raw_fd(fd: RawFd) -> Self; +} + +/// A trait to express the ability to consume an object and acquire ownership of +/// its raw file descriptor. +#[cfg_attr(staged_api, stable(feature = "into_raw_os", since = "1.4.0"))] +pub trait IntoRawFd { + /// Consumes this object, returning the raw underlying file descriptor. + /// + /// This function is typically used to **transfer ownership** of the underlying + /// file descriptor to the caller. When used in this way, callers are then the unique + /// owners of the file descriptor and must close it once it's no longer needed. + /// + /// However, transferring ownership is not strictly required. Use a + /// [`Into::into`] implementation for an API which strictly + /// transfers ownership. + /// + /// # Example + /// + /// ```no_run + /// use std::fs::File; + /// # use std::io; + /// #[cfg(unix)] + /// use std::os::unix::io::{IntoRawFd, RawFd}; + /// #[cfg(target_os = "wasi")] + /// use std::os::wasi::io::{IntoRawFd, RawFd}; + /// + /// let f = File::open("foo.txt")?; + /// #[cfg(any(unix, target_os = "wasi"))] + /// let raw_fd: RawFd = f.into_raw_fd(); + /// # Ok::<(), io::Error>(()) + /// ``` + #[cfg_attr(staged_api, stable(feature = "into_raw_os", since = "1.4.0"))] + fn into_raw_fd(self) -> RawFd; +} + +#[cfg_attr( + staged_api, + stable(feature = "raw_fd_reflexive_traits", since = "1.48.0") +)] +impl AsRawFd for RawFd { + #[inline] + fn as_raw_fd(&self) -> RawFd { + *self + } +} +#[cfg_attr( + staged_api, + stable(feature = "raw_fd_reflexive_traits", since = "1.48.0") +)] +impl IntoRawFd for RawFd { + #[inline] + fn into_raw_fd(self) -> RawFd { + self + } +} +#[cfg_attr( + staged_api, + stable(feature = "raw_fd_reflexive_traits", since = "1.48.0") +)] +impl FromRawFd for RawFd { + #[inline] + unsafe fn from_raw_fd(fd: RawFd) -> RawFd { + fd + } +} diff --git a/vendor/rustix/src/maybe_polyfill/no_std/os/mod.rs b/vendor/rustix/src/maybe_polyfill/no_std/os/mod.rs new file mode 100644 index 000000000..67f41f5b3 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/os/mod.rs @@ -0,0 +1,4 @@ +#[cfg(any(unix, target_os = "wasi"))] +pub mod fd; +#[cfg(windows)] +pub mod windows; diff --git a/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/mod.rs b/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/mod.rs new file mode 100644 index 000000000..77abd03c5 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/mod.rs @@ -0,0 +1,5 @@ +mod raw; +mod socket; + +pub use raw::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}; +pub use socket::{AsSocket, BorrowedSocket, OwnedSocket}; diff --git a/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/raw.rs b/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/raw.rs new file mode 100644 index 000000000..1e73e0019 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/raw.rs @@ -0,0 +1,71 @@ +//! The following is derived from Rust's +//! library/std/src/os/windows/io/raw.rs +//! at revision +//! 4f9b394c8a24803e57ba892fa00e539742ebafc0. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. + +use super::super::raw; + +/// Raw SOCKETs. +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub type RawSocket = raw::SOCKET; + +/// Extracts raw sockets. +#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] +pub trait AsRawSocket { + /// Extracts the raw socket. + /// + /// This function is typically used to **borrow** an owned socket. + /// When used in this way, this method does **not** pass ownership of the + /// raw socket to the caller, and the socket is only guaranteed + /// to be valid while the original object has not yet been destroyed. + /// + /// However, borrowing is not strictly required. See [`AsSocket::as_socket`] + /// for an API which strictly borrows a socket. + #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] + fn as_raw_socket(&self) -> RawSocket; +} + +/// Creates I/O objects from raw sockets. +#[cfg_attr(staged_api, stable(feature = "from_raw_os", since = "1.1.0"))] +pub trait FromRawSocket { + /// Constructs a new I/O object from the specified raw socket. + /// + /// This function is typically used to **consume ownership** of the socket + /// given, passing responsibility for closing the socket to the returned + /// object. When used in this way, the returned object + /// will take responsibility for closing it when the object goes out of + /// scope. + /// + /// However, consuming ownership is not strictly required. Use a + /// `From::from` implementation for an API which strictly + /// consumes ownership. + /// + /// # Safety + /// + /// The `socket` passed in must: + /// - be a valid an open socket, + /// - be a socket that may be freed via [`closesocket`]. + /// + /// [`closesocket`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-closesocket + #[cfg_attr(staged_api, stable(feature = "from_raw_os", since = "1.1.0"))] + unsafe fn from_raw_socket(sock: RawSocket) -> Self; +} + +/// A trait to express the ability to consume an object and acquire ownership of +/// its raw `SOCKET`. +#[cfg_attr(staged_api, stable(feature = "into_raw_os", since = "1.4.0"))] +pub trait IntoRawSocket { + /// Consumes this object, returning the raw underlying socket. + /// + /// This function is typically used to **transfer ownership** of the underlying + /// socket to the caller. When used in this way, callers are then the unique + /// owners of the socket and must close it once it's no longer needed. + /// + /// However, transferring ownership is not strictly required. Use a + /// `Into::into` implementation for an API which strictly + /// transfers ownership. + #[cfg_attr(staged_api, stable(feature = "into_raw_os", since = "1.4.0"))] + fn into_raw_socket(self) -> RawSocket; +} diff --git a/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/socket.rs b/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/socket.rs new file mode 100644 index 000000000..bc637aa53 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/os/windows/io/socket.rs @@ -0,0 +1,199 @@ +//! The following is derived from Rust's +//! library/std/src/os/windows/io/socket.rs +//! at revision +//! 4f9b394c8a24803e57ba892fa00e539742ebafc0. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. + +use super::raw::*; +use crate::backend::c; +use crate::backend::fd::LibcFd as LibcSocket; +use core::fmt; +use core::marker::PhantomData; +use core::mem::forget; + +/// A borrowed socket. +/// +/// This has a lifetime parameter to tie it to the lifetime of something that +/// owns the socket. +/// +/// This uses `repr(transparent)` and has the representation of a host socket, +/// so it can be used in FFI in places where a socket is passed as an argument, +/// it is not captured or consumed, and it never has the value +/// `INVALID_SOCKET`. +/// +/// This type's `.to_owned()` implementation returns another `BorrowedSocket` +/// rather than an `OwnedSocket`. It just makes a trivial copy of the raw +/// socket, which is then borrowed under the same lifetime. +#[derive(Copy, Clone)] +#[repr(transparent)] +#[cfg_attr(staged_api, rustc_layout_scalar_valid_range_start(0))] +// This is -2, in two's complement. -1 is `INVALID_SOCKET`. +#[cfg_attr( + all(staged_api, target_pointer_width = "32"), + rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE) +)] +#[cfg_attr( + all(staged_api, target_pointer_width = "64"), + rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE) +)] +#[cfg_attr(staged_api, rustc_nonnull_optimization_guaranteed)] +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +pub struct BorrowedSocket<'socket> { + socket: RawSocket, + _phantom: PhantomData<&'socket OwnedSocket>, +} + +/// An owned socket. +/// +/// This closes the socket on drop. +/// +/// This uses `repr(transparent)` and has the representation of a host socket, +/// so it can be used in FFI in places where a socket is passed as a consumed +/// argument or returned as an owned value, and it never has the value +/// `INVALID_SOCKET`. +#[repr(transparent)] +#[cfg_attr(staged_api, rustc_layout_scalar_valid_range_start(0))] +// This is -2, in two's complement. -1 is `INVALID_SOCKET`. +#[cfg_attr( + all(staged_api, target_pointer_width = "32"), + rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE) +)] +#[cfg_attr( + all(staged_api, target_pointer_width = "64"), + rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE) +)] +#[cfg_attr(staged_api, rustc_nonnull_optimization_guaranteed)] +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +pub struct OwnedSocket { + socket: RawSocket, +} + +impl BorrowedSocket<'_> { + /// Return a `BorrowedSocket` holding the given raw socket. + /// + /// # Safety + /// + /// The resource pointed to by `raw` must remain open for the duration of + /// the returned `BorrowedSocket`, and it must not have the value + /// `INVALID_SOCKET`. + #[inline] + #[cfg_attr( + staged_api, + rustc_const_stable(feature = "io_safety", since = "1.63.0") + )] + #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] + pub const unsafe fn borrow_raw(socket: RawSocket) -> Self { + assert!(socket != c::INVALID_SOCKET as RawSocket); + Self { + socket, + _phantom: PhantomData, + } + } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl AsRawSocket for BorrowedSocket<'_> { + #[inline] + fn as_raw_socket(&self) -> RawSocket { + self.socket + } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl AsRawSocket for OwnedSocket { + #[inline] + fn as_raw_socket(&self) -> RawSocket { + self.socket + } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl IntoRawSocket for OwnedSocket { + #[inline] + fn into_raw_socket(self) -> RawSocket { + let socket = self.socket; + forget(self); + socket + } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl FromRawSocket for OwnedSocket { + #[inline] + unsafe fn from_raw_socket(socket: RawSocket) -> Self { + debug_assert_ne!(socket, c::INVALID_SOCKET as RawSocket); + Self { socket } + } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl Drop for OwnedSocket { + #[inline] + fn drop(&mut self) { + unsafe { + let _ = c::closesocket(self.socket as LibcSocket); + } + } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl fmt::Debug for BorrowedSocket<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("BorrowedSocket") + .field("socket", &self.socket) + .finish() + } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl fmt::Debug for OwnedSocket { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("OwnedSocket") + .field("socket", &self.socket) + .finish() + } +} + +/// A trait to borrow the socket from an underlying object. +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +pub trait AsSocket { + /// Borrows the socket. + #[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] + fn as_socket(&self) -> BorrowedSocket<'_>; +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl AsSocket for &T { + #[inline] + fn as_socket(&self) -> BorrowedSocket<'_> { + T::as_socket(self) + } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl AsSocket for &mut T { + #[inline] + fn as_socket(&self) -> BorrowedSocket<'_> { + T::as_socket(self) + } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl AsSocket for BorrowedSocket<'_> { + #[inline] + fn as_socket(&self) -> BorrowedSocket<'_> { + *self + } +} + +#[cfg_attr(staged_api, stable(feature = "io_safety", since = "1.63.0"))] +impl AsSocket for OwnedSocket { + #[inline] + fn as_socket(&self) -> BorrowedSocket<'_> { + // Safety: `OwnedSocket` and `BorrowedSocket` have the same validity + // invariants, and the `BorrowdSocket` is bounded by the lifetime + // of `&self`. + unsafe { BorrowedSocket::borrow_raw(self.as_raw_socket()) } + } +} diff --git a/vendor/rustix/src/maybe_polyfill/no_std/os/windows/mod.rs b/vendor/rustix/src/maybe_polyfill/no_std/os/windows/mod.rs new file mode 100644 index 000000000..02f389497 --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/no_std/os/windows/mod.rs @@ -0,0 +1,19 @@ +//! The following is derived from Rust's +//! library/std/src/os/windows/raw.rs, +//! library/std/src/os/windows/io/raw.rs and +//! library/std/src/os/windows/io/socket.rs +//! at revision +//! 4f9b394c8a24803e57ba892fa00e539742ebafc0. +//! +//! All code in this file is licensed MIT or Apache 2.0 at your option. + +mod raw { + #[cfg(target_pointer_width = "32")] + #[cfg_attr(staged_api, stable(feature = "raw_ext", since = "1.1.0"))] + pub type SOCKET = u32; + #[cfg(target_pointer_width = "64")] + #[cfg_attr(staged_api, stable(feature = "raw_ext", since = "1.1.0"))] + pub type SOCKET = u64; +} + +pub mod io; diff --git a/vendor/rustix/src/maybe_polyfill/std/mod.rs b/vendor/rustix/src/maybe_polyfill/std/mod.rs new file mode 100644 index 000000000..92b5cab5b --- /dev/null +++ b/vendor/rustix/src/maybe_polyfill/std/mod.rs @@ -0,0 +1,41 @@ +//! Imports from `std` that would be polyfilled for `no_std` builds (see `src/polyfill/no_std`). +//! +//! This implementation is used when `std` is available and just imports the necessary items from +//! `std`. For `no_std` builds, the file `src/polyfill/no_std` is used instead, which doesn't +//! depend on the standard library. + +#[cfg(not(windows))] +pub mod io { + pub use std::io::{IoSlice, IoSliceMut}; +} + +#[cfg(not(any(target_os = "redox", target_os = "wasi")))] +#[cfg(feature = "net")] +pub mod net { + pub use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; +} + +pub mod os { + pub mod fd { + // Change to use `std::os::fd` when MSRV becomes 1.66 or higher. + + #[cfg(unix)] + pub use std::os::unix::io::{ + AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd, + }; + #[cfg(target_os = "wasi")] + pub use std::os::wasi::io::{ + AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd, + }; + } + + #[cfg(windows)] + pub mod windows { + pub mod io { + pub use std::os::windows::io::{ + AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, + RawSocket, + }; + } + } +} diff --git a/vendor/rustix/src/mm/mmap.rs b/vendor/rustix/src/mm/mmap.rs index 8d4b7e23b..bec15f0ad 100644 --- a/vendor/rustix/src/mm/mmap.rs +++ b/vendor/rustix/src/mm/mmap.rs @@ -10,7 +10,7 @@ use crate::{backend, io}; use backend::fd::AsFd; use core::ffi::c_void; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use backend::mm::types::MlockFlags; #[cfg(any(target_os = "emscripten", target_os = "linux"))] pub use backend::mm::types::MremapFlags; @@ -270,7 +270,7 @@ pub unsafe fn mlock(ptr: *mut c_void, len: usize) -> io::Result<()> { /// /// [Linux]: https://man7.org/linux/man-pages/man2/mlock2.2.html /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Page-Lock-Functions.html#index-mlock2 -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] #[doc(alias = "mlock2")] pub unsafe fn mlock_with(ptr: *mut c_void, len: usize, flags: MlockFlags) -> io::Result<()> { diff --git a/vendor/rustix/src/mm/mod.rs b/vendor/rustix/src/mm/mod.rs index 5a439b34b..7505cac0a 100644 --- a/vendor/rustix/src/mm/mod.rs +++ b/vendor/rustix/src/mm/mod.rs @@ -4,12 +4,12 @@ mod madvise; mod mmap; mod msync; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] mod userfaultfd; #[cfg(not(target_os = "redox"))] pub use madvise::{madvise, Advice}; pub use mmap::*; pub use msync::{msync, MsyncFlags}; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use userfaultfd::{userfaultfd, UserfaultfdFlags}; diff --git a/vendor/rustix/src/net/addr.rs b/vendor/rustix/src/net/addr.rs deleted file mode 100644 index ca87298e9..000000000 --- a/vendor/rustix/src/net/addr.rs +++ /dev/null @@ -1,641 +0,0 @@ -//! The following is derived from Rust's -//! library/std/src/net/socket_addr.rs at revision -//! bd20fc1fd657b32f7aa1d70d8723f04c87f21606. -//! -//! All code in this file is licensed MIT or Apache 2.0 at your option. -//! -//! This defines `SocketAddr`, `SocketAddrV4`, and `SocketAddrV6` in a -//! platform-independent way. It is not the native representation. - -use crate::net::ip::{IpAddr, Ipv4Addr, Ipv6Addr}; -use core::cmp::Ordering; -use core::hash; - -/// An internet socket address, either IPv4 or IPv6. -/// -/// Internet socket addresses consist of an [IP address], a 16-bit port number, as well -/// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and -/// [`SocketAddrV6`]'s respective documentation for more details. -/// -/// The size of a `SocketAddr` instance may vary depending on the target operating -/// system. -/// -/// [IP address]: IpAddr -/// -/// # Examples -/// -/// ``` -/// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; -/// -/// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); -/// -/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket)); -/// assert_eq!(socket.port(), 8080); -/// assert_eq!(socket.is_ipv4(), true); -/// ``` -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] -pub enum SocketAddr { - /// An IPv4 socket address. - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - V4(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] SocketAddrV4), - /// An IPv6 socket address. - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - V6(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] SocketAddrV6), -} - -/// An IPv4 socket address. -/// -/// IPv4 socket addresses consist of an [`IPv4` address] and a 16-bit port number, as -/// stated in [IETF RFC 793]. -/// -/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses. -/// -/// The size of a `SocketAddrV4` struct may vary depending on the target operating -/// system. Do not assume that this type has the same memory layout as the underlying -/// system representation. -/// -/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793 -/// [`IPv4` address]: Ipv4Addr -/// -/// # Examples -/// -/// ``` -/// use std::net::{Ipv4Addr, SocketAddrV4}; -/// -/// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); -/// -/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket)); -/// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); -/// assert_eq!(socket.port(), 8080); -/// ``` -#[derive(Copy, Clone, Eq, PartialEq)] -#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] -pub struct SocketAddrV4 { - ip: Ipv4Addr, - port: u16, -} - -/// An IPv6 socket address. -/// -/// IPv6 socket addresses consist of an [`IPv6` address], a 16-bit port number, as well -/// as fields containing the traffic class, the flow label, and a scope identifier -/// (see [IETF RFC 2553, Section 3.3] for more details). -/// -/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses. -/// -/// The size of a `SocketAddrV6` struct may vary depending on the target operating -/// system. Do not assume that this type has the same memory layout as the underlying -/// system representation. -/// -/// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 -/// [`IPv6` address]: Ipv6Addr -/// -/// # Examples -/// -/// ``` -/// use std::net::{Ipv6Addr, SocketAddrV6}; -/// -/// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0); -/// -/// assert_eq!("[2001:db8::1]:8080".parse(), Ok(socket)); -/// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); -/// assert_eq!(socket.port(), 8080); -/// ``` -#[derive(Copy, Clone, Eq, PartialEq)] -#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] -pub struct SocketAddrV6 { - ip: Ipv6Addr, - port: u16, - flowinfo: u32, - scope_id: u32, -} - -impl SocketAddr { - /// Creates a new socket address from an [IP address] and a port number. - /// - /// [IP address]: IpAddr - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; - /// - /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); - /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); - /// assert_eq!(socket.port(), 8080); - /// ``` - #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] - #[must_use] - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_socketaddr", issue = "82485") - )] - pub const fn new(ip: IpAddr, port: u16) -> SocketAddr { - match ip { - IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)), - IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)), - } - } - - /// Returns the IP address associated with this socket address. - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; - /// - /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); - /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); - /// ``` - #[must_use] - #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_socketaddr", issue = "82485") - )] - pub const fn ip(&self) -> IpAddr { - match *self { - SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()), - SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()), - } - } - - /// Changes the IP address associated with this socket address. - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; - /// - /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); - /// socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); - /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); - /// ``` - #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] - pub fn set_ip(&mut self, new_ip: IpAddr) { - // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away. - match (self, new_ip) { - (&mut SocketAddr::V4(ref mut a), IpAddr::V4(new_ip)) => a.set_ip(new_ip), - (&mut SocketAddr::V6(ref mut a), IpAddr::V6(new_ip)) => a.set_ip(new_ip), - (self_, new_ip) => *self_ = Self::new(new_ip, self_.port()), - } - } - - /// Returns the port number associated with this socket address. - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; - /// - /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); - /// assert_eq!(socket.port(), 8080); - /// ``` - #[must_use] - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_socketaddr", issue = "82485") - )] - pub const fn port(&self) -> u16 { - match *self { - SocketAddr::V4(ref a) => a.port(), - SocketAddr::V6(ref a) => a.port(), - } - } - - /// Changes the port number associated with this socket address. - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; - /// - /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); - /// socket.set_port(1025); - /// assert_eq!(socket.port(), 1025); - /// ``` - #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] - pub fn set_port(&mut self, new_port: u16) { - match *self { - SocketAddr::V4(ref mut a) => a.set_port(new_port), - SocketAddr::V6(ref mut a) => a.set_port(new_port), - } - } - - /// Returns [`true`] if the [IP address] in this `SocketAddr` is an - /// [`IPv4` address], and [`false`] otherwise. - /// - /// [IP address]: IpAddr - /// [`IPv4` address]: IpAddr::V4 - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; - /// - /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); - /// assert_eq!(socket.is_ipv4(), true); - /// assert_eq!(socket.is_ipv6(), false); - /// ``` - #[must_use] - #[cfg_attr(staged_api, stable(feature = "sockaddr_checker", since = "1.16.0"))] - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_socketaddr", issue = "82485") - )] - pub const fn is_ipv4(&self) -> bool { - matches!(*self, SocketAddr::V4(_)) - } - - /// Returns [`true`] if the [IP address] in this `SocketAddr` is an - /// [`IPv6` address], and [`false`] otherwise. - /// - /// [IP address]: IpAddr - /// [`IPv6` address]: IpAddr::V6 - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv6Addr, SocketAddr}; - /// - /// let socket = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080); - /// assert_eq!(socket.is_ipv4(), false); - /// assert_eq!(socket.is_ipv6(), true); - /// ``` - #[must_use] - #[cfg_attr(staged_api, stable(feature = "sockaddr_checker", since = "1.16.0"))] - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_socketaddr", issue = "82485") - )] - pub const fn is_ipv6(&self) -> bool { - matches!(*self, SocketAddr::V6(_)) - } -} - -impl SocketAddrV4 { - /// Creates a new socket address from an [`IPv4` address] and a port number. - /// - /// [`IPv4` address]: Ipv4Addr - /// - /// # Examples - /// - /// ``` - /// use std::net::{SocketAddrV4, Ipv4Addr}; - /// - /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); - /// ``` - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - #[must_use] - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_socketaddr", issue = "82485") - )] - pub const fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 { - SocketAddrV4 { ip, port } - } - - /// Returns the IP address associated with this socket address. - /// - /// # Examples - /// - /// ``` - /// use std::net::{SocketAddrV4, Ipv4Addr}; - /// - /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); - /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); - /// ``` - #[must_use] - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_socketaddr", issue = "82485") - )] - pub const fn ip(&self) -> &Ipv4Addr { - &self.ip - } - - /// Changes the IP address associated with this socket address. - /// - /// # Examples - /// - /// ``` - /// use std::net::{SocketAddrV4, Ipv4Addr}; - /// - /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); - /// socket.set_ip(Ipv4Addr::new(192, 168, 0, 1)); - /// assert_eq!(socket.ip(), &Ipv4Addr::new(192, 168, 0, 1)); - /// ``` - #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] - pub fn set_ip(&mut self, new_ip: Ipv4Addr) { - self.ip = new_ip; - } - - /// Returns the port number associated with this socket address. - /// - /// # Examples - /// - /// ``` - /// use std::net::{SocketAddrV4, Ipv4Addr}; - /// - /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); - /// assert_eq!(socket.port(), 8080); - /// ``` - #[must_use] - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_socketaddr", issue = "82485") - )] - pub const fn port(&self) -> u16 { - self.port - } - - /// Changes the port number associated with this socket address. - /// - /// # Examples - /// - /// ``` - /// use std::net::{SocketAddrV4, Ipv4Addr}; - /// - /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); - /// socket.set_port(4242); - /// assert_eq!(socket.port(), 4242); - /// ``` - #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] - pub fn set_port(&mut self, new_port: u16) { - self.port = new_port; - } -} - -impl SocketAddrV6 { - /// Creates a new socket address from an [`IPv6` address], a 16-bit port number, - /// and the `flowinfo` and `scope_id` fields. - /// - /// For more information on the meaning and layout of the `flowinfo` and `scope_id` - /// parameters, see [IETF RFC 2553, Section 3.3]. - /// - /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 - /// [`IPv6` address]: Ipv6Addr - /// - /// # Examples - /// - /// ``` - /// use std::net::{SocketAddrV6, Ipv6Addr}; - /// - /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); - /// ``` - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - #[must_use] - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_socketaddr", issue = "82485") - )] - pub const fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 { - SocketAddrV6 { - ip, - port, - flowinfo, - scope_id, - } - } - - /// Returns the IP address associated with this socket address. - /// - /// # Examples - /// - /// ``` - /// use std::net::{SocketAddrV6, Ipv6Addr}; - /// - /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); - /// assert_eq!(socket.ip(), &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); - /// ``` - #[must_use] - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_socketaddr", issue = "82485") - )] - pub const fn ip(&self) -> &Ipv6Addr { - &self.ip - } - - /// Changes the IP address associated with this socket address. - /// - /// # Examples - /// - /// ``` - /// use std::net::{SocketAddrV6, Ipv6Addr}; - /// - /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); - /// socket.set_ip(Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0)); - /// assert_eq!(socket.ip(), &Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0)); - /// ``` - #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] - pub fn set_ip(&mut self, new_ip: Ipv6Addr) { - self.ip = new_ip; - } - - /// Returns the port number associated with this socket address. - /// - /// # Examples - /// - /// ``` - /// use std::net::{SocketAddrV6, Ipv6Addr}; - /// - /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); - /// assert_eq!(socket.port(), 8080); - /// ``` - #[must_use] - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_socketaddr", issue = "82485") - )] - pub const fn port(&self) -> u16 { - self.port - } - - /// Changes the port number associated with this socket address. - /// - /// # Examples - /// - /// ``` - /// use std::net::{SocketAddrV6, Ipv6Addr}; - /// - /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0); - /// socket.set_port(4242); - /// assert_eq!(socket.port(), 4242); - /// ``` - #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] - pub fn set_port(&mut self, new_port: u16) { - self.port = new_port; - } - - /// Returns the flow information associated with this address. - /// - /// This information corresponds to the `sin6_flowinfo` field in C's `netinet/in.h`, - /// as specified in [IETF RFC 2553, Section 3.3]. - /// It combines information about the flow label and the traffic class as specified - /// in [IETF RFC 2460], respectively [Section 6] and [Section 7]. - /// - /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 - /// [IETF RFC 2460]: https://tools.ietf.org/html/rfc2460 - /// [Section 6]: https://tools.ietf.org/html/rfc2460#section-6 - /// [Section 7]: https://tools.ietf.org/html/rfc2460#section-7 - /// - /// # Examples - /// - /// ``` - /// use std::net::{SocketAddrV6, Ipv6Addr}; - /// - /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0); - /// assert_eq!(socket.flowinfo(), 10); - /// ``` - #[must_use] - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_socketaddr", issue = "82485") - )] - pub const fn flowinfo(&self) -> u32 { - self.flowinfo - } - - /// Changes the flow information associated with this socket address. - /// - /// See [`SocketAddrV6::flowinfo`]'s documentation for more details. - /// - /// # Examples - /// - /// ``` - /// use std::net::{SocketAddrV6, Ipv6Addr}; - /// - /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0); - /// socket.set_flowinfo(56); - /// assert_eq!(socket.flowinfo(), 56); - /// ``` - #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] - pub fn set_flowinfo(&mut self, new_flowinfo: u32) { - self.flowinfo = new_flowinfo; - } - - /// Returns the scope ID associated with this address. - /// - /// This information corresponds to the `sin6_scope_id` field in C's `netinet/in.h`, - /// as specified in [IETF RFC 2553, Section 3.3]. - /// - /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3 - /// - /// # Examples - /// - /// ``` - /// use std::net::{SocketAddrV6, Ipv6Addr}; - /// - /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78); - /// assert_eq!(socket.scope_id(), 78); - /// ``` - #[must_use] - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_socketaddr", issue = "82485") - )] - pub const fn scope_id(&self) -> u32 { - self.scope_id - } - - /// Changes the scope ID associated with this socket address. - /// - /// See [`SocketAddrV6::scope_id`]'s documentation for more details. - /// - /// # Examples - /// - /// ``` - /// use std::net::{SocketAddrV6, Ipv6Addr}; - /// - /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78); - /// socket.set_scope_id(42); - /// assert_eq!(socket.scope_id(), 42); - /// ``` - #[cfg_attr(staged_api, stable(feature = "sockaddr_setters", since = "1.9.0"))] - pub fn set_scope_id(&mut self, new_scope_id: u32) { - self.scope_id = new_scope_id; - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_from_ip", since = "1.16.0"))] -impl From for SocketAddr { - /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`]. - fn from(sock4: SocketAddrV4) -> SocketAddr { - SocketAddr::V4(sock4) - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_from_ip", since = "1.16.0"))] -impl From for SocketAddr { - /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`]. - fn from(sock6: SocketAddrV6) -> SocketAddr { - SocketAddr::V6(sock6) - } -} - -#[cfg_attr(staged_api, stable(feature = "addr_from_into_ip", since = "1.17.0"))] -impl> From<(I, u16)> for SocketAddr { - /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`]. - /// - /// This conversion creates a [`SocketAddr::V4`] for an [`IpAddr::V4`] - /// and creates a [`SocketAddr::V6`] for an [`IpAddr::V6`]. - /// - /// `u16` is treated as port of the newly created [`SocketAddr`]. - fn from(pieces: (I, u16)) -> SocketAddr { - SocketAddr::new(pieces.0.into(), pieces.1) - } -} - -#[cfg_attr(staged_api, stable(feature = "socketaddr_ordering", since = "1.45.0"))] -impl PartialOrd for SocketAddrV4 { - fn partial_cmp(&self, other: &SocketAddrV4) -> Option { - Some(self.cmp(other)) - } -} - -#[cfg_attr(staged_api, stable(feature = "socketaddr_ordering", since = "1.45.0"))] -impl PartialOrd for SocketAddrV6 { - fn partial_cmp(&self, other: &SocketAddrV6) -> Option { - Some(self.cmp(other)) - } -} - -#[cfg_attr(staged_api, stable(feature = "socketaddr_ordering", since = "1.45.0"))] -impl Ord for SocketAddrV4 { - fn cmp(&self, other: &SocketAddrV4) -> Ordering { - self.ip() - .cmp(other.ip()) - .then(self.port().cmp(&other.port())) - } -} - -#[cfg_attr(staged_api, stable(feature = "socketaddr_ordering", since = "1.45.0"))] -impl Ord for SocketAddrV6 { - fn cmp(&self, other: &SocketAddrV6) -> Ordering { - self.ip() - .cmp(other.ip()) - .then(self.port().cmp(&other.port())) - } -} - -#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] -impl hash::Hash for SocketAddrV4 { - fn hash(&self, s: &mut H) { - (self.port, self.ip).hash(s) - } -} -#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] -impl hash::Hash for SocketAddrV6 { - fn hash(&self, s: &mut H) { - (self.port, &self.ip, self.flowinfo, self.scope_id).hash(s) - } -} diff --git a/vendor/rustix/src/net/ip.rs b/vendor/rustix/src/net/ip.rs deleted file mode 100644 index ffa5302e3..000000000 --- a/vendor/rustix/src/net/ip.rs +++ /dev/null @@ -1,2068 +0,0 @@ -//! The following is derived from Rust's -//! library/std/src/net/ip_addr.rs at revision -//! bd20fc1fd657b32f7aa1d70d8723f04c87f21606. -//! -//! All code in this file is licensed MIT or Apache 2.0 at your option. -//! -//! This defines `IpAddr`, `Ipv4Addr`, and `Ipv6Addr`. Ideally, these should be -//! defined in `core`. See [RFC 2832]. -//! -//! [RFC 2832]: https://github.com/rust-lang/rfcs/pull/2832 - -#![allow(unsafe_code)] - -use core::cmp::Ordering; -use core::mem::transmute; - -/// An IP address, either IPv4 or IPv6. -/// -/// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their -/// respective documentation for more details. -/// -/// # Examples -/// -/// ``` -/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; -/// -/// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); -/// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); -/// -/// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4)); -/// assert_eq!("::1".parse(), Ok(localhost_v6)); -/// -/// assert_eq!(localhost_v4.is_ipv6(), false); -/// assert_eq!(localhost_v4.is_ipv4(), true); -/// ``` -#[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] -#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] -pub enum IpAddr { - /// An IPv4 address. - #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] - V4(#[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] Ipv4Addr), - /// An IPv6 address. - #[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] - V6(#[cfg_attr(staged_api, stable(feature = "ip_addr", since = "1.7.0"))] Ipv6Addr), -} - -/// An IPv4 address. -/// -/// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791]. -/// They are usually represented as four octets. -/// -/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses. -/// -/// [IETF RFC 791]: https://tools.ietf.org/html/rfc791 -/// -/// # Textual representation -/// -/// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal -/// notation, divided by `.` (this is called "dot-decimal notation"). -/// Notably, octal numbers (which are indicated with a leading `0`) and hexadecimal numbers (which -/// are indicated with a leading `0x`) are not allowed per [IETF RFC 6943]. -/// -/// [IETF RFC 6943]: https://tools.ietf.org/html/rfc6943#section-3.1.1 -/// [`FromStr`]: core::str::FromStr -/// -/// # Examples -/// -/// ``` -/// use std::net::Ipv4Addr; -/// -/// let localhost = Ipv4Addr::new(127, 0, 0, 1); -/// assert_eq!("127.0.0.1".parse(), Ok(localhost)); -/// assert_eq!(localhost.is_loopback(), true); -/// assert!("012.004.002.000".parse::().is_err()); // all octets are in octal -/// assert!("0000000.0.0.0".parse::().is_err()); // first octet is a zero in octal -/// assert!("0xcb.0x0.0x71.0x00".parse::().is_err()); // all octets are in hex -/// ``` -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] -pub struct Ipv4Addr { - octets: [u8; 4], -} - -/// An IPv6 address. -/// -/// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291]. -/// They are usually represented as eight 16-bit segments. -/// -/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 -/// -/// # Embedding IPv4 Addresses -/// -/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses. -/// -/// To assist in the transition from IPv4 to IPv6 two types of IPv6 addresses that embed an IPv4 address were defined: -/// IPv4-compatible and IPv4-mapped addresses. Of these IPv4-compatible addresses have been officially deprecated. -/// -/// Both types of addresses are not assigned any special meaning by this implementation, -/// other than what the relevant standards prescribe. This means that an address like `::ffff:127.0.0.1`, -/// while representing an IPv4 loopback address, is not itself an IPv6 loopback address; only `::1` is. -/// To handle these so called "IPv4-in-IPv6" addresses, they have to first be converted to their canonical IPv4 address. -/// -/// ### IPv4-Compatible IPv6 Addresses -/// -/// IPv4-compatible IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.1], and have been officially deprecated. -/// The RFC describes the format of an "IPv4-Compatible IPv6 address" as follows: -/// -/// ```text -/// | 80 bits | 16 | 32 bits | -/// +--------------------------------------+--------------------------+ -/// |0000..............................0000|0000| IPv4 address | -/// +--------------------------------------+----+---------------------+ -/// ``` -/// So `::a.b.c.d` would be an IPv4-compatible IPv6 address representing the IPv4 address `a.b.c.d`. -/// -/// To convert from an IPv4 address to an IPv4-compatible IPv6 address, use [`Ipv4Addr::to_ipv6_compatible`]. -/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-compatible IPv6 address to the canonical IPv4 address. -/// -/// [IETF RFC 4291 Section 2.5.5.1]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.1 -/// -/// ### IPv4-Mapped IPv6 Addresses -/// -/// IPv4-mapped IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.2]. -/// The RFC describes the format of an "IPv4-Mapped IPv6 address" as follows: -/// -/// ```text -/// | 80 bits | 16 | 32 bits | -/// +--------------------------------------+--------------------------+ -/// |0000..............................0000|FFFF| IPv4 address | -/// +--------------------------------------+----+---------------------+ -/// ``` -/// So `::ffff:a.b.c.d` would be an IPv4-mapped IPv6 address representing the IPv4 address `a.b.c.d`. -/// -/// To convert from an IPv4 address to an IPv4-mapped IPv6 address, use [`Ipv4Addr::to_ipv6_mapped`]. -/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-mapped IPv6 address to the canonical IPv4 address. -/// Note that this will also convert the IPv6 loopback address `::1` to `0.0.0.1`. Use -/// [`Ipv6Addr::to_ipv4_mapped`] to avoid this. -/// -/// [IETF RFC 4291 Section 2.5.5.2]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2 -/// -/// # Textual representation -/// -/// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent -/// an IPv6 address in text, but in general, each segments is written in hexadecimal -/// notation, and segments are separated by `:`. For more information, see -/// [IETF RFC 5952]. -/// -/// [`FromStr`]: core::str::FromStr -/// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952 -/// -/// # Examples -/// -/// ``` -/// use std::net::Ipv6Addr; -/// -/// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); -/// assert_eq!("::1".parse(), Ok(localhost)); -/// assert_eq!(localhost.is_loopback(), true); -/// ``` -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] -pub struct Ipv6Addr { - octets: [u8; 16], -} - -/// Scope of an [IPv6 multicast address] as defined in [IETF RFC 7346 section 2]. -/// -/// # Stability Guarantees -/// -/// Not all possible values for a multicast scope have been assigned. -/// Future RFCs may introduce new scopes, which will be added as variants to this enum; -/// because of this the enum is marked as `#[non_exhaustive]`. -/// -/// # Examples -/// ``` -/// #![feature(ip)] -/// -/// use std::net::Ipv6Addr; -/// use std::net::Ipv6MulticastScope::*; -/// -/// // An IPv6 multicast address with global scope (`ff0e::`). -/// let address = Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0); -/// -/// // Will print "Global scope". -/// match address.multicast_scope() { -/// Some(InterfaceLocal) => println!("Interface-Local scope"), -/// Some(LinkLocal) => println!("Link-Local scope"), -/// Some(RealmLocal) => println!("Realm-Local scope"), -/// Some(AdminLocal) => println!("Admin-Local scope"), -/// Some(SiteLocal) => println!("Site-Local scope"), -/// Some(OrganizationLocal) => println!("Organization-Local scope"), -/// Some(Global) => println!("Global scope"), -/// Some(_) => println!("Unknown scope"), -/// None => println!("Not a multicast address!") -/// } -/// -/// ``` -/// -/// [IPv6 multicast address]: Ipv6Addr -/// [IETF RFC 7346 section 2]: https://tools.ietf.org/html/rfc7346#section-2 -#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)] -#[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] -#[non_exhaustive] -pub enum Ipv6MulticastScope { - /// Interface-Local scope. - InterfaceLocal, - /// Link-Local scope. - LinkLocal, - /// Realm-Local scope. - RealmLocal, - /// Admin-Local scope. - AdminLocal, - /// Site-Local scope. - SiteLocal, - /// Organization-Local scope. - OrganizationLocal, - /// Global scope. - Global, -} - -impl IpAddr { - /// Returns [`true`] for the special 'unspecified' address. - /// - /// See the documentation for [`Ipv4Addr::is_unspecified()`] and - /// [`Ipv6Addr::is_unspecified()`] for more details. - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; - /// - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true); - /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(feature = "ip_shared", since = "1.12.0"))] - #[must_use] - #[inline] - pub const fn is_unspecified(&self) -> bool { - match self { - IpAddr::V4(ip) => ip.is_unspecified(), - IpAddr::V6(ip) => ip.is_unspecified(), - } - } - - /// Returns [`true`] if this is a loopback address. - /// - /// See the documentation for [`Ipv4Addr::is_loopback()`] and - /// [`Ipv6Addr::is_loopback()`] for more details. - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; - /// - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true); - /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(feature = "ip_shared", since = "1.12.0"))] - #[must_use] - #[inline] - pub const fn is_loopback(&self) -> bool { - match self { - IpAddr::V4(ip) => ip.is_loopback(), - IpAddr::V6(ip) => ip.is_loopback(), - } - } - - /// Returns [`true`] if the address appears to be globally routable. - /// - /// See the documentation for [`Ipv4Addr::is_global()`] and - /// [`Ipv6Addr::is_global()`] for more details. - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// - /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; - /// - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true); - /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_ip", issue = "76205") - )] - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - #[must_use] - #[inline] - pub const fn is_global(&self) -> bool { - match self { - IpAddr::V4(ip) => ip.is_global(), - IpAddr::V6(ip) => ip.is_global(), - } - } - - /// Returns [`true`] if this is a multicast address. - /// - /// See the documentation for [`Ipv4Addr::is_multicast()`] and - /// [`Ipv6Addr::is_multicast()`] for more details. - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; - /// - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true); - /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(feature = "ip_shared", since = "1.12.0"))] - #[must_use] - #[inline] - pub const fn is_multicast(&self) -> bool { - match self { - IpAddr::V4(ip) => ip.is_multicast(), - IpAddr::V6(ip) => ip.is_multicast(), - } - } - - /// Returns [`true`] if this address is in a range designated for documentation. - /// - /// See the documentation for [`Ipv4Addr::is_documentation()`] and - /// [`Ipv6Addr::is_documentation()`] for more details. - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// - /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; - /// - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true); - /// assert_eq!( - /// IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_documentation(), - /// true - /// ); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_ip", issue = "76205") - )] - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - #[must_use] - #[inline] - pub const fn is_documentation(&self) -> bool { - match self { - IpAddr::V4(ip) => ip.is_documentation(), - IpAddr::V6(ip) => ip.is_documentation(), - } - } - - /// Returns [`true`] if this address is in a range designated for benchmarking. - /// - /// See the documentation for [`Ipv4Addr::is_benchmarking()`] and - /// [`Ipv6Addr::is_benchmarking()`] for more details. - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// - /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; - /// - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(198, 19, 255, 255)).is_benchmarking(), true); - /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0)).is_benchmarking(), true); - /// ``` - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - #[must_use] - #[inline] - pub const fn is_benchmarking(&self) -> bool { - match self { - IpAddr::V4(ip) => ip.is_benchmarking(), - IpAddr::V6(ip) => ip.is_benchmarking(), - } - } - - /// Returns [`true`] if this address is an [`IPv4` address], and [`false`] - /// otherwise. - /// - /// [`IPv4` address]: IpAddr::V4 - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; - /// - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true); - /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(feature = "ipaddr_checker", since = "1.16.0"))] - #[must_use] - #[inline] - pub const fn is_ipv4(&self) -> bool { - matches!(self, IpAddr::V4(_)) - } - - /// Returns [`true`] if this address is an [`IPv6` address], and [`false`] - /// otherwise. - /// - /// [`IPv6` address]: IpAddr::V6 - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; - /// - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false); - /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(feature = "ipaddr_checker", since = "1.16.0"))] - #[must_use] - #[inline] - pub const fn is_ipv6(&self) -> bool { - matches!(self, IpAddr::V6(_)) - } - - /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped IPv6 addresses, otherwise it - /// return `self` as-is. - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; - /// - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).to_canonical().is_loopback(), true); - /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).is_loopback(), false); - /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).to_canonical().is_loopback(), true); - /// ``` - #[inline] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_ip", issue = "76205") - )] - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - pub const fn to_canonical(&self) -> IpAddr { - match self { - &v4 @ IpAddr::V4(_) => v4, - IpAddr::V6(v6) => v6.to_canonical(), - } - } -} - -impl Ipv4Addr { - /// Creates a new IPv4 address from four eight-bit octets. - /// - /// The result will represent the IP address `a`.`b`.`c`.`d`. - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv4Addr; - /// - /// let addr = Ipv4Addr::new(127, 0, 0, 1); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_32", since = "1.32.0") - )] - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - #[must_use] - #[inline] - pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { - Ipv4Addr { - octets: [a, b, c, d], - } - } - - /// An IPv4 address with the address pointing to localhost: `127.0.0.1` - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv4Addr; - /// - /// let addr = Ipv4Addr::LOCALHOST; - /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1)); - /// ``` - #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))] - pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1); - - /// An IPv4 address representing an unspecified address: `0.0.0.0` - /// - /// This corresponds to the constant `INADDR_ANY` in other languages. - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv4Addr; - /// - /// let addr = Ipv4Addr::UNSPECIFIED; - /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0)); - /// ``` - #[doc(alias = "INADDR_ANY")] - #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))] - pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0); - - /// An IPv4 address representing the broadcast address: `255.255.255.255` - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv4Addr; - /// - /// let addr = Ipv4Addr::BROADCAST; - /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255)); - /// ``` - #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))] - pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255); - - /// Returns the four eight-bit integers that make up this address. - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv4Addr; - /// - /// let addr = Ipv4Addr::new(127, 0, 0, 1); - /// assert_eq!(addr.octets(), [127, 0, 0, 1]); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - #[must_use] - #[inline] - pub const fn octets(&self) -> [u8; 4] { - self.octets - } - - /// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`). - /// - /// This property is defined in _UNIX Network Programming, Second Edition_, - /// W. Richard Stevens, p. 891; see also [ip7]. - /// - /// [ip7]: https://man7.org/linux/man-pages/man7/ip.7.html - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv4Addr; - /// - /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true); - /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_32", since = "1.32.0") - )] - #[cfg_attr(staged_api, stable(feature = "ip_shared", since = "1.12.0"))] - #[must_use] - #[inline] - pub const fn is_unspecified(&self) -> bool { - u32::from_be_bytes(self.octets) == 0 - } - - /// Returns [`true`] if this is a loopback address (`127.0.0.0/8`). - /// - /// This property is defined by [IETF RFC 1122]. - /// - /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122 - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv4Addr; - /// - /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true); - /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] - #[must_use] - #[inline] - pub const fn is_loopback(&self) -> bool { - self.octets()[0] == 127 - } - - /// Returns [`true`] if this is a private address. - /// - /// The private address ranges are defined in [IETF RFC 1918] and include: - /// - /// - `10.0.0.0/8` - /// - `172.16.0.0/12` - /// - `192.168.0.0/16` - /// - /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918 - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv4Addr; - /// - /// assert_eq!(Ipv4Addr::new(10, 0, 0, 1).is_private(), true); - /// assert_eq!(Ipv4Addr::new(10, 10, 10, 10).is_private(), true); - /// assert_eq!(Ipv4Addr::new(172, 16, 10, 10).is_private(), true); - /// assert_eq!(Ipv4Addr::new(172, 29, 45, 14).is_private(), true); - /// assert_eq!(Ipv4Addr::new(172, 32, 0, 2).is_private(), false); - /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true); - /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] - #[must_use] - #[inline] - pub const fn is_private(&self) -> bool { - match self.octets() { - [10, ..] => true, - [172, b, ..] if b >= 16 && b <= 31 => true, - [192, 168, ..] => true, - _ => false, - } - } - - /// Returns [`true`] if the address is link-local (`169.254.0.0/16`). - /// - /// This property is defined by [IETF RFC 3927]. - /// - /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927 - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv4Addr; - /// - /// assert_eq!(Ipv4Addr::new(169, 254, 0, 0).is_link_local(), true); - /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true); - /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] - #[must_use] - #[inline] - pub const fn is_link_local(&self) -> bool { - matches!(self.octets(), [169, 254, ..]) - } - - /// Returns [`true`] if the address appears to be globally reachable - /// as specified by the [IANA IPv4 Special-Purpose Address Registry]. - /// Whether or not an address is practically reachable will depend on your network configuration. - /// - /// Most IPv4 addresses are globally reachable; - /// unless they are specifically defined as *not* globally reachable. - /// - /// Non-exhaustive list of notable addresses that are not globally reachable: - /// - /// - The [unspecified address] ([`is_unspecified`](Ipv4Addr::is_unspecified)) - /// - Addresses reserved for private use ([`is_private`](Ipv4Addr::is_private)) - /// - Addresses in the shared address space ([`is_shared`](Ipv4Addr::is_shared)) - /// - Loopback addresses ([`is_loopback`](Ipv4Addr::is_loopback)) - /// - Link-local addresses ([`is_link_local`](Ipv4Addr::is_link_local)) - /// - Addresses reserved for documentation ([`is_documentation`](Ipv4Addr::is_documentation)) - /// - Addresses reserved for benchmarking ([`is_benchmarking`](Ipv4Addr::is_benchmarking)) - /// - Reserved addresses ([`is_reserved`](Ipv4Addr::is_reserved)) - /// - The [broadcast address] ([`is_broadcast`](Ipv4Addr::is_broadcast)) - /// - /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv4 Special-Purpose Address Registry]. - /// - /// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml - /// [unspecified address]: Ipv4Addr::UNSPECIFIED - /// [broadcast address]: Ipv4Addr::BROADCAST - - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// - /// use std::net::Ipv4Addr; - /// - /// // Most IPv4 addresses are globally reachable: - /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true); - /// - /// // However some addresses have been assigned a special meaning - /// // that makes them not globally reachable. Some examples are: - /// - /// // The unspecified address (`0.0.0.0`) - /// assert_eq!(Ipv4Addr::UNSPECIFIED.is_global(), false); - /// - /// // Addresses reserved for private use (`10.0.0.0/8`, `172.16.0.0/12`, 192.168.0.0/16) - /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false); - /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false); - /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false); - /// - /// // Addresses in the shared address space (`100.64.0.0/10`) - /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false); - /// - /// // The loopback addresses (`127.0.0.0/8`) - /// assert_eq!(Ipv4Addr::LOCALHOST.is_global(), false); - /// - /// // Link-local addresses (`169.254.0.0/16`) - /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false); - /// - /// // Addresses reserved for documentation (`192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`) - /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false); - /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false); - /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false); - /// - /// // Addresses reserved for benchmarking (`198.18.0.0/15`) - /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false); - /// - /// // Reserved addresses (`240.0.0.0/4`) - /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false); - /// - /// // The broadcast address (`255.255.255.255`) - /// assert_eq!(Ipv4Addr::BROADCAST.is_global(), false); - /// - /// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry. - /// ``` - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_ipv4", issue = "76205") - )] - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - #[must_use] - #[inline] - pub const fn is_global(&self) -> bool { - !(self.octets()[0] == 0 // "This network" - || self.is_private() - || self.is_shared() - || self.is_loopback() - || self.is_link_local() - // addresses reserved for future protocols (`192.0.0.0/24`) - ||(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0) - || self.is_documentation() - || self.is_benchmarking() - || self.is_reserved() - || self.is_broadcast()) - } - - /// Returns [`true`] if this address is part of the Shared Address Space defined in - /// [IETF RFC 6598] (`100.64.0.0/10`). - /// - /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598 - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// use std::net::Ipv4Addr; - /// - /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true); - /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true); - /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_ipv4", issue = "76205") - )] - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - #[must_use] - #[inline] - pub const fn is_shared(&self) -> bool { - self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000) - } - - /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for - /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0` - /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`. - /// - /// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544 - /// [errata 423]: https://www.rfc-editor.org/errata/eid423 - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// use std::net::Ipv4Addr; - /// - /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false); - /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true); - /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true); - /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_ipv4", issue = "76205") - )] - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - #[must_use] - #[inline] - pub const fn is_benchmarking(&self) -> bool { - self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18 - } - - /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112] - /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the - /// broadcast address `255.255.255.255`, but this implementation explicitly excludes it, since - /// it is obviously not reserved for future use. - /// - /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112 - /// - /// # Warning - /// - /// As IANA assigns new addresses, this method will be - /// updated. This may result in non-reserved addresses being - /// treated as reserved in code that relies on an outdated version - /// of this method. - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// use std::net::Ipv4Addr; - /// - /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true); - /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true); - /// - /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false); - /// // The broadcast address is not considered as reserved for future use by this implementation - /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_ipv4", issue = "76205") - )] - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - #[must_use] - #[inline] - pub const fn is_reserved(&self) -> bool { - self.octets()[0] & 240 == 240 && !self.is_broadcast() - } - - /// Returns [`true`] if this is a multicast address (`224.0.0.0/4`). - /// - /// Multicast addresses have a most significant octet between `224` and `239`, - /// and is defined by [IETF RFC 5771]. - /// - /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771 - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv4Addr; - /// - /// assert_eq!(Ipv4Addr::new(224, 254, 0, 0).is_multicast(), true); - /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true); - /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] - #[must_use] - #[inline] - pub const fn is_multicast(&self) -> bool { - self.octets()[0] >= 224 && self.octets()[0] <= 239 - } - - /// Returns [`true`] if this is a broadcast address (`255.255.255.255`). - /// - /// A broadcast address has all octets set to `255` as defined in [IETF RFC 919]. - /// - /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919 - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv4Addr; - /// - /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true); - /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] - #[must_use] - #[inline] - pub const fn is_broadcast(&self) -> bool { - u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets()) - } - - /// Returns [`true`] if this address is in a range designated for documentation. - /// - /// This is defined in [IETF RFC 5737]: - /// - /// - `192.0.2.0/24` (TEST-NET-1) - /// - `198.51.100.0/24` (TEST-NET-2) - /// - `203.0.113.0/24` (TEST-NET-3) - /// - /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737 - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv4Addr; - /// - /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_documentation(), true); - /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_documentation(), true); - /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true); - /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] - #[must_use] - #[inline] - pub const fn is_documentation(&self) -> bool { - matches!( - self.octets(), - [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _] - ) - } - - /// Converts this address to an [IPv4-compatible] [`IPv6` address]. - /// - /// `a.b.c.d` becomes `::a.b.c.d` - /// - /// Note that IPv4-compatible addresses have been officially deprecated. - /// If you don't explicitly need an IPv4-compatible address for legacy reasons, consider using `to_ipv6_mapped` instead. - /// - /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses - /// [`IPv6` address]: Ipv6Addr - /// - /// # Examples - /// - /// ``` - /// use std::net::{Ipv4Addr, Ipv6Addr}; - /// - /// assert_eq!( - /// Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(), - /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x2ff) - /// ); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn to_ipv6_compatible(&self) -> Ipv6Addr { - let [a, b, c, d] = self.octets(); - Ipv6Addr { - octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d], - } - } - - /// Converts this address to an [IPv4-mapped] [`IPv6` address]. - /// - /// `a.b.c.d` becomes `::ffff:a.b.c.d` - /// - /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses - /// [`IPv6` address]: Ipv6Addr - /// - /// # Examples - /// - /// ``` - /// use std::net::{Ipv4Addr, Ipv6Addr}; - /// - /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(), - /// Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff)); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn to_ipv6_mapped(&self) -> Ipv6Addr { - let [a, b, c, d] = self.octets(); - Ipv6Addr { - octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d], - } - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_from_ip", since = "1.16.0"))] -impl From for IpAddr { - /// Copies this address to a new `IpAddr::V4`. - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv4Addr}; - /// - /// let addr = Ipv4Addr::new(127, 0, 0, 1); - /// - /// assert_eq!( - /// IpAddr::V4(addr), - /// IpAddr::from(addr) - /// ) - /// ``` - #[inline] - fn from(ipv4: Ipv4Addr) -> IpAddr { - IpAddr::V4(ipv4) - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_from_ip", since = "1.16.0"))] -impl From for IpAddr { - /// Copies this address to a new `IpAddr::V6`. - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv6Addr}; - /// - /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); - /// - /// assert_eq!( - /// IpAddr::V6(addr), - /// IpAddr::from(addr) - /// ); - /// ``` - #[inline] - fn from(ipv6: Ipv6Addr) -> IpAddr { - IpAddr::V6(ipv6) - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] -impl PartialEq for IpAddr { - #[inline] - fn eq(&self, other: &Ipv4Addr) -> bool { - match self { - IpAddr::V4(v4) => v4 == other, - IpAddr::V6(_) => false, - } - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] -impl PartialEq for Ipv4Addr { - #[inline] - fn eq(&self, other: &IpAddr) -> bool { - match other { - IpAddr::V4(v4) => self == v4, - IpAddr::V6(_) => false, - } - } -} - -#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] -impl PartialOrd for Ipv4Addr { - #[inline] - fn partial_cmp(&self, other: &Ipv4Addr) -> Option { - Some(self.cmp(other)) - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] -impl PartialOrd for IpAddr { - #[inline] - fn partial_cmp(&self, other: &Ipv4Addr) -> Option { - match self { - IpAddr::V4(v4) => v4.partial_cmp(other), - IpAddr::V6(_) => Some(Ordering::Greater), - } - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] -impl PartialOrd for Ipv4Addr { - #[inline] - fn partial_cmp(&self, other: &IpAddr) -> Option { - match other { - IpAddr::V4(v4) => self.partial_cmp(v4), - IpAddr::V6(_) => Some(Ordering::Less), - } - } -} - -#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] -impl Ord for Ipv4Addr { - #[inline] - fn cmp(&self, other: &Ipv4Addr) -> Ordering { - self.octets.cmp(&other.octets) - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_u32", since = "1.1.0"))] -impl From for u32 { - /// Converts an `Ipv4Addr` into a host byte order `u32`. - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv4Addr; - /// - /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78); - /// assert_eq!(0x12345678, u32::from(addr)); - /// ``` - #[inline] - fn from(ip: Ipv4Addr) -> u32 { - u32::from_be_bytes(ip.octets) - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_u32", since = "1.1.0"))] -impl From for Ipv4Addr { - /// Converts a host byte order `u32` into an `Ipv4Addr`. - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv4Addr; - /// - /// let addr = Ipv4Addr::from(0x12345678); - /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr); - /// ``` - #[inline] - fn from(ip: u32) -> Ipv4Addr { - Ipv4Addr { - octets: ip.to_be_bytes(), - } - } -} - -#[cfg_attr(staged_api, stable(feature = "from_slice_v4", since = "1.9.0"))] -impl From<[u8; 4]> for Ipv4Addr { - /// Creates an `Ipv4Addr` from a four element byte array. - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv4Addr; - /// - /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]); - /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr); - /// ``` - #[inline] - fn from(octets: [u8; 4]) -> Ipv4Addr { - Ipv4Addr { octets } - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_from_slice", since = "1.17.0"))] -impl From<[u8; 4]> for IpAddr { - /// Creates an `IpAddr::V4` from a four element byte array. - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv4Addr}; - /// - /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]); - /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr); - /// ``` - #[inline] - fn from(octets: [u8; 4]) -> IpAddr { - IpAddr::V4(Ipv4Addr::from(octets)) - } -} - -impl Ipv6Addr { - /// Creates a new IPv6 address from eight 16-bit segments. - /// - /// The result will represent the IP address `a:b:c:d:e:f:g:h`. - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv6Addr; - /// - /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_32", since = "1.32.0") - )] - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - #[allow(clippy::too_many_arguments)] - #[must_use] - #[inline] - pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { - let addr16 = [ - a.to_be(), - b.to_be(), - c.to_be(), - d.to_be(), - e.to_be(), - f.to_be(), - g.to_be(), - h.to_be(), - ]; - Ipv6Addr { - // All elements in `addr16` are big endian. - // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`. - octets: unsafe { transmute::<_, [u8; 16]>(addr16) }, - } - } - - /// An IPv6 address representing localhost: `::1`. - /// - /// This corresponds to constant `IN6ADDR_LOOPBACK_INIT` or `in6addr_loopback` in other - /// languages. - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv6Addr; - /// - /// let addr = Ipv6Addr::LOCALHOST; - /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); - /// ``` - #[doc(alias = "IN6ADDR_LOOPBACK_INIT")] - #[doc(alias = "in6addr_loopback")] - #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))] - pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); - - /// An IPv6 address representing the unspecified address: `::` - /// - /// This corresponds to constant `IN6ADDR_ANY_INIT` or `in6addr_any` in other languages. - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv6Addr; - /// - /// let addr = Ipv6Addr::UNSPECIFIED; - /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); - /// ``` - #[doc(alias = "IN6ADDR_ANY_INIT")] - #[doc(alias = "in6addr_any")] - #[cfg_attr(staged_api, stable(feature = "ip_constructors", since = "1.30.0"))] - pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0); - - /// Returns the eight 16-bit segments that make up this address. - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv6Addr; - /// - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(), - /// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - #[must_use] - #[inline] - pub const fn segments(&self) -> [u16; 8] { - // All elements in `self.octets` must be big endian. - // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`. - let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.octets) }; - // We want native endian u16 - [ - u16::from_be(a), - u16::from_be(b), - u16::from_be(c), - u16::from_be(d), - u16::from_be(e), - u16::from_be(f), - u16::from_be(g), - u16::from_be(h), - ] - } - - /// Returns [`true`] for the special 'unspecified' address (`::`). - /// - /// This property is defined in [IETF RFC 4291]. - /// - /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv6Addr; - /// - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] - #[must_use] - #[inline] - pub const fn is_unspecified(&self) -> bool { - u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets()) - } - - /// Returns [`true`] if this is the [loopback address] (`::1`), - /// as defined in [IETF RFC 4291 section 2.5.3]. - /// - /// Contrary to IPv4, in IPv6 there is only one loopback address. - /// - /// [loopback address]: Ipv6Addr::LOCALHOST - /// [IETF RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3 - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv6Addr; - /// - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] - #[must_use] - #[inline] - pub const fn is_loopback(&self) -> bool { - u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets()) - } - - /// Returns [`true`] if the address appears to be globally reachable - /// as specified by the [IANA IPv6 Special-Purpose Address Registry]. - /// Whether or not an address is practically reachable will depend on your network configuration. - /// - /// Most IPv6 addresses are globally reachable; - /// unless they are specifically defined as *not* globally reachable. - /// - /// Non-exhaustive list of notable addresses that are not globally reachable: - /// - The [unspecified address] ([`is_unspecified`](Ipv6Addr::is_unspecified)) - /// - The [loopback address] ([`is_loopback`](Ipv6Addr::is_loopback)) - /// - IPv4-mapped addresses - /// - Addresses reserved for benchmarking - /// - Addresses reserved for documentation ([`is_documentation`](Ipv6Addr::is_documentation)) - /// - Unique local addresses ([`is_unique_local`](Ipv6Addr::is_unique_local)) - /// - Unicast addresses with link-local scope ([`is_unicast_link_local`](Ipv6Addr::is_unicast_link_local)) - /// - /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv6 Special-Purpose Address Registry]. - /// - /// Note that an address having global scope is not the same as being globally reachable, - /// and there is no direct relation between the two concepts: There exist addresses with global scope - /// that are not globally reachable (for example unique local addresses), - /// and addresses that are globally reachable without having global scope - /// (multicast addresses with non-global scope). - /// - /// [IANA IPv6 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml - /// [unspecified address]: Ipv6Addr::UNSPECIFIED - /// [loopback address]: Ipv6Addr::LOCALHOST - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// - /// use std::net::Ipv6Addr; - /// - /// // Most IPv6 addresses are globally reachable: - /// assert_eq!(Ipv6Addr::new(0x26, 0, 0x1c9, 0, 0, 0xafc8, 0x10, 0x1).is_global(), true); - /// - /// // However some addresses have been assigned a special meaning - /// // that makes them not globally reachable. Some examples are: - /// - /// // The unspecified address (`::`) - /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_global(), false); - /// - /// // The loopback address (`::1`) - /// assert_eq!(Ipv6Addr::LOCALHOST.is_global(), false); - /// - /// // IPv4-mapped addresses (`::ffff:0:0/96`) - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), false); - /// - /// // Addresses reserved for benchmarking (`2001:2::/48`) - /// assert_eq!(Ipv6Addr::new(0x2001, 2, 0, 0, 0, 0, 0, 1,).is_global(), false); - /// - /// // Addresses reserved for documentation (`2001:db8::/32`) - /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1).is_global(), false); - /// - /// // Unique local addresses (`fc00::/7`) - /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 1).is_global(), false); - /// - /// // Unicast addresses with link-local scope (`fe80::/10`) - /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 1).is_global(), false); - /// - /// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry. - /// ``` - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_ipv6", issue = "76205") - )] - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - #[must_use] - #[inline] - pub const fn is_global(&self) -> bool { - !(self.is_unspecified() - || self.is_loopback() - // IPv4-mapped Address (`::ffff:0:0/96`) - || matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _]) - // IPv4-IPv6 Translat. (`64:ff9b:1::/48`) - || matches!(self.segments(), [0x64, 0xff9b, 1, _, _, _, _, _]) - // Discard-Only Address Block (`100::/64`) - || matches!(self.segments(), [0x100, 0, 0, 0, _, _, _, _]) - // IETF Protocol Assignments (`2001::/23`) - || (matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200) - && !( - // Port Control Protocol Anycast (`2001:1::1`) - u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001 - // Traversal Using Relays around NAT Anycast (`2001:1::2`) - || u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002 - // AMT (`2001:3::/32`) - || matches!(self.segments(), [0x2001, 3, _, _, _, _, _, _]) - // AS112-v6 (`2001:4:112::/48`) - || matches!(self.segments(), [0x2001, 4, 0x112, _, _, _, _, _]) - // ORCHIDv2 (`2001:20::/28`) - || matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x2F) - )) - || self.is_documentation() - || self.is_unique_local() - || self.is_unicast_link_local()) - } - - /// Returns [`true`] if this is a unique local address (`fc00::/7`). - /// - /// This property is defined in [IETF RFC 4193]. - /// - /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193 - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// - /// use std::net::Ipv6Addr; - /// - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false); - /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_ipv6", issue = "76205") - )] - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - #[must_use] - #[inline] - pub const fn is_unique_local(&self) -> bool { - (self.segments()[0] & 0xfe00) == 0xfc00 - } - - /// Returns [`true`] if this is a unicast address, as defined by [IETF RFC 4291]. - /// Any address that is not a [multicast address] (`ff00::/8`) is unicast. - /// - /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 - /// [multicast address]: Ipv6Addr::is_multicast - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// - /// use std::net::Ipv6Addr; - /// - /// // The unspecified and loopback addresses are unicast. - /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_unicast(), true); - /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast(), true); - /// - /// // Any address that is not a multicast address (`ff00::/8`) is unicast. - /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast(), true); - /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_unicast(), false); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_ipv6", issue = "76205") - )] - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - #[must_use] - #[inline] - pub const fn is_unicast(&self) -> bool { - !self.is_multicast() - } - - /// Returns `true` if the address is a unicast address with link-local scope, - /// as defined in [RFC 4291]. - /// - /// A unicast address has link-local scope if it has the prefix `fe80::/10`, as per [RFC 4291 section 2.4]. - /// Note that this encompasses more addresses than those defined in [RFC 4291 section 2.5.6], - /// which describes "Link-Local IPv6 Unicast Addresses" as having the following stricter format: - /// - /// ```text - /// | 10 bits | 54 bits | 64 bits | - /// +----------+-------------------------+----------------------------+ - /// |1111111010| 0 | interface ID | - /// +----------+-------------------------+----------------------------+ - /// ``` - /// So while currently the only addresses with link-local scope an application will encounter are all in `fe80::/64`, - /// this might change in the future with the publication of new standards. More addresses in `fe80::/10` could be allocated, - /// and those addresses will have link-local scope. - /// - /// Also note that while [RFC 4291 section 2.5.3] mentions about the [loopback address] (`::1`) that "it is treated as having Link-Local scope", - /// this does not mean that the loopback address actually has link-local scope and this method will return `false` on it. - /// - /// [RFC 4291]: https://tools.ietf.org/html/rfc4291 - /// [RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4 - /// [RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3 - /// [RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6 - /// [loopback address]: Ipv6Addr::LOCALHOST - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// - /// use std::net::Ipv6Addr; - /// - /// // The loopback address (`::1`) does not actually have link-local scope. - /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast_link_local(), false); - /// - /// // Only addresses in `fe80::/10` have link-local scope. - /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), false); - /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true); - /// - /// // Addresses outside the stricter `fe80::/64` also have link-local scope. - /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0).is_unicast_link_local(), true); - /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_ipv6", issue = "76205") - )] - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - #[must_use] - #[inline] - pub const fn is_unicast_link_local(&self) -> bool { - (self.segments()[0] & 0xffc0) == 0xfe80 - } - - /// Returns [`true`] if this is an address reserved for documentation - /// (`2001:db8::/32`). - /// - /// This property is defined in [IETF RFC 3849]. - /// - /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849 - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// - /// use std::net::Ipv6Addr; - /// - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false); - /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_ipv6", issue = "76205") - )] - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - #[must_use] - #[inline] - pub const fn is_documentation(&self) -> bool { - (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8) - } - - /// Returns [`true`] if this is an address reserved for benchmarking (`2001:2::/48`). - /// - /// This property is defined in [IETF RFC 5180], where it is mistakenly specified as covering the range `2001:0200::/48`. - /// This is corrected in [IETF RFC Errata 1752] to `2001:0002::/48`. - /// - /// [IETF RFC 5180]: https://tools.ietf.org/html/rfc5180 - /// [IETF RFC Errata 1752]: https://www.rfc-editor.org/errata_search.php?eid=1752 - /// - /// ``` - /// #![feature(ip)] - /// - /// use std::net::Ipv6Addr; - /// - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc613, 0x0).is_benchmarking(), false); - /// assert_eq!(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0).is_benchmarking(), true); - /// ``` - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - #[must_use] - #[inline] - pub const fn is_benchmarking(&self) -> bool { - (self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) && (self.segments()[2] == 0) - } - - /// Returns [`true`] if the address is a globally routable unicast address. - /// - /// The following return false: - /// - /// - the loopback address - /// - the link-local addresses - /// - unique local addresses - /// - the unspecified address - /// - the address range reserved for documentation - /// - /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7] - /// - /// ```no_rust - /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer - /// be supported in new implementations (i.e., new implementations must treat this prefix as - /// Global Unicast). - /// ``` - /// - /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7 - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// - /// use std::net::Ipv6Addr; - /// - /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_ipv6", issue = "76205") - )] - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - #[must_use] - #[inline] - pub const fn is_unicast_global(&self) -> bool { - self.is_unicast() - && !self.is_loopback() - && !self.is_unicast_link_local() - && !self.is_unique_local() - && !self.is_unspecified() - && !self.is_documentation() - && !self.is_benchmarking() - } - - /// Returns the address's multicast scope if the address is multicast. - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// - /// use std::net::{Ipv6Addr, Ipv6MulticastScope}; - /// - /// assert_eq!( - /// Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(), - /// Some(Ipv6MulticastScope::Global) - /// ); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_ipv6", issue = "76205") - )] - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - #[must_use] - #[inline] - pub const fn multicast_scope(&self) -> Option { - if self.is_multicast() { - match self.segments()[0] & 0x000f { - 1 => Some(Ipv6MulticastScope::InterfaceLocal), - 2 => Some(Ipv6MulticastScope::LinkLocal), - 3 => Some(Ipv6MulticastScope::RealmLocal), - 4 => Some(Ipv6MulticastScope::AdminLocal), - 5 => Some(Ipv6MulticastScope::SiteLocal), - 8 => Some(Ipv6MulticastScope::OrganizationLocal), - 14 => Some(Ipv6MulticastScope::Global), - _ => None, - } - } else { - None - } - } - - /// Returns [`true`] if this is a multicast address (`ff00::/8`). - /// - /// This property is defined by [IETF RFC 4291]. - /// - /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv6Addr; - /// - /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(since = "1.7.0", feature = "ip_17"))] - #[must_use] - #[inline] - pub const fn is_multicast(&self) -> bool { - (self.segments()[0] & 0xff00) == 0xff00 - } - - /// Converts this address to an [`IPv4` address] if it's an [IPv4-mapped] address, - /// as defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`]. - /// - /// `::ffff:a.b.c.d` becomes `a.b.c.d`. - /// All addresses *not* starting with `::ffff` will return `None`. - /// - /// [`IPv4` address]: Ipv4Addr - /// [IPv4-mapped]: Ipv6Addr - /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2 - /// - /// # Examples - /// - /// ``` - /// use std::net::{Ipv4Addr, Ipv6Addr}; - /// - /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(), - /// Some(Ipv4Addr::new(192, 10, 2, 255))); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_ipv6", issue = "76205") - )] - #[cfg_attr(staged_api, stable(feature = "ipv6_to_ipv4_mapped", since = "1.63.0"))] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn to_ipv4_mapped(&self) -> Option { - match self.octets() { - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => { - Some(Ipv4Addr::new(a, b, c, d)) - } - _ => None, - } - } - - /// Converts this address to an [`IPv4` address] if it is either - /// an [IPv4-compatible] address as defined in [IETF RFC 4291 section 2.5.5.1], - /// or an [IPv4-mapped] address as defined in [IETF RFC 4291 section 2.5.5.2], - /// otherwise returns [`None`]. - /// - /// Note that this will return an [`IPv4` address] for the IPv6 loopback address `::1`. Use - /// [`Ipv6Addr::to_ipv4_mapped`] to avoid this. - /// - /// `::a.b.c.d` and `::ffff:a.b.c.d` become `a.b.c.d`. `::1` becomes `0.0.0.1`. - /// All addresses *not* starting with either all zeroes or `::ffff` will return `None`. - /// - /// [`IPv4` address]: Ipv4Addr - /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses - /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses - /// [IETF RFC 4291 section 2.5.5.1]: https://tools.ietf.org/html/rfc4291#section-2.5.5.1 - /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2 - /// - /// # Examples - /// - /// ``` - /// use std::net::{Ipv4Addr, Ipv6Addr}; - /// - /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(), - /// Some(Ipv4Addr::new(192, 10, 2, 255))); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(), - /// Some(Ipv4Addr::new(0, 0, 0, 1))); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_50", since = "1.50.0") - )] - #[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn to_ipv4(&self) -> Option { - if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() { - let [a, b] = ab.to_be_bytes(); - let [c, d] = cd.to_be_bytes(); - Some(Ipv4Addr::new(a, b, c, d)) - } else { - None - } - } - - /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped addresses, otherwise it - /// returns self wrapped in an `IpAddr::V6`. - /// - /// # Examples - /// - /// ``` - /// #![feature(ip)] - /// use std::net::Ipv6Addr; - /// - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false); - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).to_canonical().is_loopback(), true); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_unstable(feature = "const_ipv6", issue = "76205") - )] - #[cfg_attr(staged_api, unstable(feature = "ip", issue = "27709"))] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn to_canonical(&self) -> IpAddr { - if let Some(mapped) = self.to_ipv4_mapped() { - return IpAddr::V4(mapped); - } - IpAddr::V6(*self) - } - - /// Returns the sixteen eight-bit integers the IPv6 address consists of. - /// - /// ``` - /// use std::net::Ipv6Addr; - /// - /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(), - /// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); - /// ``` - #[cfg_attr( - staged_api, - rustc_const_stable(feature = "const_ip_32", since = "1.32.0") - )] - #[cfg_attr(staged_api, stable(feature = "ipv6_to_octets", since = "1.12.0"))] - #[must_use] - #[inline] - pub const fn octets(&self) -> [u8; 16] { - self.octets - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] -impl PartialEq for Ipv6Addr { - #[inline] - fn eq(&self, other: &IpAddr) -> bool { - match other { - IpAddr::V4(_) => false, - IpAddr::V6(v6) => self == v6, - } - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] -impl PartialEq for IpAddr { - #[inline] - fn eq(&self, other: &Ipv6Addr) -> bool { - match self { - IpAddr::V4(_) => false, - IpAddr::V6(v6) => v6 == other, - } - } -} - -#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] -impl PartialOrd for Ipv6Addr { - #[inline] - fn partial_cmp(&self, other: &Ipv6Addr) -> Option { - Some(self.cmp(other)) - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] -impl PartialOrd for IpAddr { - #[inline] - fn partial_cmp(&self, other: &Ipv6Addr) -> Option { - match self { - IpAddr::V4(_) => Some(Ordering::Less), - IpAddr::V6(v6) => v6.partial_cmp(other), - } - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_cmp", since = "1.16.0"))] -impl PartialOrd for Ipv6Addr { - #[inline] - fn partial_cmp(&self, other: &IpAddr) -> Option { - match other { - IpAddr::V4(_) => Some(Ordering::Greater), - IpAddr::V6(v6) => self.partial_cmp(v6), - } - } -} - -#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] -impl Ord for Ipv6Addr { - #[inline] - fn cmp(&self, other: &Ipv6Addr) -> Ordering { - self.segments().cmp(&other.segments()) - } -} - -#[cfg_attr(staged_api, stable(feature = "i128", since = "1.26.0"))] -impl From for u128 { - /// Convert an `Ipv6Addr` into a host byte order `u128`. - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv6Addr; - /// - /// let addr = Ipv6Addr::new( - /// 0x1020, 0x3040, 0x5060, 0x7080, - /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D, - /// ); - /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr)); - /// ``` - #[inline] - fn from(ip: Ipv6Addr) -> u128 { - u128::from_be_bytes(ip.octets) - } -} -#[cfg_attr(staged_api, stable(feature = "i128", since = "1.26.0"))] -impl From for Ipv6Addr { - /// Convert a host byte order `u128` into an `Ipv6Addr`. - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv6Addr; - /// - /// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128); - /// assert_eq!( - /// Ipv6Addr::new( - /// 0x1020, 0x3040, 0x5060, 0x7080, - /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D, - /// ), - /// addr); - /// ``` - #[inline] - fn from(ip: u128) -> Ipv6Addr { - Ipv6Addr::from(ip.to_be_bytes()) - } -} - -#[cfg_attr(staged_api, stable(feature = "ipv6_from_octets", since = "1.9.0"))] -impl From<[u8; 16]> for Ipv6Addr { - /// Creates an `Ipv6Addr` from a sixteen element byte array. - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv6Addr; - /// - /// let addr = Ipv6Addr::from([ - /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8, - /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8, - /// ]); - /// assert_eq!( - /// Ipv6Addr::new( - /// 0x1918, 0x1716, - /// 0x1514, 0x1312, - /// 0x1110, 0x0f0e, - /// 0x0d0c, 0x0b0a - /// ), - /// addr - /// ); - /// ``` - #[inline] - fn from(octets: [u8; 16]) -> Ipv6Addr { - Ipv6Addr { octets } - } -} - -#[cfg_attr(staged_api, stable(feature = "ipv6_from_segments", since = "1.16.0"))] -impl From<[u16; 8]> for Ipv6Addr { - /// Creates an `Ipv6Addr` from an eight element 16-bit array. - /// - /// # Examples - /// - /// ``` - /// use std::net::Ipv6Addr; - /// - /// let addr = Ipv6Addr::from([ - /// 525u16, 524u16, 523u16, 522u16, - /// 521u16, 520u16, 519u16, 518u16, - /// ]); - /// assert_eq!( - /// Ipv6Addr::new( - /// 0x20d, 0x20c, - /// 0x20b, 0x20a, - /// 0x209, 0x208, - /// 0x207, 0x206 - /// ), - /// addr - /// ); - /// ``` - #[inline] - fn from(segments: [u16; 8]) -> Ipv6Addr { - let [a, b, c, d, e, f, g, h] = segments; - Ipv6Addr::new(a, b, c, d, e, f, g, h) - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_from_slice", since = "1.17.0"))] -impl From<[u8; 16]> for IpAddr { - /// Creates an `IpAddr::V6` from a sixteen element byte array. - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv6Addr}; - /// - /// let addr = IpAddr::from([ - /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8, - /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8, - /// ]); - /// assert_eq!( - /// IpAddr::V6(Ipv6Addr::new( - /// 0x1918, 0x1716, - /// 0x1514, 0x1312, - /// 0x1110, 0x0f0e, - /// 0x0d0c, 0x0b0a - /// )), - /// addr - /// ); - /// ``` - #[inline] - fn from(octets: [u8; 16]) -> IpAddr { - IpAddr::V6(Ipv6Addr::from(octets)) - } -} - -#[cfg_attr(staged_api, stable(feature = "ip_from_slice", since = "1.17.0"))] -impl From<[u16; 8]> for IpAddr { - /// Creates an `IpAddr::V6` from an eight element 16-bit array. - /// - /// # Examples - /// - /// ``` - /// use std::net::{IpAddr, Ipv6Addr}; - /// - /// let addr = IpAddr::from([ - /// 525u16, 524u16, 523u16, 522u16, - /// 521u16, 520u16, 519u16, 518u16, - /// ]); - /// assert_eq!( - /// IpAddr::V6(Ipv6Addr::new( - /// 0x20d, 0x20c, - /// 0x20b, 0x20a, - /// 0x209, 0x208, - /// 0x207, 0x206 - /// )), - /// addr - /// ); - /// ``` - #[inline] - fn from(segments: [u16; 8]) -> IpAddr { - IpAddr::V6(Ipv6Addr::from(segments)) - } -} diff --git a/vendor/rustix/src/net/mod.rs b/vendor/rustix/src/net/mod.rs index 4a3419737..73ae2f089 100644 --- a/vendor/rustix/src/net/mod.rs +++ b/vendor/rustix/src/net/mod.rs @@ -7,36 +7,25 @@ //! [`wsa_startup`]: https://docs.rs/rustix/*/x86_64-pc-windows-msvc/rustix/net/fn.wsa_startup.html //! [`wsa_cleanup`]: https://docs.rs/rustix/*/x86_64-pc-windows-msvc/rustix/net/fn.wsa_cleanup.html -#[cfg(not(feature = "std"))] -mod addr; -#[cfg(not(feature = "std"))] -mod ip; mod send_recv; mod socket; mod socket_addr_any; #[cfg(not(any(windows, target_os = "wasi")))] mod socketpair; +mod types; #[cfg(windows)] mod wsa; pub mod sockopt; +pub use crate::maybe_polyfill::net::{ + IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, +}; pub use send_recv::*; pub use socket::*; pub use socket_addr_any::{SocketAddrAny, SocketAddrStorage}; #[cfg(not(any(windows, target_os = "wasi")))] pub use socketpair::socketpair; -#[cfg(feature = "std")] -pub use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; +pub use types::*; #[cfg(windows)] pub use wsa::{wsa_cleanup, wsa_startup}; -#[cfg(not(feature = "std"))] -pub use { - addr::{SocketAddr, SocketAddrV4, SocketAddrV6}, - ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}, -}; -#[cfg(unix)] -pub use { - send_recv::sendto_unix, - socket::{bind_unix, connect_unix, SocketAddrUnix}, -}; diff --git a/vendor/rustix/src/net/send_recv.rs b/vendor/rustix/src/net/send_recv.rs deleted file mode 100644 index 439711727..000000000 --- a/vendor/rustix/src/net/send_recv.rs +++ /dev/null @@ -1,322 +0,0 @@ -//! `recv` and `send`, and variants. - -#[cfg(unix)] -use crate::net::SocketAddrUnix; -use crate::net::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6}; -use crate::{backend, io}; -use backend::fd::{AsFd, BorrowedFd}; - -pub use backend::net::send_recv::{RecvFlags, SendFlags}; - -/// `recv(fd, buf, flags)`—Reads data from a socket. -/// -/// # References -/// - [Beej's Guide to Network Programming] -/// - [POSIX] -/// - [Linux] -/// - [Apple] -/// - [Winsock2] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendrecv -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html -/// [Linux]: https://man7.org/linux/man-pages/man2/recv.2.html -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recv.2.html -/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recv -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=recv&sektion=2 -/// [NetBSD]: https://man.netbsd.org/recv.2 -/// [OpenBSD]: https://man.openbsd.org/recv.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=recv§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/recv -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Receiving-Data.html -#[inline] -pub fn recv(fd: Fd, buf: &mut [u8], flags: RecvFlags) -> io::Result { - backend::net::syscalls::recv(fd.as_fd(), buf, flags) -} - -/// `send(fd, buf, flags)`—Writes data to a socket. -/// -/// # References -/// - [Beej's Guide to Network Programming] -/// - [POSIX] -/// - [Linux] -/// - [Apple] -/// - [Winsock2] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendrecv -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html -/// [Linux]: https://man7.org/linux/man-pages/man2/send.2.html -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/send.2.html -/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=send&sektion=2 -/// [NetBSD]: https://man.netbsd.org/send.2 -/// [OpenBSD]: https://man.openbsd.org/send.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=send§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/send -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Data.html -#[inline] -pub fn send(fd: Fd, buf: &[u8], flags: SendFlags) -> io::Result { - backend::net::syscalls::send(fd.as_fd(), buf, flags) -} - -/// `recvfrom(fd, buf, flags, addr, len)`—Reads data from a socket and -/// returns the sender address. -/// -/// # References -/// - [Beej's Guide to Network Programming] -/// - [POSIX] -/// - [Linux] -/// - [Apple] -/// - [Winsock2] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html -/// [Linux]: https://man7.org/linux/man-pages/man2/recvfrom.2.html -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recvfrom.2.html -/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recvfrom -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=recvfrom&sektion=2 -/// [NetBSD]: https://man.netbsd.org/recvfrom.2 -/// [OpenBSD]: https://man.openbsd.org/recvfrom.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=recvfrom§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/recvfrom -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Receiving-Datagrams.html -#[inline] -pub fn recvfrom( - fd: Fd, - buf: &mut [u8], - flags: RecvFlags, -) -> io::Result<(usize, Option)> { - backend::net::syscalls::recvfrom(fd.as_fd(), buf, flags) -} - -/// `sendto(fd, buf, flags, addr)`—Writes data to a socket to a specific IP -/// address. -/// -/// # References -/// - [Beej's Guide to Network Programming] -/// - [POSIX] -/// - [Linux] -/// - [Apple] -/// - [Winsock2] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html -/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html -/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2 -/// [NetBSD]: https://man.netbsd.org/sendto.2 -/// [OpenBSD]: https://man.openbsd.org/sendto.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/sendto -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html -pub fn sendto( - fd: Fd, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddr, -) -> io::Result { - _sendto(fd.as_fd(), buf, flags, addr) -} - -fn _sendto( - fd: BorrowedFd<'_>, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddr, -) -> io::Result { - match addr { - SocketAddr::V4(v4) => backend::net::syscalls::sendto_v4(fd, buf, flags, v4), - SocketAddr::V6(v6) => backend::net::syscalls::sendto_v6(fd, buf, flags, v6), - } -} - -/// `sendto(fd, buf, flags, addr)`—Writes data to a socket to a specific -/// address. -/// -/// # References -/// - [Beej's Guide to Network Programming] -/// - [POSIX] -/// - [Linux] -/// - [Apple] -/// - [Winsock2] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html -/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html -/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2 -/// [NetBSD]: https://man.netbsd.org/sendto.2 -/// [OpenBSD]: https://man.openbsd.org/sendto.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/sendto -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html -pub fn sendto_any( - fd: Fd, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrAny, -) -> io::Result { - _sendto_any(fd.as_fd(), buf, flags, addr) -} - -fn _sendto_any( - fd: BorrowedFd<'_>, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrAny, -) -> io::Result { - match addr { - SocketAddrAny::V4(v4) => backend::net::syscalls::sendto_v4(fd, buf, flags, v4), - SocketAddrAny::V6(v6) => backend::net::syscalls::sendto_v6(fd, buf, flags, v6), - #[cfg(unix)] - SocketAddrAny::Unix(unix) => backend::net::syscalls::sendto_unix(fd, buf, flags, unix), - } -} - -/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_in))`—Writes data to -/// a socket to a specific IPv4 address. -/// -/// # References -/// - [Beej's Guide to Network Programming] -/// - [POSIX] -/// - [Linux] -/// - [Apple] -/// - [Winsock2] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html -/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html -/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2 -/// [NetBSD]: https://man.netbsd.org/sendto.2 -/// [OpenBSD]: https://man.openbsd.org/sendto.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/sendto -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html -#[inline] -#[doc(alias = "sendto")] -pub fn sendto_v4( - fd: Fd, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrV4, -) -> io::Result { - backend::net::syscalls::sendto_v4(fd.as_fd(), buf, flags, addr) -} - -/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_in6))`—Writes data -/// to a socket to a specific IPv6 address. -/// -/// # References -/// - [Beej's Guide to Network Programming] -/// - [POSIX] -/// - [Linux] -/// - [Apple] -/// - [Winsock2] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html -/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html -/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2 -/// [NetBSD]: https://man.netbsd.org/sendto.2 -/// [OpenBSD]: https://man.openbsd.org/sendto.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/sendto -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html -#[inline] -#[doc(alias = "sendto")] -pub fn sendto_v6( - fd: Fd, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrV6, -) -> io::Result { - backend::net::syscalls::sendto_v6(fd.as_fd(), buf, flags, addr) -} - -/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_un))`—Writes data to -/// a socket to a specific Unix-domain socket address. -/// -/// # References -/// - [Beej's Guide to Network Programming] -/// - [POSIX] -/// - [Linux] -/// - [Apple] -/// - [Winsock2] -/// - [FreeBSD] -/// - [NetBSD] -/// - [OpenBSD] -/// - [DragonFly BSD] -/// - [illumos] -/// - [glibc] -/// -/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html -/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html -/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html -/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto -/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2 -/// [NetBSD]: https://man.netbsd.org/sendto.2 -/// [OpenBSD]: https://man.openbsd.org/sendto.2 -/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto§ion=2 -/// [illumos]: https://illumos.org/man/3SOCKET/sendto -/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html -#[cfg(unix)] -#[inline] -#[doc(alias = "sendto")] -pub fn sendto_unix( - fd: Fd, - buf: &[u8], - flags: SendFlags, - addr: &SocketAddrUnix, -) -> io::Result { - backend::net::syscalls::sendto_unix(fd.as_fd(), buf, flags, addr) -} - -// TODO: `recvmsg`, `sendmsg` diff --git a/vendor/rustix/src/net/send_recv/mod.rs b/vendor/rustix/src/net/send_recv/mod.rs new file mode 100644 index 000000000..2d55c7f94 --- /dev/null +++ b/vendor/rustix/src/net/send_recv/mod.rs @@ -0,0 +1,326 @@ +//! `recv`, `send`, and variants. + +#[cfg(unix)] +use crate::net::SocketAddrUnix; +use crate::net::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6}; +use crate::{backend, io}; +use backend::fd::{AsFd, BorrowedFd}; + +pub use backend::net::send_recv::{RecvFlags, SendFlags}; + +#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))] +mod msg; + +#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))] +pub use msg::*; + +/// `recv(fd, buf, flags)`—Reads data from a socket. +/// +/// # References +/// - [Beej's Guide to Network Programming] +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [Winsock2] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendrecv +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html +/// [Linux]: https://man7.org/linux/man-pages/man2/recv.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recv.2.html +/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recv +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=recv&sektion=2 +/// [NetBSD]: https://man.netbsd.org/recv.2 +/// [OpenBSD]: https://man.openbsd.org/recv.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=recv§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/recv +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Receiving-Data.html +#[inline] +pub fn recv(fd: Fd, buf: &mut [u8], flags: RecvFlags) -> io::Result { + backend::net::syscalls::recv(fd.as_fd(), buf, flags) +} + +/// `send(fd, buf, flags)`—Writes data to a socket. +/// +/// # References +/// - [Beej's Guide to Network Programming] +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [Winsock2] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendrecv +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html +/// [Linux]: https://man7.org/linux/man-pages/man2/send.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/send.2.html +/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=send&sektion=2 +/// [NetBSD]: https://man.netbsd.org/send.2 +/// [OpenBSD]: https://man.openbsd.org/send.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=send§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/send +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Data.html +#[inline] +pub fn send(fd: Fd, buf: &[u8], flags: SendFlags) -> io::Result { + backend::net::syscalls::send(fd.as_fd(), buf, flags) +} + +/// `recvfrom(fd, buf, flags, addr, len)`—Reads data from a socket and +/// returns the sender address. +/// +/// # References +/// - [Beej's Guide to Network Programming] +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [Winsock2] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html +/// [Linux]: https://man7.org/linux/man-pages/man2/recvfrom.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recvfrom.2.html +/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recvfrom +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=recvfrom&sektion=2 +/// [NetBSD]: https://man.netbsd.org/recvfrom.2 +/// [OpenBSD]: https://man.openbsd.org/recvfrom.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=recvfrom§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/recvfrom +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Receiving-Datagrams.html +#[inline] +pub fn recvfrom( + fd: Fd, + buf: &mut [u8], + flags: RecvFlags, +) -> io::Result<(usize, Option)> { + backend::net::syscalls::recvfrom(fd.as_fd(), buf, flags) +} + +/// `sendto(fd, buf, flags, addr)`—Writes data to a socket to a specific IP +/// address. +/// +/// # References +/// - [Beej's Guide to Network Programming] +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [Winsock2] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html +/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendto.2 +/// [OpenBSD]: https://man.openbsd.org/sendto.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendto +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html +pub fn sendto( + fd: Fd, + buf: &[u8], + flags: SendFlags, + addr: &SocketAddr, +) -> io::Result { + _sendto(fd.as_fd(), buf, flags, addr) +} + +fn _sendto( + fd: BorrowedFd<'_>, + buf: &[u8], + flags: SendFlags, + addr: &SocketAddr, +) -> io::Result { + match addr { + SocketAddr::V4(v4) => backend::net::syscalls::sendto_v4(fd, buf, flags, v4), + SocketAddr::V6(v6) => backend::net::syscalls::sendto_v6(fd, buf, flags, v6), + } +} + +/// `sendto(fd, buf, flags, addr)`—Writes data to a socket to a specific +/// address. +/// +/// # References +/// - [Beej's Guide to Network Programming] +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [Winsock2] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html +/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendto.2 +/// [OpenBSD]: https://man.openbsd.org/sendto.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendto +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html +pub fn sendto_any( + fd: Fd, + buf: &[u8], + flags: SendFlags, + addr: &SocketAddrAny, +) -> io::Result { + _sendto_any(fd.as_fd(), buf, flags, addr) +} + +fn _sendto_any( + fd: BorrowedFd<'_>, + buf: &[u8], + flags: SendFlags, + addr: &SocketAddrAny, +) -> io::Result { + match addr { + SocketAddrAny::V4(v4) => backend::net::syscalls::sendto_v4(fd, buf, flags, v4), + SocketAddrAny::V6(v6) => backend::net::syscalls::sendto_v6(fd, buf, flags, v6), + #[cfg(unix)] + SocketAddrAny::Unix(unix) => backend::net::syscalls::sendto_unix(fd, buf, flags, unix), + } +} + +/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_in))`—Writes data to +/// a socket to a specific IPv4 address. +/// +/// # References +/// - [Beej's Guide to Network Programming] +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [Winsock2] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html +/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendto.2 +/// [OpenBSD]: https://man.openbsd.org/sendto.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendto +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html +#[inline] +#[doc(alias = "sendto")] +pub fn sendto_v4( + fd: Fd, + buf: &[u8], + flags: SendFlags, + addr: &SocketAddrV4, +) -> io::Result { + backend::net::syscalls::sendto_v4(fd.as_fd(), buf, flags, addr) +} + +/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_in6))`—Writes data +/// to a socket to a specific IPv6 address. +/// +/// # References +/// - [Beej's Guide to Network Programming] +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [Winsock2] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html +/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendto.2 +/// [OpenBSD]: https://man.openbsd.org/sendto.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendto +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html +#[inline] +#[doc(alias = "sendto")] +pub fn sendto_v6( + fd: Fd, + buf: &[u8], + flags: SendFlags, + addr: &SocketAddrV6, +) -> io::Result { + backend::net::syscalls::sendto_v6(fd.as_fd(), buf, flags, addr) +} + +/// `sendto(fd, buf, flags, addr, sizeof(struct sockaddr_un))`—Writes data to +/// a socket to a specific Unix-domain socket address. +/// +/// # References +/// - [Beej's Guide to Network Programming] +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [Winsock2] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [Beej's Guide to Network Programming]: https://beej.us/guide/bgnet/html/split/system-calls-or-bust.html#sendtorecv +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendto.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendto.2.html +/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-sendto +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendto&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendto.2 +/// [OpenBSD]: https://man.openbsd.org/sendto.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendto§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendto +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Sending-Datagrams.html +#[cfg(unix)] +#[inline] +#[doc(alias = "sendto")] +pub fn sendto_unix( + fd: Fd, + buf: &[u8], + flags: SendFlags, + addr: &SocketAddrUnix, +) -> io::Result { + backend::net::syscalls::sendto_unix(fd.as_fd(), buf, flags, addr) +} diff --git a/vendor/rustix/src/net/send_recv/msg.rs b/vendor/rustix/src/net/send_recv/msg.rs new file mode 100644 index 000000000..916f2a3db --- /dev/null +++ b/vendor/rustix/src/net/send_recv/msg.rs @@ -0,0 +1,751 @@ +//! [`recvmsg`], [`sendmsg`], and related functions. + +#![allow(unsafe_code)] + +use crate::backend::{self, c}; +use crate::fd::{AsFd, BorrowedFd, OwnedFd}; +use crate::io::{self, IoSlice, IoSliceMut}; + +use core::iter::FusedIterator; +use core::marker::PhantomData; +use core::mem::{size_of, size_of_val, take}; +use core::{ptr, slice}; + +use super::{RecvFlags, SendFlags, SocketAddrAny, SocketAddrV4, SocketAddrV6}; + +/// Macro for defining the amount of space used by CMSGs. +#[macro_export] +macro_rules! cmsg_space { + // Base Rules + (ScmRights($len:expr)) => { + $crate::net::__cmsg_space( + $len * ::core::mem::size_of::<$crate::fd::BorrowedFd<'static>>(), + ) + }; + + // Combo Rules + (($($($x:tt)*),+)) => { + $( + cmsg_space!($($x)*) + + )+ + 0 + }; +} + +#[doc(hidden)] +pub fn __cmsg_space(len: usize) -> usize { + unsafe { c::CMSG_SPACE(len.try_into().expect("CMSG_SPACE size overflow")) as usize } +} + +/// Ancillary message for [`sendmsg`], [`sendmsg_v4`], [`sendmsg_v6`], +/// [`sendmsg_unix`], and [`sendmsg_any`]. +#[non_exhaustive] +pub enum SendAncillaryMessage<'slice, 'fd> { + /// Send file descriptors. + ScmRights(&'slice [BorrowedFd<'fd>]), +} + +impl SendAncillaryMessage<'_, '_> { + /// Get the maximum size of an ancillary message. + /// + /// This can be helpful in determining the size of the buffer you allocate. + pub fn size(&self) -> usize { + let total_bytes = match self { + Self::ScmRights(slice) => size_of_val(*slice), + }; + + unsafe { + c::CMSG_SPACE( + total_bytes + .try_into() + .expect("size too large for CMSG_SPACE"), + ) as usize + } + } +} + +/// Ancillary message for [`recvmsg`]. +#[non_exhaustive] +pub enum RecvAncillaryMessage<'a> { + /// Received file descriptors. + ScmRights(AncillaryIter<'a, OwnedFd>), +} + +/// Buffer for sending ancillary messages. +pub struct SendAncillaryBuffer<'buf, 'slice, 'fd> { + /// Raw byte buffer for messages. + buffer: &'buf mut [u8], + + /// The amount of the buffer that is used. + length: usize, + + /// Phantom data for lifetime of `&'slice [BorrowedFd<'fd>]`. + _phantom: PhantomData<&'slice [BorrowedFd<'fd>]>, +} + +impl<'buf> From<&'buf mut [u8]> for SendAncillaryBuffer<'buf, '_, '_> { + fn from(buffer: &'buf mut [u8]) -> Self { + Self::new(buffer) + } +} + +impl Default for SendAncillaryBuffer<'_, '_, '_> { + fn default() -> Self { + Self::new(&mut []) + } +} + +impl<'buf, 'slice, 'fd> SendAncillaryBuffer<'buf, 'slice, 'fd> { + /// Create a new, empty `SendAncillaryBuffer` from a raw byte buffer. + pub fn new(buffer: &'buf mut [u8]) -> Self { + Self { + buffer, + length: 0, + _phantom: PhantomData, + } + } + + /// Returns a pointer to the message data. + pub(crate) fn as_control_ptr(&mut self) -> *mut u8 { + if self.length > 0 { + self.buffer.as_mut_ptr() + } else { + ptr::null_mut() + } + } + + /// Returns the length of the message data. + pub(crate) fn control_len(&self) -> usize { + self.length + } + + /// Delete all messages from the buffer. + pub fn clear(&mut self) { + self.length = 0; + } + + /// Add an ancillary message to the buffer. + /// + /// Returns `true` if the message was added successfully. + pub fn push(&mut self, msg: SendAncillaryMessage<'slice, 'fd>) -> bool { + match msg { + SendAncillaryMessage::ScmRights(fds) => { + let fds_bytes = + unsafe { slice::from_raw_parts(fds.as_ptr().cast::(), size_of_val(fds)) }; + self.push_ancillary(fds_bytes, c::SOL_SOCKET as _, c::SCM_RIGHTS as _) + } + } + } + + /// Pushes an ancillary message to the buffer. + fn push_ancillary(&mut self, source: &[u8], cmsg_level: c::c_int, cmsg_type: c::c_int) -> bool { + macro_rules! leap { + ($e:expr) => {{ + match ($e) { + Some(x) => x, + None => return false, + } + }}; + } + + // Calculate the length of the message. + let source_len = leap!(u32::try_from(source.len()).ok()); + + // Calculate the new length of the buffer. + let additional_space = unsafe { c::CMSG_SPACE(source_len) }; + let new_length = leap!(self.length.checked_add(additional_space as usize)); + let buffer = leap!(self.buffer.get_mut(..new_length)); + + // Fill the new part of the buffer with zeroes. + buffer[self.length..new_length].fill(0); + self.length = new_length; + + // Get the last header in the buffer. + let last_header = leap!(messages::Messages::new(buffer).last()); + + // Set the header fields. + last_header.cmsg_len = unsafe { c::CMSG_LEN(source_len) } as _; + last_header.cmsg_level = cmsg_level; + last_header.cmsg_type = cmsg_type; + + // Get the pointer to the payload and copy the data. + unsafe { + let payload = c::CMSG_DATA(last_header); + ptr::copy_nonoverlapping(source.as_ptr(), payload, source_len as _); + } + + true + } +} + +impl<'slice, 'fd> Extend> + for SendAncillaryBuffer<'_, 'slice, 'fd> +{ + fn extend>>(&mut self, iter: T) { + // TODO: This could be optimized to add every message in one go. + iter.into_iter().all(|msg| self.push(msg)); + } +} + +/// Buffer for receiving ancillary messages. +pub struct RecvAncillaryBuffer<'buf> { + /// Raw byte buffer for messages. + buffer: &'buf mut [u8], + + /// The portion of the buffer we've read from already. + read: usize, + + /// The amount of the buffer that is used. + length: usize, +} + +impl<'buf> From<&'buf mut [u8]> for RecvAncillaryBuffer<'buf> { + fn from(buffer: &'buf mut [u8]) -> Self { + Self::new(buffer) + } +} + +impl Default for RecvAncillaryBuffer<'_> { + fn default() -> Self { + Self::new(&mut []) + } +} + +impl<'buf> RecvAncillaryBuffer<'buf> { + /// Create a new, empty `RecvAncillaryBuffer` from a raw byte buffer. + pub fn new(buffer: &'buf mut [u8]) -> Self { + Self { + buffer, + read: 0, + length: 0, + } + } + + /// Returns a pointer to the message data. + pub(crate) fn as_control_ptr(&mut self) -> *mut u8 { + self.buffer.as_mut_ptr() + } + + /// Returns the length of the message data. + pub(crate) fn control_len(&self) -> usize { + self.buffer.len() + } + + /// Set the length of the message data. + /// + /// # Safety + /// + /// The buffer must be filled with valid message data. + pub(crate) unsafe fn set_control_len(&mut self, len: usize) { + self.length = len; + self.read = 0; + } + + /// Delete all messages from the buffer. + pub(crate) fn clear(&mut self) { + self.drain().for_each(drop); + } + + /// Drain all messages from the buffer. + pub fn drain(&mut self) -> AncillaryDrain<'_> { + AncillaryDrain { + messages: messages::Messages::new(&mut self.buffer[self.read..][..self.length]), + read: &mut self.read, + length: &mut self.length, + } + } +} + +impl Drop for RecvAncillaryBuffer<'_> { + fn drop(&mut self) { + self.clear(); + } +} + +/// An iterator that drains messages from a `RecvAncillaryBuffer`. +pub struct AncillaryDrain<'buf> { + /// Inner iterator over messages. + messages: messages::Messages<'buf>, + + /// Increment the number of messages we've read. + read: &'buf mut usize, + + /// Decrement the total length. + length: &'buf mut usize, +} + +impl<'buf> AncillaryDrain<'buf> { + /// A closure that converts a message into a `RecvAncillaryMessage`. + fn cvt_msg( + read: &mut usize, + length: &mut usize, + msg: &c::cmsghdr, + ) -> Option> { + unsafe { + // Advance the "read" pointer. + let msg_len = msg.cmsg_len as usize; + *read += msg_len; + *length -= msg_len; + + // Get a pointer to the payload. + let payload = c::CMSG_DATA(msg); + let payload_len = msg.cmsg_len as usize - c::CMSG_LEN(0) as usize; + + // Get a mutable slice of the payload. + let payload: &'buf mut [u8] = slice::from_raw_parts_mut(payload, payload_len); + + // Determine what type it is. + let (level, msg_type) = (msg.cmsg_level, msg.cmsg_type); + match (level as _, msg_type as _) { + (c::SOL_SOCKET, c::SCM_RIGHTS) => { + // Create an iterator that reads out the file descriptors. + let fds = AncillaryIter::new(payload); + + Some(RecvAncillaryMessage::ScmRights(fds)) + } + _ => None, + } + } + } +} + +impl<'buf> Iterator for AncillaryDrain<'buf> { + type Item = RecvAncillaryMessage<'buf>; + + fn next(&mut self) -> Option { + let read = &mut self.read; + let length = &mut self.length; + self.messages.find_map(|ev| Self::cvt_msg(read, length, ev)) + } + + fn size_hint(&self) -> (usize, Option) { + let (_, max) = self.messages.size_hint(); + (0, max) + } + + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + let read = self.read; + let length = self.length; + self.messages + .filter_map(|ev| Self::cvt_msg(read, length, ev)) + .fold(init, f) + } + + fn count(self) -> usize { + let read = self.read; + let length = self.length; + self.messages + .filter_map(|ev| Self::cvt_msg(read, length, ev)) + .count() + } + + fn last(self) -> Option + where + Self: Sized, + { + let read = self.read; + let length = self.length; + self.messages + .filter_map(|ev| Self::cvt_msg(read, length, ev)) + .last() + } + + fn collect>(self) -> B + where + Self: Sized, + { + let read = self.read; + let length = self.length; + self.messages + .filter_map(|ev| Self::cvt_msg(read, length, ev)) + .collect() + } +} + +impl FusedIterator for AncillaryDrain<'_> {} + +/// `sendmsg(msghdr)`—Sends a message on a socket. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendmsg.2 +/// [OpenBSD]: https://man.openbsd.org/sendmsg.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendmsg +#[inline] +pub fn sendmsg( + socket: impl AsFd, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + flags: SendFlags, +) -> io::Result { + backend::net::syscalls::sendmsg(socket.as_fd(), iov, control, flags) +} + +/// `sendmsg(msghdr)`—Sends a message on a socket to a specific IPv4 address. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendmsg.2 +/// [OpenBSD]: https://man.openbsd.org/sendmsg.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendmsg +#[inline] +pub fn sendmsg_v4( + socket: impl AsFd, + addr: &SocketAddrV4, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + flags: SendFlags, +) -> io::Result { + backend::net::syscalls::sendmsg_v4(socket.as_fd(), addr, iov, control, flags) +} + +/// `sendmsg(msghdr)`—Sends a message on a socket to a specific IPv6 address. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendmsg.2 +/// [OpenBSD]: https://man.openbsd.org/sendmsg.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendmsg +#[inline] +pub fn sendmsg_v6( + socket: impl AsFd, + addr: &SocketAddrV6, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + flags: SendFlags, +) -> io::Result { + backend::net::syscalls::sendmsg_v6(socket.as_fd(), addr, iov, control, flags) +} + +/// `sendmsg(msghdr)`—Sends a message on a socket to a specific Unix-domain +/// address. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendmsg.2 +/// [OpenBSD]: https://man.openbsd.org/sendmsg.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendmsg +#[inline] +#[cfg(unix)] +pub fn sendmsg_unix( + socket: impl AsFd, + addr: &super::SocketAddrUnix, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + flags: SendFlags, +) -> io::Result { + backend::net::syscalls::sendmsg_unix(socket.as_fd(), addr, iov, control, flags) +} + +/// `sendmsg(msghdr)`—Sends a message on a socket to a specific address. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html +/// [Linux]: https://man7.org/linux/man-pages/man2/sendmsg.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/sendmsg.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=sendmsg&sektion=2 +/// [NetBSD]: https://man.netbsd.org/sendmsg.2 +/// [OpenBSD]: https://man.openbsd.org/sendmsg.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sendmsg§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/sendmsg +#[inline] +pub fn sendmsg_any( + socket: impl AsFd, + addr: Option<&SocketAddrAny>, + iov: &[IoSlice<'_>], + control: &mut SendAncillaryBuffer<'_, '_, '_>, + flags: SendFlags, +) -> io::Result { + match addr { + None => backend::net::syscalls::sendmsg(socket.as_fd(), iov, control, flags), + Some(SocketAddrAny::V4(addr)) => { + backend::net::syscalls::sendmsg_v4(socket.as_fd(), addr, iov, control, flags) + } + Some(SocketAddrAny::V6(addr)) => { + backend::net::syscalls::sendmsg_v6(socket.as_fd(), addr, iov, control, flags) + } + #[cfg(unix)] + Some(SocketAddrAny::Unix(addr)) => { + backend::net::syscalls::sendmsg_unix(socket.as_fd(), addr, iov, control, flags) + } + } +} + +/// `recvmsg(msghdr)`—Receives a message from a socket. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html +/// [Linux]: https://man7.org/linux/man-pages/man2/recvmsg.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/recvmsg.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=recvmsg&sektion=2 +/// [NetBSD]: https://man.netbsd.org/recvmsg.2 +/// [OpenBSD]: https://man.openbsd.org/recvmsg.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=recvmsg§ion=2 +/// [illumos]: https://illumos.org/man/3SOCKET/recvmsg +#[inline] +pub fn recvmsg( + socket: impl AsFd, + iov: &mut [IoSliceMut<'_>], + control: &mut RecvAncillaryBuffer<'_>, + flags: RecvFlags, +) -> io::Result { + backend::net::syscalls::recvmsg(socket.as_fd(), iov, control, flags) +} + +/// The result of a successful [`recvmsg`] call. +pub struct RecvMsgReturn { + /// The number of bytes received. + pub bytes: usize, + + /// The flags received. + pub flags: RecvFlags, + + /// The address of the socket we received from, if any. + pub address: Option, +} + +/// An iterator over data in an ancillary buffer. +pub struct AncillaryIter<'data, T> { + /// The data we're iterating over. + data: &'data mut [u8], + + /// The raw data we're removing. + _marker: PhantomData, +} + +impl<'data, T> AncillaryIter<'data, T> { + /// Create a new iterator over data in an ancillary buffer. + /// + /// # Safety + /// + /// The buffer must contain valid ancillary data. + unsafe fn new(data: &'data mut [u8]) -> Self { + assert_eq!(data.len() % size_of::(), 0); + + Self { + data, + _marker: PhantomData, + } + } +} + +impl<'data, T> Drop for AncillaryIter<'data, T> { + fn drop(&mut self) { + self.for_each(drop); + } +} + +impl Iterator for AncillaryIter<'_, T> { + type Item = T; + + fn next(&mut self) -> Option { + // See if there is a next item. + if self.data.len() < size_of::() { + return None; + } + + // Get the next item. + let item = unsafe { self.data.as_ptr().cast::().read_unaligned() }; + + // Move forward. + let data = take(&mut self.data); + self.data = &mut data[size_of::()..]; + + Some(item) + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } + + fn count(self) -> usize { + self.len() + } + + fn last(mut self) -> Option { + self.next_back() + } +} + +impl FusedIterator for AncillaryIter<'_, T> {} + +impl ExactSizeIterator for AncillaryIter<'_, T> { + fn len(&self) -> usize { + self.data.len() / size_of::() + } +} + +impl DoubleEndedIterator for AncillaryIter<'_, T> { + fn next_back(&mut self) -> Option { + // See if there is a next item. + if self.data.len() < size_of::() { + return None; + } + + // Get the next item. + let item = unsafe { + let ptr = self.data.as_ptr().add(self.data.len() - size_of::()); + ptr.cast::().read_unaligned() + }; + + // Move forward. + let len = self.data.len(); + let data = take(&mut self.data); + self.data = &mut data[..len - size_of::()]; + + Some(item) + } +} + +mod messages { + use crate::backend::c; + use core::iter::FusedIterator; + use core::marker::PhantomData; + use core::mem::zeroed; + use core::ptr::NonNull; + + /// An iterator over the messages in an ancillary buffer. + pub(super) struct Messages<'buf> { + /// The message header we're using to iterator over the messages. + msghdr: c::msghdr, + + /// The current pointer to the next message header to return. + /// + /// This has a lifetime of `'buf`. + header: Option>, + + /// Capture the original lifetime of the buffer. + _buffer: PhantomData<&'buf mut [u8]>, + } + + impl<'buf> Messages<'buf> { + /// Create a new iterator over messages from a byte buffer. + pub(super) fn new(buf: &'buf mut [u8]) -> Self { + let msghdr = { + let mut h: c::msghdr = unsafe { zeroed() }; + h.msg_control = buf.as_mut_ptr().cast(); + h.msg_controllen = buf.len().try_into().expect("buffer too large for msghdr"); + h + }; + + // Get the first header. + let header = NonNull::new(unsafe { c::CMSG_FIRSTHDR(&msghdr) }); + + Self { + msghdr, + header, + _buffer: PhantomData, + } + } + } + + impl<'a> Iterator for Messages<'a> { + type Item = &'a mut c::cmsghdr; + + #[inline] + fn next(&mut self) -> Option { + // Get the current header. + let header = self.header?; + + // Get the next header. + self.header = NonNull::new(unsafe { c::CMSG_NXTHDR(&self.msghdr, header.as_ptr()) }); + + // If the headers are equal, we're done. + if Some(header) == self.header { + self.header = None; + } + + // SAFETY: The lifetime of `header` is tied to this. + Some(unsafe { &mut *header.as_ptr() }) + } + + fn size_hint(&self) -> (usize, Option) { + if self.header.is_some() { + // The remaining buffer *could* be filled with zero-length + // messages. + let max_size = unsafe { c::CMSG_LEN(0) } as usize; + let remaining_count = self.msghdr.msg_controllen as usize / max_size; + (1, Some(remaining_count)) + } else { + (0, Some(0)) + } + } + } + + impl FusedIterator for Messages<'_> {} +} diff --git a/vendor/rustix/src/net/socket.rs b/vendor/rustix/src/net/socket.rs index dbfb391ba..23cc00aed 100644 --- a/vendor/rustix/src/net/socket.rs +++ b/vendor/rustix/src/net/socket.rs @@ -3,19 +3,9 @@ use crate::net::{SocketAddr, SocketAddrAny, SocketAddrV4, SocketAddrV6}; use crate::{backend, io}; use backend::fd::{AsFd, BorrowedFd}; +pub use crate::net::{AddressFamily, Protocol, Shutdown, SocketFlags, SocketType}; #[cfg(unix)] pub use backend::net::addr::SocketAddrUnix; -pub use backend::net::types::{AddressFamily, Protocol, Shutdown, SocketFlags, SocketType}; - -/// Compatibility alias for `SocketFlags`. Use `SocketFlags` instead of this. -pub type AcceptFlags = SocketFlags; - -impl Default for Protocol { - #[inline] - fn default() -> Self { - Self::IP - } -} /// `socket(domain, type_, protocol)`—Creates a socket. /// @@ -50,7 +40,11 @@ impl Default for Protocol { /// [illumos]: https://illumos.org/man/3SOCKET/socket /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Creating-a-Socket.html #[inline] -pub fn socket(domain: AddressFamily, type_: SocketType, protocol: Protocol) -> io::Result { +pub fn socket( + domain: AddressFamily, + type_: SocketType, + protocol: Option, +) -> io::Result { backend::net::syscalls::socket(domain, type_, protocol) } @@ -93,7 +87,7 @@ pub fn socket_with( domain: AddressFamily, type_: SocketType, flags: SocketFlags, - protocol: Protocol, + protocol: Option, ) -> io::Result { backend::net::syscalls::socket_with(domain, type_, flags, protocol) } diff --git a/vendor/rustix/src/net/socket_addr_any.rs b/vendor/rustix/src/net/socket_addr_any.rs index 403ad11c2..7cb124e4c 100644 --- a/vendor/rustix/src/net/socket_addr_any.rs +++ b/vendor/rustix/src/net/socket_addr_any.rs @@ -1,7 +1,7 @@ //! A socket address for any kind of socket. //! //! This is similar to [`std::net::SocketAddr`], but also supports Unix-domain -//! socket addresses. +//! socket addresses on Unix. //! //! # Safety //! diff --git a/vendor/rustix/src/net/socketpair.rs b/vendor/rustix/src/net/socketpair.rs index b2d46060e..7228e716b 100644 --- a/vendor/rustix/src/net/socketpair.rs +++ b/vendor/rustix/src/net/socketpair.rs @@ -2,7 +2,8 @@ use crate::fd::OwnedFd; use crate::net::{AddressFamily, Protocol, SocketFlags, SocketType}; use crate::{backend, io}; -/// `socketpair(domain, type_ | accept_flags, protocol)` +/// `socketpair(domain, type_ | accept_flags, protocol)`—Create a pair of +/// sockets that are connected to each other. /// /// # References /// - [POSIX] @@ -29,7 +30,7 @@ pub fn socketpair( domain: AddressFamily, type_: SocketType, flags: SocketFlags, - protocol: Protocol, + protocol: Option, ) -> io::Result<(OwnedFd, OwnedFd)> { backend::net::syscalls::socketpair(domain, type_, flags, protocol) } diff --git a/vendor/rustix/src/net/sockopt.rs b/vendor/rustix/src/net/sockopt.rs index 26de89e0a..53e73e64b 100644 --- a/vendor/rustix/src/net/sockopt.rs +++ b/vendor/rustix/src/net/sockopt.rs @@ -8,10 +8,24 @@ use crate::net::{Ipv4Addr, Ipv6Addr, SocketType}; use crate::{backend, io}; +use backend::c; use backend::fd::AsFd; use core::time::Duration; -pub use backend::net::types::Timeout; +/// Timeout identifier for use with [`set_socket_timeout`] and +/// [`get_socket_timeout`]. +/// +/// [`set_socket_timeout`]: crate::net::sockopt::set_socket_timeout. +/// [`get_socket_timeout`]: crate::net::sockopt::get_socket_timeout. +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[repr(u32)] +pub enum Timeout { + /// `SO_RCVTIMEO`—Timeout for receiving. + Recv = c::SO_RCVTIMEO as _, + + /// `SO_SNDTIMEO`—Timeout for sending. + Send = c::SO_SNDTIMEO as _, +} /// `getsockopt(fd, SOL_SOCKET, SO_TYPE)`—Returns the type of a socket. /// @@ -249,7 +263,7 @@ pub fn get_socket_linger(fd: Fd) -> io::Result> { /// /// [Linux `setsockopt`]: https://man7.org/linux/man-pages/man2/setsockopt.2.html /// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] #[doc(alias = "SO_PASSCRED")] pub fn set_socket_passcred(fd: Fd, passcred: bool) -> io::Result<()> { @@ -264,7 +278,7 @@ pub fn set_socket_passcred(fd: Fd, passcred: bool) -> io::Result<()> { /// /// [Linux `getsockopt`]: https://man7.org/linux/man-pages/man2/getsockopt.2.html /// [Linux `socket`]: https://man7.org/linux/man-pages/man7/socket.7.html -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] #[doc(alias = "SO_PASSCRED")] pub fn get_socket_passcred(fd: Fd) -> io::Result { @@ -427,8 +441,8 @@ pub fn get_socket_error(fd: Fd) -> io::Result> { #[cfg(any(apple, target_os = "freebsd"))] #[doc(alias = "SO_NOSIGPIPE")] #[inline] -pub fn getsockopt_nosigpipe(fd: Fd) -> io::Result { - backend::net::syscalls::sockopt::getsockopt_nosigpipe(fd.as_fd()) +pub fn get_socket_nosigpipe(fd: Fd) -> io::Result { + backend::net::syscalls::sockopt::get_socket_nosigpipe(fd.as_fd()) } /// `setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, val)` @@ -466,8 +480,8 @@ pub fn getsockopt_nosigpipe(fd: Fd) -> io::Result { #[cfg(any(apple, target_os = "freebsd"))] #[doc(alias = "SO_NOSIGPIPE")] #[inline] -pub fn setsockopt_nosigpipe(fd: Fd, val: bool) -> io::Result<()> { - backend::net::syscalls::sockopt::setsockopt_nosigpipe(fd.as_fd(), val) +pub fn set_socket_nosigpipe(fd: Fd, val: bool) -> io::Result<()> { + backend::net::syscalls::sockopt::set_socket_nosigpipe(fd.as_fd(), val) } /// `setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, keepalive)` @@ -1614,3 +1628,13 @@ pub fn set_tcp_nodelay(fd: Fd, nodelay: bool) -> io::Result<()> { pub fn get_tcp_nodelay(fd: Fd) -> io::Result { backend::net::syscalls::sockopt::get_tcp_nodelay(fd.as_fd()) } + +#[test] +fn test_sizes() { + use c::c_int; + use core::mem::size_of; + + // Backend code needs to cast these to `c_int` so make sure that cast + // isn't lossy. + assert_eq!(size_of::(), size_of::()); +} diff --git a/vendor/rustix/src/net/types.rs b/vendor/rustix/src/net/types.rs new file mode 100644 index 000000000..95fa931a1 --- /dev/null +++ b/vendor/rustix/src/net/types.rs @@ -0,0 +1,1299 @@ +#![allow(unsafe_code)] + +use crate::backend::c; +use bitflags::bitflags; + +/// A type for holding raw integer socket types. +#[doc(hidden)] +pub type RawSocketType = u32; + +/// `SOCK_*` constants for use with [`socket`]. +/// +/// [`socket`]: crate::net::socket() +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[repr(transparent)] +pub struct SocketType(pub(crate) RawSocketType); + +#[rustfmt::skip] +impl SocketType { + /// `SOCK_STREAM` + pub const STREAM: Self = Self(c::SOCK_STREAM as _); + + /// `SOCK_DGRAM` + pub const DGRAM: Self = Self(c::SOCK_DGRAM as _); + + /// `SOCK_SEQPACKET` + pub const SEQPACKET: Self = Self(c::SOCK_SEQPACKET as _); + + /// `SOCK_RAW` + pub const RAW: Self = Self(c::SOCK_RAW as _); + + /// `SOCK_RDM` + #[cfg(not(target_os = "haiku"))] + pub const RDM: Self = Self(c::SOCK_RDM as _); + + /// Constructs a `SocketType` from a raw integer. + #[inline] + pub const fn from_raw(raw: RawSocketType) -> Self { + Self(raw) + } + + /// Returns the raw integer for this `SocketType`. + #[inline] + pub const fn as_raw(self) -> RawSocketType { + self.0 + } +} + +/// A type for holding raw integer address families. +#[doc(hidden)] +pub type RawAddressFamily = c::sa_family_t; + +/// `AF_*` constants. +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[repr(transparent)] +pub struct AddressFamily(pub(crate) RawAddressFamily); + +#[rustfmt::skip] +#[allow(non_upper_case_globals)] +impl AddressFamily { + /// `AF_UNSPEC` + pub const UNSPEC: Self = Self(c::AF_UNSPEC as _); + /// `AF_INET` + /// + /// # References + /// - [Linux] + /// + /// [Linux]: https://man7.org/linux/man-pages/man7/ip.7.html> + pub const INET: Self = Self(c::AF_INET as _); + /// `AF_INET6` + /// + /// # References + /// - [Linux] + /// + /// [Linux]: https://man7.org/linux/man-pages/man7/ipv6.7.html + pub const INET6: Self = Self(c::AF_INET6 as _); + /// `AF_NETLINK` + /// + /// # References + /// - [Linux] + /// + /// [Linux]: https://man7.org/linux/man-pages/man7/netlink.7.html + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const NETLINK: Self = Self(c::AF_NETLINK as _); + /// `AF_UNIX`, aka `AF_LOCAL` + #[doc(alias = "LOCAL")] + pub const UNIX: Self = Self(c::AF_UNIX as _); + /// `AF_AX25` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const AX25: Self = Self(c::AF_AX25 as _); + /// `AF_IPX` + pub const IPX: Self = Self(c::AF_IPX as _); + /// `AF_APPLETALK` + pub const APPLETALK: Self = Self(c::AF_APPLETALK as _); + /// `AF_NETROM` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const NETROM: Self = Self(c::AF_NETROM as _); + /// `AF_BRIDGE` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const BRIDGE: Self = Self(c::AF_BRIDGE as _); + /// `AF_ATMPVC` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const ATMPVC: Self = Self(c::AF_ATMPVC as _); + /// `AF_X25` + #[cfg(not(any( + bsd, + windows, + target_os = "haiku", + )))] + pub const X25: Self = Self(c::AF_X25 as _); + /// `AF_ROSE` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const ROSE: Self = Self(c::AF_ROSE as _); + /// `AF_DECnet` + #[cfg(not(target_os = "haiku"))] + pub const DECnet: Self = Self(c::AF_DECnet as _); + /// `AF_NETBEUI` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const NETBEUI: Self = Self(c::AF_NETBEUI as _); + /// `AF_SECURITY` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const SECURITY: Self = Self(c::AF_SECURITY as _); + /// `AF_KEY` + #[cfg(not(any( + bsd, + windows, + target_os = "haiku", + )))] + pub const KEY: Self = Self(c::AF_KEY as _); + /// `AF_PACKET` + /// + /// # References + /// - [Linux] + /// + /// [Linux]: https://man7.org/linux/man-pages/man7/packet.7.html + #[cfg(not(any( + bsd, + windows, + target_os = "haiku", + )))] + pub const PACKET: Self = Self(c::AF_PACKET as _); + /// `AF_ASH` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const ASH: Self = Self(c::AF_ASH as _); + /// `AF_ECONET` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const ECONET: Self = Self(c::AF_ECONET as _); + /// `AF_ATMSVC` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const ATMSVC: Self = Self(c::AF_ATMSVC as _); + /// `AF_RDS` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const RDS: Self = Self(c::AF_RDS as _); + /// `AF_SNA` + #[cfg(not(target_os = "haiku"))] + pub const SNA: Self = Self(c::AF_SNA as _); + /// `AF_IRDA` + #[cfg(not(any( + bsd, + solarish, + target_os = "haiku", + )))] + pub const IRDA: Self = Self(c::AF_IRDA as _); + /// `AF_PPPOX` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const PPPOX: Self = Self(c::AF_PPPOX as _); + /// `AF_WANPIPE` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const WANPIPE: Self = Self(c::AF_WANPIPE as _); + /// `AF_LLC` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const LLC: Self = Self(c::AF_LLC as _); + /// `AF_CAN` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const CAN: Self = Self(c::AF_CAN as _); + /// `AF_TIPC` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const TIPC: Self = Self(c::AF_TIPC as _); + /// `AF_BLUETOOTH` + #[cfg(not(any(apple, solarish, windows)))] + pub const BLUETOOTH: Self = Self(c::AF_BLUETOOTH as _); + /// `AF_IUCV` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const IUCV: Self = Self(c::AF_IUCV as _); + /// `AF_RXRPC` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const RXRPC: Self = Self(c::AF_RXRPC as _); + /// `AF_ISDN` + #[cfg(not(any(solarish, windows, target_os = "haiku")))] + pub const ISDN: Self = Self(c::AF_ISDN as _); + /// `AF_PHONET` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const PHONET: Self = Self(c::AF_PHONET as _); + /// `AF_IEEE802154` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "haiku", + )))] + pub const IEEE802154: Self = Self(c::AF_IEEE802154 as _); + /// `AF_802` + #[cfg(solarish)] + pub const EIGHT_ZERO_TWO: Self = Self(c::AF_802 as _); + #[cfg(target_os = "fuchsia")] + /// `AF_ALG` + pub const ALG: Self = Self(c::AF_ALG as _); + #[cfg(any(target_os = "freebsd", target_os = "netbsd", target_os = "nto"))] + /// `AF_ARP` + pub const ARP: Self = Self(c::AF_ARP as _); + /// `AF_ATM` + #[cfg(freebsdlike)] + pub const ATM: Self = Self(c::AF_ATM as _); + /// `AF_CAIF` + #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "fuchsia"))] + pub const CAIF: Self = Self(c::AF_CAIF as _); + /// `AF_CCITT` + #[cfg(any(bsd, solarish, target_os = "aix", target_os = "nto"))] + pub const CCITT: Self = Self(c::AF_CCITT as _); + /// `AF_CHAOS` + #[cfg(any(bsd, solarish, target_os = "aix", target_os = "nto"))] + pub const CHAOS: Self = Self(c::AF_CHAOS as _); + /// `AF_CNT` + #[cfg(any(bsd, target_os = "nto"))] + pub const CNT: Self = Self(c::AF_CNT as _); + /// `AF_COIP` + #[cfg(any(bsd, target_os = "nto"))] + pub const COIP: Self = Self(c::AF_COIP as _); + /// `AF_DATAKIT` + #[cfg(any(bsd, solarish, target_os = "aix", target_os = "nto"))] + pub const DATAKIT: Self = Self(c::AF_DATAKIT as _); + /// `AF_DLI` + #[cfg(any(bsd, solarish, target_os = "aix", target_os = "haiku", target_os = "nto"))] + pub const DLI: Self = Self(c::AF_DLI as _); + /// `AF_E164` + #[cfg(any(bsd, target_os = "nto"))] + pub const E164: Self = Self(c::AF_E164 as _); + /// `AF_ECMA` + #[cfg(any(apple, freebsdlike, solarish, target_os = "aix", target_os = "nto", target_os = "openbsd"))] + pub const ECMA: Self = Self(c::AF_ECMA as _); + /// `AF_ENCAP` + #[cfg(target_os = "openbsd")] + pub const ENCAP: Self = Self(c::AF_ENCAP as _); + /// `AF_FILE` + #[cfg(solarish)] + pub const FILE: Self = Self(c::AF_FILE as _); + /// `AF_GOSIP` + #[cfg(solarish)] + pub const GOSIP: Self = Self(c::AF_GOSIP as _); + /// `AF_HYLINK` + #[cfg(any(bsd, solarish, target_os = "aix", target_os = "nto"))] + pub const HYLINK: Self = Self(c::AF_HYLINK as _); + /// `AF_IB` + #[cfg(any(target_os = "emscripten", target_os = "fuchsia"))] + pub const IB: Self = Self(c::AF_IB as _); + /// `AF_IMPLINK` + #[cfg(any(bsd, solarish, target_os = "aix", target_os = "nto"))] + pub const IMPLINK: Self = Self(c::AF_IMPLINK as _); + /// `AF_IEEE80211` + #[cfg(any(apple, freebsdlike, linuxlike, target_os = "netbsd"))] + pub const IEEE80211: Self = Self(c::AF_IEEE80211 as _); + /// `AF_INET6_SDP` + #[cfg(target_os = "freebsd")] + pub const INET6_SDP: Self = Self(c::AF_INET6_SDP as _); + /// `AF_INET_OFFLOAD` + #[cfg(solarish)] + pub const INET_OFFLOAD: Self = Self(c::AF_INET_OFFLOAD as _); + /// `AF_INET_SDP` + #[cfg(target_os = "freebsd")] + pub const INET_SDP: Self = Self(c::AF_INET_SDP as _); + /// `AF_INTF` + #[cfg(target_os = "aix")] + pub const INTF: Self = Self(c::AF_INTF as _); + /// `AF_ISO` + #[cfg(any(bsd, target_os = "aix", target_os = "nto"))] + pub const ISO: Self = Self(c::AF_ISO as _); + /// `AF_LAT` + #[cfg(any(bsd, solarish, target_os = "aix", target_os = "nto"))] + pub const LAT: Self = Self(c::AF_LAT as _); + /// `AF_LINK` + #[cfg(any(bsd, solarish, target_os = "aix", target_os = "haiku", target_os = "nto"))] + pub const LINK: Self = Self(c::AF_LINK as _); + /// `AF_MPLS` + #[cfg(any(netbsdlike, target_os = "dragonfly", target_os = "emscripten", target_os = "fuchsia"))] + pub const MPLS: Self = Self(c::AF_MPLS as _); + /// `AF_NATM` + #[cfg(any(bsd, target_os = "aix", target_os = "nto"))] + pub const NATM: Self = Self(c::AF_NATM as _); + /// `AF_NBS` + #[cfg(solarish)] + pub const NBS: Self = Self(c::AF_NBS as _); + /// `AF_NCA` + #[cfg(solarish)] + pub const NCA: Self = Self(c::AF_NCA as _); + /// `AF_NDD` + #[cfg(target_os = "aix")] + pub const NDD: Self = Self(c::AF_NDD as _); + /// `AF_NDRV` + #[cfg(apple)] + pub const NDRV: Self = Self(c::AF_NDRV as _); + /// `AF_NETBIOS` + #[cfg(any(apple, freebsdlike))] + pub const NETBIOS: Self = Self(c::AF_NETBIOS as _); + /// `AF_NETGRAPH` + #[cfg(freebsdlike)] + pub const NETGRAPH: Self = Self(c::AF_NETGRAPH as _); + /// `AF_NIT` + #[cfg(solarish)] + pub const NIT: Self = Self(c::AF_NIT as _); + /// `AF_NOTIFY` + #[cfg(target_os = "haiku")] + pub const NOTIFY: Self = Self(c::AF_NOTIFY as _); + /// `AF_NFC` + #[cfg(any(target_os = "emscripten", target_os = "fuchsia"))] + pub const NFC: Self = Self(c::AF_NFC as _); + /// `AF_NS` + #[cfg(any(apple, solarish, netbsdlike, target_os = "aix", target_os = "nto"))] + pub const NS: Self = Self(c::AF_NS as _); + /// `AF_OROUTE` + #[cfg(target_os = "netbsd")] + pub const OROUTE: Self = Self(c::AF_OROUTE as _); + /// `AF_OSI` + #[cfg(any(bsd, solarish, target_os = "aix", target_os = "nto"))] + pub const OSI: Self = Self(c::AF_OSI as _); + /// `AF_OSINET` + #[cfg(solarish)] + pub const OSINET: Self = Self(c::AF_OSINET as _); + /// `AF_POLICY` + #[cfg(solarish)] + pub const POLICY: Self = Self(c::AF_POLICY as _); + /// `AF_PPP` + #[cfg(apple)] + pub const PPP: Self = Self(c::AF_PPP as _); + /// `AF_PUP` + #[cfg(any(bsd, solarish, target_os = "aix", target_os = "nto"))] + pub const PUP: Self = Self(c::AF_PUP as _); + /// `AF_RIF` + #[cfg(target_os = "aix")] + pub const RIF: Self = Self(c::AF_RIF as _); + /// `AF_ROUTE` + #[cfg(any(bsd, solarish, target_os = "android", target_os = "emscripten", target_os = "fuchsia", target_os = "haiku", target_os = "nto"))] + pub const ROUTE: Self = Self(c::AF_ROUTE as _); + /// `AF_SCLUSTER` + #[cfg(target_os = "freebsd")] + pub const SCLUSTER: Self = Self(c::AF_SCLUSTER as _); + /// `AF_SIP` + #[cfg(any(apple, target_os = "freebsd", target_os = "opensbd"))] + pub const SIP: Self = Self(c::AF_SIP as _); + /// `AF_SLOW` + #[cfg(target_os = "freebsd")] + pub const SLOW: Self = Self(c::AF_SLOW as _); + /// `AF_SYS_CONTROL` + #[cfg(apple)] + pub const SYS_CONTROL: Self = Self(c::AF_SYS_CONTROL as _); + /// `AF_SYSTEM` + #[cfg(apple)] + pub const SYSTEM: Self = Self(c::AF_SYSTEM as _); + /// `AF_TRILL` + #[cfg(solarish)] + pub const TRILL: Self = Self(c::AF_TRILL as _); + /// `AF_UTUN` + #[cfg(apple)] + pub const UTUN: Self = Self(c::AF_UTUN as _); + /// `AF_VSOCK` + #[cfg(any(apple, target_os = "emscripten", target_os = "fuchsia"))] + pub const VSOCK: Self = Self(c::AF_VSOCK as _); + + /// Constructs a `AddressFamily` from a raw integer. + #[inline] + pub const fn from_raw(raw: RawAddressFamily) -> Self { + Self(raw) + } + + /// Returns the raw integer for this `AddressFamily`. + #[inline] + pub const fn as_raw(self) -> RawAddressFamily { + self.0 + } +} + +/// A type for holding raw integer protocols. +#[doc(hidden)] +pub type RawProtocol = core::num::NonZeroU32; + +/// `IPPROTO_*` and other constants for use with [`socket`], [`socket_with`], +/// and [`socketpair`] when a nondefault value is desired. See the [`ipproto`], +/// [`sysproto`], and [`netlink`] modules for possible values. +/// +/// For the default values, such as `IPPROTO_IP` or `NETLINK_ROUTE`, pass +/// `None` as the `protocol` argument in these functions. +/// +/// [`socket`]: crate::net::socket() +/// [`socket_with`]: crate::net::socket_with +/// [`socketpair`]: crate::net::socketpair() +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[repr(transparent)] +#[doc(alias = "IPPROTO_IP")] +#[doc(alias = "NETLINK_ROUTE")] +pub struct Protocol(pub(crate) RawProtocol); + +/// `IPPROTO_*` constants. +/// +/// For `IPPROTO_IP`, pass `None` as the `protocol` argument. +pub mod ipproto { + use super::{Protocol, RawProtocol}; + use crate::backend::c; + + /// `IPPROTO_ICMP` + pub const ICMP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_ICMP as _) }); + /// `IPPROTO_IGMP` + #[cfg(not(any(solarish, target_os = "haiku")))] + pub const IGMP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_IGMP as _) }); + /// `IPPROTO_IPIP` + #[cfg(not(any(solarish, windows, target_os = "haiku")))] + pub const IPIP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_IPIP as _) }); + /// `IPPROTO_TCP` + pub const TCP: Protocol = Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_TCP as _) }); + /// `IPPROTO_EGP` + #[cfg(not(any(solarish, target_os = "haiku")))] + pub const EGP: Protocol = Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_EGP as _) }); + /// `IPPROTO_PUP` + #[cfg(not(any(solarish, target_os = "haiku")))] + pub const PUP: Protocol = Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_PUP as _) }); + /// `IPPROTO_UDP` + pub const UDP: Protocol = Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_UDP as _) }); + /// `IPPROTO_IDP` + #[cfg(not(any(solarish, target_os = "haiku")))] + pub const IDP: Protocol = Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_IDP as _) }); + /// `IPPROTO_TP` + #[cfg(not(any(solarish, windows, target_os = "haiku")))] + pub const TP: Protocol = Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_TP as _) }); + /// `IPPROTO_DCCP` + #[cfg(not(any( + apple, + solarish, + windows, + target_os = "dragonfly", + target_os = "haiku", + target_os = "openbsd", + )))] + pub const DCCP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_DCCP as _) }); + /// `IPPROTO_IPV6` + pub const IPV6: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_IPV6 as _) }); + /// `IPPROTO_RSVP` + #[cfg(not(any(solarish, windows, target_os = "haiku")))] + pub const RSVP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_RSVP as _) }); + /// `IPPROTO_GRE` + #[cfg(not(any(solarish, windows, target_os = "haiku")))] + pub const GRE: Protocol = Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_GRE as _) }); + /// `IPPROTO_ESP` + #[cfg(not(any(solarish, target_os = "haiku")))] + pub const ESP: Protocol = Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_ESP as _) }); + /// `IPPROTO_AH` + #[cfg(not(any(solarish, target_os = "haiku")))] + pub const AH: Protocol = Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_AH as _) }); + /// `IPPROTO_MTP` + #[cfg(not(any(solarish, netbsdlike, windows, target_os = "haiku")))] + pub const MTP: Protocol = Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_MTP as _) }); + /// `IPPROTO_BEETPH` + #[cfg(not(any(bsd, solarish, windows, target_os = "haiku")))] + pub const BEETPH: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_BEETPH as _) }); + /// `IPPROTO_ENCAP` + #[cfg(not(any(solarish, windows, target_os = "haiku")))] + pub const ENCAP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_ENCAP as _) }); + /// `IPPROTO_PIM` + #[cfg(not(any(solarish, target_os = "haiku")))] + pub const PIM: Protocol = Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_PIM as _) }); + /// `IPPROTO_COMP` + #[cfg(not(any(bsd, solarish, windows, target_os = "haiku")))] + pub const COMP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_COMP as _) }); + /// `IPPROTO_SCTP` + #[cfg(not(any( + solarish, + target_os = "dragonfly", + target_os = "haiku", + target_os = "openbsd" + )))] + pub const SCTP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_SCTP as _) }); + /// `IPPROTO_UDPLITE` + #[cfg(not(any( + apple, + netbsdlike, + solarish, + windows, + target_os = "dragonfly", + target_os = "haiku", + )))] + pub const UDPLITE: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_UDPLITE as _) }); + /// `IPPROTO_MPLS` + #[cfg(not(any( + apple, + solarish, + windows, + target_os = "dragonfly", + target_os = "haiku", + target_os = "netbsd", + )))] + pub const MPLS: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_MPLS as _) }); + /// `IPPROTO_ETHERNET` + #[cfg(linux_kernel)] + pub const ETHERNET: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_ETHERNET as _) }); + /// `IPPROTO_RAW` + pub const RAW: Protocol = Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_RAW as _) }); + /// `IPPROTO_MPTCP` + #[cfg(not(any( + bsd, + solarish, + windows, + target_os = "emscripten", + target_os = "fuchsia", + target_os = "haiku", + )))] + pub const MPTCP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_MPTCP as _) }); + /// `IPPROTO_FRAGMENT` + #[cfg(not(any(solarish, target_os = "haiku")))] + pub const FRAGMENT: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_FRAGMENT as _) }); + /// `IPPROTO_ICMPV6` + pub const ICMPV6: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_ICMPV6 as _) }); + /// `IPPROTO_MH` + #[cfg(not(any( + apple, + netbsdlike, + solarish, + windows, + target_os = "dragonfly", + target_os = "haiku", + )))] + pub const MH: Protocol = Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_MH as _) }); + /// `IPPROTO_ROUTING` + #[cfg(not(any(solarish, target_os = "haiku")))] + pub const ROUTING: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::IPPROTO_ROUTING as _) }); +} + +/// `SYSPROTO_*` constants. +pub mod sysproto { + #[cfg(apple)] + use { + super::{Protocol, RawProtocol}, + crate::backend::c, + }; + + /// `SYSPROTO_EVENT` + #[cfg(apple)] + pub const EVENT: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::SYSPROTO_EVENT as _) }); + + /// `SYSPROTO_CONTROL` + #[cfg(apple)] + pub const CONTROL: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::SYSPROTO_CONTROL as _) }); +} + +/// `NETLINK_*` constants. +/// +/// For `NETLINK_ROUTE`, pass `None` as the `protocol` argument. +pub mod netlink { + #[cfg(linux_kernel)] + use { + super::{Protocol, RawProtocol}, + crate::backend::c, + }; + + /// `NETLINK_UNUSED` + #[cfg(linux_kernel)] + pub const UNUSED: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_UNUSED as _) }); + /// `NETLINK_USERSOCK` + #[cfg(linux_kernel)] + pub const USERSOCK: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_USERSOCK as _) }); + /// `NETLINK_FIREWALL` + #[cfg(linux_kernel)] + pub const FIREWALL: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_FIREWALL as _) }); + /// `NETLINK_SOCK_DIAG` + #[cfg(linux_kernel)] + pub const SOCK_DIAG: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_SOCK_DIAG as _) }); + /// `NETLINK_NFLOG` + #[cfg(linux_kernel)] + pub const NFLOG: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_NFLOG as _) }); + /// `NETLINK_XFRM` + #[cfg(linux_kernel)] + pub const XFRM: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_XFRM as _) }); + /// `NETLINK_SELINUX` + #[cfg(linux_kernel)] + pub const SELINUX: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_SELINUX as _) }); + /// `NETLINK_ISCSI` + #[cfg(linux_kernel)] + pub const ISCSI: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_ISCSI as _) }); + /// `NETLINK_AUDIT` + #[cfg(linux_kernel)] + pub const AUDIT: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_AUDIT as _) }); + /// `NETLINK_FIB_LOOKUP` + #[cfg(linux_kernel)] + pub const FIB_LOOKUP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_FIB_LOOKUP as _) }); + /// `NETLINK_CONNECTOR` + #[cfg(linux_kernel)] + pub const CONNECTOR: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_CONNECTOR as _) }); + /// `NETLINK_NETFILTER` + #[cfg(linux_kernel)] + pub const NETFILTER: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_NETFILTER as _) }); + /// `NETLINK_IP6_FW` + #[cfg(linux_kernel)] + pub const IP6_FW: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_IP6_FW as _) }); + /// `NETLINK_DNRTMSG` + #[cfg(linux_kernel)] + pub const DNRTMSG: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_DNRTMSG as _) }); + /// `NETLINK_KOBJECT_UEVENT` + #[cfg(linux_kernel)] + pub const KOBJECT_UEVENT: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_KOBJECT_UEVENT as _) }); + /// `NETLINK_GENERIC` + // This is defined on FreeBSD too, but it has the value 0, so it doesn't + // fit in or `NonZeroU32`. It's unclear whether FreeBSD intends + // `NETLINK_GENERIC` to be the default when Linux has `NETLINK_ROUTE` + // as the default. + #[cfg(linux_kernel)] + pub const GENERIC: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_GENERIC as _) }); + /// `NETLINK_SCSITRANSPORT` + #[cfg(linux_kernel)] + pub const SCSITRANSPORT: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_SCSITRANSPORT as _) }); + /// `NETLINK_ECRYPTFS` + #[cfg(linux_kernel)] + pub const ECRYPTFS: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_ECRYPTFS as _) }); + /// `NETLINK_RDMA` + #[cfg(linux_kernel)] + pub const RDMA: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_RDMA as _) }); + /// `NETLINK_CRYPTO` + #[cfg(linux_kernel)] + pub const CRYPTO: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_CRYPTO as _) }); + /// `NETLINK_INET_DIAG` + #[cfg(linux_kernel)] + pub const INET_DIAG: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_INET_DIAG as _) }); + /// `NETLINK_ADD_MEMBERSHIP` + #[cfg(linux_kernel)] + pub const ADD_MEMBERSHIP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_ADD_MEMBERSHIP as _) }); + /// `NETLINK_DROP_MEMBERSHIP` + #[cfg(linux_kernel)] + pub const DROP_MEMBERSHIP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_DROP_MEMBERSHIP as _) }); + /// `NETLINK_PKTINFO` + #[cfg(linux_kernel)] + pub const PKTINFO: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_PKTINFO as _) }); + /// `NETLINK_BROADCAST_ERROR` + #[cfg(linux_kernel)] + pub const BROADCAST_ERROR: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_BROADCAST_ERROR as _) }); + /// `NETLINK_NO_ENOBUFS` + #[cfg(linux_kernel)] + pub const NO_ENOBUFS: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_NO_ENOBUFS as _) }); + /// `NETLINK_RX_RING` + #[cfg(linux_kernel)] + pub const RX_RING: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_RX_RING as _) }); + /// `NETLINK_TX_RING` + #[cfg(linux_kernel)] + pub const TX_RING: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_TX_RING as _) }); + /// `NETLINK_LISTEN_ALL_NSID` + #[cfg(linux_kernel)] + pub const LISTEN_ALL_NSID: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_LISTEN_ALL_NSID as _) }); + /// `NETLINK_LIST_MEMBERSHIPS` + #[cfg(linux_kernel)] + pub const LIST_MEMBERSHIPS: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_LIST_MEMBERSHIPS as _) }); + /// `NETLINK_CAP_ACK` + #[cfg(linux_kernel)] + pub const CAP_ACK: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_CAP_ACK as _) }); + /// `NETLINK_EXT_ACK` + #[cfg(linux_kernel)] + pub const EXT_ACK: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_EXT_ACK as _) }); + /// `NETLINK_GET_STRICT_CHK` + #[cfg(linux_kernel)] + pub const GET_STRICT_CHK: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked(c::NETLINK_GET_STRICT_CHK as _) }); +} + +/// `ETH_P_*` constants. +/// +// These are translated into 16-bit big-endian form because that's what the +// `AddressFamily::PACKET` address family [expects]. +// +// [expects]: https://man7.org/linux/man-pages/man7/packet.7.html +pub mod eth { + #[cfg(linux_kernel)] + use { + super::{Protocol, RawProtocol}, + crate::backend::c, + }; + + /// `ETH_P_LOOP` + #[cfg(linux_kernel)] + pub const LOOP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_LOOP as u16).to_be() as u32) }); + /// `ETH_P_PUP` + #[cfg(linux_kernel)] + pub const PUP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_PUP as u16).to_be() as u32) }); + /// `ETH_P_PUPAT` + #[cfg(linux_kernel)] + pub const PUPAT: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_PUPAT as u16).to_be() as u32) }); + /// `ETH_P_TSN` + #[cfg(linux_kernel)] + pub const TSN: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_TSN as u16).to_be() as u32) }); + /// `ETH_P_ERSPAN2` + #[cfg(linux_kernel)] + pub const ERSPAN2: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_ERSPAN2 as u16).to_be() as u32) }); + /// `ETH_P_IP` + #[cfg(linux_kernel)] + pub const IP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_IP as u16).to_be() as u32) }); + /// `ETH_P_X25` + #[cfg(linux_kernel)] + pub const X25: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_X25 as u16).to_be() as u32) }); + /// `ETH_P_ARP` + #[cfg(linux_kernel)] + pub const ARP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_ARP as u16).to_be() as u32) }); + /// `ETH_P_BPQ` + #[cfg(linux_kernel)] + pub const BPQ: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_BPQ as u16).to_be() as u32) }); + /// `ETH_P_IEEEPUP` + #[cfg(linux_kernel)] + pub const IEEEPUP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_IEEEPUP as u16).to_be() as u32) }); + /// `ETH_P_IEEEPUPAT` + #[cfg(linux_kernel)] + pub const IEEEPUPAT: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_IEEEPUPAT as u16).to_be() as u32) }); + /// `ETH_P_BATMAN` + #[cfg(linux_kernel)] + pub const BATMAN: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_BATMAN as u16).to_be() as u32) }); + /// `ETH_P_DEC` + #[cfg(linux_kernel)] + pub const DEC: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_DEC as u16).to_be() as u32) }); + /// `ETH_P_DNA_DL` + #[cfg(linux_kernel)] + pub const DNA_DL: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_DNA_DL as u16).to_be() as u32) }); + /// `ETH_P_DNA_RC` + #[cfg(linux_kernel)] + pub const DNA_RC: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_DNA_RC as u16).to_be() as u32) }); + /// `ETH_P_DNA_RT` + #[cfg(linux_kernel)] + pub const DNA_RT: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_DNA_RT as u16).to_be() as u32) }); + /// `ETH_P_LAT` + #[cfg(linux_kernel)] + pub const LAT: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_LAT as u16).to_be() as u32) }); + /// `ETH_P_DIAG` + #[cfg(linux_kernel)] + pub const DIAG: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_DIAG as u16).to_be() as u32) }); + /// `ETH_P_CUST` + #[cfg(linux_kernel)] + pub const CUST: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_CUST as u16).to_be() as u32) }); + /// `ETH_P_SCA` + #[cfg(linux_kernel)] + pub const SCA: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_SCA as u16).to_be() as u32) }); + /// `ETH_P_TEB` + #[cfg(linux_kernel)] + pub const TEB: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_TEB as u16).to_be() as u32) }); + /// `ETH_P_RARP` + #[cfg(linux_kernel)] + pub const RARP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_RARP as u16).to_be() as u32) }); + /// `ETH_P_ATALK` + #[cfg(linux_kernel)] + pub const ATALK: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_ATALK as u16).to_be() as u32) }); + /// `ETH_P_AARP` + #[cfg(linux_kernel)] + pub const AARP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_AARP as u16).to_be() as u32) }); + /// `ETH_P_8021Q` + #[cfg(linux_kernel)] + pub const P_8021Q: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_8021Q as u16).to_be() as u32) }); + /// `ETH_P_ERSPAN` + #[cfg(linux_kernel)] + pub const ERSPAN: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_ERSPAN as u16).to_be() as u32) }); + /// `ETH_P_IPX` + #[cfg(linux_kernel)] + pub const IPX: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_IPX as u16).to_be() as u32) }); + /// `ETH_P_IPV6` + #[cfg(linux_kernel)] + pub const IPV6: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_IPV6 as u16).to_be() as u32) }); + /// `ETH_P_PAUSE` + #[cfg(linux_kernel)] + pub const PAUSE: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_PAUSE as u16).to_be() as u32) }); + /// `ETH_P_SLOW` + #[cfg(linux_kernel)] + pub const SLOW: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_SLOW as u16).to_be() as u32) }); + /// `ETH_P_WCCP` + #[cfg(linux_kernel)] + pub const WCCP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_WCCP as u16).to_be() as u32) }); + /// `ETH_P_MPLS_UC` + #[cfg(linux_kernel)] + pub const MPLS_UC: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_MPLS_UC as u16).to_be() as u32) }); + /// `ETH_P_MPLS_MC` + #[cfg(linux_kernel)] + pub const MPLS_MC: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_MPLS_MC as u16).to_be() as u32) }); + /// `ETH_P_ATMMPOA` + #[cfg(linux_kernel)] + pub const ATMMPOA: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_ATMMPOA as u16).to_be() as u32) }); + /// `ETH_P_PPP_DISC` + #[cfg(linux_kernel)] + pub const PPP_DISC: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_PPP_DISC as u16).to_be() as u32) }); + /// `ETH_P_PPP_SES` + #[cfg(linux_kernel)] + pub const PPP_SES: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_PPP_SES as u16).to_be() as u32) }); + /// `ETH_P_LINK_CTL` + #[cfg(linux_kernel)] + pub const LINK_CTL: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_LINK_CTL as u16).to_be() as u32) }); + /// `ETH_P_ATMFATE` + #[cfg(linux_kernel)] + pub const ATMFATE: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_ATMFATE as u16).to_be() as u32) }); + /// `ETH_P_PAE` + #[cfg(linux_kernel)] + pub const PAE: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_PAE as u16).to_be() as u32) }); + /// `ETH_P_PROFINET` + #[cfg(linux_kernel)] + pub const PROFINET: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_PROFINET as u16).to_be() as u32) }); + /// `ETH_P_REALTEK` + #[cfg(linux_kernel)] + pub const REALTEK: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_REALTEK as u16).to_be() as u32) }); + /// `ETH_P_AOE` + #[cfg(linux_kernel)] + pub const AOE: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_AOE as u16).to_be() as u32) }); + /// `ETH_P_ETHERCAT` + #[cfg(linux_kernel)] + pub const ETHERCAT: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_ETHERCAT as u16).to_be() as u32) }); + /// `ETH_P_8021AD` + #[cfg(linux_kernel)] + pub const P_8021AD: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_8021AD as u16).to_be() as u32) }); + /// `ETH_P_802_EX1` + #[cfg(linux_kernel)] + pub const P_802_EX1: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_802_EX1 as u16).to_be() as u32) }); + /// `ETH_P_PREAUTH` + #[cfg(linux_kernel)] + pub const PREAUTH: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_PREAUTH as u16).to_be() as u32) }); + /// `ETH_P_TIPC` + #[cfg(linux_kernel)] + pub const TIPC: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_TIPC as u16).to_be() as u32) }); + /// `ETH_P_LLDP` + #[cfg(linux_kernel)] + pub const LLDP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_LLDP as u16).to_be() as u32) }); + /// `ETH_P_MRP` + #[cfg(linux_kernel)] + pub const MRP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_MRP as u16).to_be() as u32) }); + /// `ETH_P_MACSEC` + #[cfg(linux_kernel)] + pub const MACSEC: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_MACSEC as u16).to_be() as u32) }); + /// `ETH_P_8021AH` + #[cfg(linux_kernel)] + pub const P_8021AH: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_8021AH as u16).to_be() as u32) }); + /// `ETH_P_MVRP` + #[cfg(linux_kernel)] + pub const MVRP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_MVRP as u16).to_be() as u32) }); + /// `ETH_P_1588` + #[cfg(linux_kernel)] + pub const P_1588: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_1588 as u16).to_be() as u32) }); + /// `ETH_P_NCSI` + #[cfg(linux_kernel)] + pub const NCSI: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_NCSI as u16).to_be() as u32) }); + /// `ETH_P_PRP` + #[cfg(linux_kernel)] + pub const PRP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_PRP as u16).to_be() as u32) }); + /// `ETH_P_CFM` + #[cfg(linux_kernel)] + pub const CFM: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_CFM as u16).to_be() as u32) }); + /// `ETH_P_FCOE` + #[cfg(linux_kernel)] + pub const FCOE: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_FCOE as u16).to_be() as u32) }); + /// `ETH_P_IBOE` + #[cfg(linux_kernel)] + pub const IBOE: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_IBOE as u16).to_be() as u32) }); + /// `ETH_P_TDLS` + #[cfg(linux_kernel)] + pub const TDLS: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_TDLS as u16).to_be() as u32) }); + /// `ETH_P_FIP` + #[cfg(linux_kernel)] + pub const FIP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_FIP as u16).to_be() as u32) }); + /// `ETH_P_80221` + #[cfg(linux_kernel)] + pub const P_80221: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_80221 as u16).to_be() as u32) }); + /// `ETH_P_HSR` + #[cfg(linux_kernel)] + pub const HSR: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_HSR as u16).to_be() as u32) }); + /// `ETH_P_NSH` + #[cfg(linux_kernel)] + pub const NSH: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_NSH as u16).to_be() as u32) }); + /// `ETH_P_LOOPBACK` + #[cfg(linux_kernel)] + pub const LOOPBACK: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_LOOPBACK as u16).to_be() as u32) }); + /// `ETH_P_QINQ1` + #[cfg(linux_kernel)] + pub const QINQ1: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_QINQ1 as u16).to_be() as u32) }); + /// `ETH_P_QINQ2` + #[cfg(linux_kernel)] + pub const QINQ2: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_QINQ2 as u16).to_be() as u32) }); + /// `ETH_P_QINQ3` + #[cfg(linux_kernel)] + pub const QINQ3: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_QINQ3 as u16).to_be() as u32) }); + /// `ETH_P_EDSA` + #[cfg(linux_kernel)] + pub const EDSA: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_EDSA as u16).to_be() as u32) }); + /// `ETH_P_DSA_8021Q` + #[cfg(linux_kernel)] + pub const DSA_8021Q: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_DSA_8021Q as u16).to_be() as u32) }); + /// `ETH_P_DSA_A5PSW` + #[cfg(linux_kernel)] + pub const DSA_A5PSW: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_DSA_A5PSW as u16).to_be() as u32) }); + /// `ETH_P_IFE` + #[cfg(linux_kernel)] + pub const IFE: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_IFE as u16).to_be() as u32) }); + /// `ETH_P_AF_IUCV` + #[cfg(linux_kernel)] + pub const AF_IUCV: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_AF_IUCV as u16).to_be() as u32) }); + /// `ETH_P_802_3_MIN` + #[cfg(linux_kernel)] + pub const P_802_3_MIN: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_802_3_MIN as u16).to_be() as u32) }); + /// `ETH_P_802_3` + #[cfg(linux_kernel)] + pub const P_802_3: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_802_3 as u16).to_be() as u32) }); + /// `ETH_P_AX25` + #[cfg(linux_kernel)] + pub const AX25: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_AX25 as u16).to_be() as u32) }); + /// `ETH_P_ALL` + #[cfg(linux_kernel)] + pub const ALL: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_ALL as u16).to_be() as u32) }); + /// `ETH_P_802_2` + #[cfg(linux_kernel)] + pub const P_802_2: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_802_2 as u16).to_be() as u32) }); + /// `ETH_P_SNAP` + #[cfg(linux_kernel)] + pub const SNAP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_SNAP as u16).to_be() as u32) }); + /// `ETH_P_DDCMP` + #[cfg(linux_kernel)] + pub const DDCMP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_DDCMP as u16).to_be() as u32) }); + /// `ETH_P_WAN_PPP` + #[cfg(linux_kernel)] + pub const WAN_PPP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_WAN_PPP as u16).to_be() as u32) }); + /// `ETH_P_PPP_MP` + #[cfg(linux_kernel)] + pub const PPP_MP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_PPP_MP as u16).to_be() as u32) }); + /// `ETH_P_LOCALTALK` + #[cfg(linux_kernel)] + pub const LOCALTALK: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_LOCALTALK as u16).to_be() as u32) }); + /// `ETH_P_CAN` + #[cfg(linux_kernel)] + pub const CAN: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_CAN as u16).to_be() as u32) }); + /// `ETH_P_CANFD` + #[cfg(linux_kernel)] + pub const CANFD: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_CANFD as u16).to_be() as u32) }); + /// `ETH_P_CANXL` + #[cfg(linux_kernel)] + pub const CANXL: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_CANXL as u16).to_be() as u32) }); + /// `ETH_P_PPPTALK` + #[cfg(linux_kernel)] + pub const PPPTALK: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_PPPTALK as u16).to_be() as u32) }); + /// `ETH_P_TR_802_2` + #[cfg(linux_kernel)] + pub const TR_802_2: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_TR_802_2 as u16).to_be() as u32) }); + /// `ETH_P_MOBITEX` + #[cfg(linux_kernel)] + pub const MOBITEX: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_MOBITEX as u16).to_be() as u32) }); + /// `ETH_P_CONTROL` + #[cfg(linux_kernel)] + pub const CONTROL: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_CONTROL as u16).to_be() as u32) }); + /// `ETH_P_IRDA` + #[cfg(linux_kernel)] + pub const IRDA: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_IRDA as u16).to_be() as u32) }); + /// `ETH_P_ECONET` + #[cfg(linux_kernel)] + pub const ECONET: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_ECONET as u16).to_be() as u32) }); + /// `ETH_P_HDLC` + #[cfg(linux_kernel)] + pub const HDLC: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_HDLC as u16).to_be() as u32) }); + /// `ETH_P_ARCNET` + #[cfg(linux_kernel)] + pub const ARCNET: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_ARCNET as u16).to_be() as u32) }); + /// `ETH_P_DSA` + #[cfg(linux_kernel)] + pub const DSA: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_DSA as u16).to_be() as u32) }); + /// `ETH_P_TRAILER` + #[cfg(linux_kernel)] + pub const TRAILER: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_TRAILER as u16).to_be() as u32) }); + /// `ETH_P_PHONET` + #[cfg(linux_kernel)] + pub const PHONET: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_PHONET as u16).to_be() as u32) }); + /// `ETH_P_IEEE802154` + #[cfg(linux_kernel)] + pub const IEEE802154: Protocol = Protocol(unsafe { + RawProtocol::new_unchecked((c::ETH_P_IEEE802154 as u16).to_be() as u32) + }); + /// `ETH_P_CAIF` + #[cfg(linux_kernel)] + pub const CAIF: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_CAIF as u16).to_be() as u32) }); + /// `ETH_P_XDSA` + #[cfg(linux_kernel)] + pub const XDSA: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_XDSA as u16).to_be() as u32) }); + /// `ETH_P_MAP` + #[cfg(linux_kernel)] + pub const MAP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_MAP as u16).to_be() as u32) }); + /// `ETH_P_MCTP` + #[cfg(linux_kernel)] + pub const MCTP: Protocol = + Protocol(unsafe { RawProtocol::new_unchecked((c::ETH_P_MCTP as u16).to_be() as u32) }); +} + +#[rustfmt::skip] +impl Protocol { + /// Constructs a `Protocol` from a raw integer. + #[inline] + pub const fn from_raw(raw: RawProtocol) -> Self { + Self(raw) + } + + /// Returns the raw integer for this `Protocol`. + #[inline] + pub const fn as_raw(self) -> RawProtocol { + self.0 + } +} + +/// `SHUT_*` constants for use with [`shutdown`]. +/// +/// [`shutdown`]: crate::net::shutdown +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[repr(u32)] +pub enum Shutdown { + /// `SHUT_RD`—Disable further read operations. + Read = c::SHUT_RD as _, + /// `SHUT_WR`—Disable further write operations. + Write = c::SHUT_WR as _, + /// `SHUT_RDWR`—Disable further read and write operations. + ReadWrite = c::SHUT_RDWR as _, +} + +bitflags! { + /// `SOCK_*` constants for use with [`socket_with`], [`accept_with`] and + /// [`acceptfrom_with`]. + /// + /// [`socket_with`]: crate::net::socket_with + /// [`accept_with`]: crate::net::accept_with + /// [`acceptfrom_with`]: crate::net::acceptfrom_with + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct SocketFlags: c::c_uint { + /// `SOCK_NONBLOCK` + #[cfg(not(any(apple, windows, target_os = "haiku")))] + const NONBLOCK = bitcast!(c::SOCK_NONBLOCK); + + /// `SOCK_CLOEXEC` + #[cfg(not(any(apple, windows, target_os = "haiku")))] + const CLOEXEC = bitcast!(c::SOCK_CLOEXEC); + } +} + +#[test] +fn test_sizes() { + use c::c_int; + use core::mem::size_of; + + // Backend code needs to cast these to `c_int` so make sure that cast + // isn't lossy. + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::>(), size_of::()); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); +} diff --git a/vendor/rustix/src/param/mod.rs b/vendor/rustix/src/param/mod.rs index c3838b62e..dde09772a 100644 --- a/vendor/rustix/src/param/mod.rs +++ b/vendor/rustix/src/param/mod.rs @@ -5,12 +5,10 @@ //! parameters; they're *process* configuration parameters, as they may differ //! between different processes on the same system. -#[cfg(feature = "param")] mod auxv; #[cfg(target_vendor = "mustang")] mod init; -#[cfg(feature = "param")] pub use auxv::*; #[cfg(target_vendor = "mustang")] pub use init::init; diff --git a/vendor/rustix/src/path/arg.rs b/vendor/rustix/src/path/arg.rs index b6b2a8a73..64091611c 100644 --- a/vendor/rustix/src/path/arg.rs +++ b/vendor/rustix/src/path/arg.rs @@ -19,17 +19,13 @@ use core::mem::MaybeUninit; use core::{ptr, slice, str}; #[cfg(feature = "std")] use std::ffi::{OsStr, OsString}; -#[cfg(feature = "std")] -#[cfg(target_os = "hermit")] +#[cfg(all(feature = "std", target_os = "hermit"))] use std::os::hermit::ext::ffi::{OsStrExt, OsStringExt}; -#[cfg(feature = "std")] -#[cfg(unix)] +#[cfg(all(feature = "std", unix))] use std::os::unix::ffi::{OsStrExt, OsStringExt}; -#[cfg(feature = "std")] -#[cfg(target_os = "vxworks")] +#[cfg(all(feature = "std", target_os = "vxworks"))] use std::os::vxworks::ext::ffi::{OsStrExt, OsStringExt}; -#[cfg(feature = "std")] -#[cfg(target_os = "wasi")] +#[cfg(all(feature = "std", target_os = "wasi"))] use std::os::wasi::ffi::{OsStrExt, OsStringExt}; #[cfg(feature = "std")] use std::path::{Component, Components, Iter, Path, PathBuf}; @@ -952,13 +948,13 @@ where // Taken from // let mut buf = MaybeUninit::<[u8; SMALL_PATH_BUFFER_SIZE]>::uninit(); - let buf_ptr = buf.as_mut_ptr() as *mut u8; + let buf_ptr = buf.as_mut_ptr().cast::(); // This helps test our safety condition below. debug_assert!(bytes.len() + 1 <= SMALL_PATH_BUFFER_SIZE); - // SAFETY: `bytes.len() < SMALL_PATH_BUFFER_SIZE` which means we have space for - // `bytes.len() + 1` u8s: + // SAFETY: `bytes.len() < SMALL_PATH_BUFFER_SIZE` which means we have space + // for `bytes.len() + 1` u8s: unsafe { ptr::copy_nonoverlapping(bytes.as_ptr(), buf_ptr, bytes.len()); buf_ptr.add(bytes.len()).write(0); diff --git a/vendor/rustix/src/path/dec_int.rs b/vendor/rustix/src/path/dec_int.rs index 5ba8be4fc..04c97d406 100644 --- a/vendor/rustix/src/path/dec_int.rs +++ b/vendor/rustix/src/path/dec_int.rs @@ -8,20 +8,14 @@ use crate::backend::fd::{AsFd, AsRawFd}; use crate::ffi::CStr; -#[cfg(feature = "std")] -use core::fmt; use core::fmt::Write; use itoa::{Buffer, Integer}; -#[cfg(feature = "std")] -use std::ffi::OsStr; -#[cfg(feature = "std")] -#[cfg(unix)] +#[cfg(all(feature = "std", unix))] use std::os::unix::ffi::OsStrExt; -#[cfg(feature = "std")] -#[cfg(target_os = "wasi")] +#[cfg(all(feature = "std", target_os = "wasi"))] use std::os::wasi::ffi::OsStrExt; #[cfg(feature = "std")] -use std::path::Path; +use {core::fmt, std::ffi::OsStr, std::path::Path}; /// Format an integer into a decimal `Path` component, without constructing a /// temporary `PathBuf` or `String`. @@ -31,10 +25,10 @@ use std::path::Path; /// # Example /// /// ``` -/// # #[cfg(feature = "path")] +/// # #[cfg(any(feature = "fs", feature = "net"))] /// use rustix::path::DecInt; /// -/// # #[cfg(feature = "path")] +/// # #[cfg(any(feature = "fs", feature = "net"))] /// assert_eq!( /// format!("hello {}", DecInt::new(9876).as_ref().display()), /// "hello 9876" diff --git a/vendor/rustix/src/path/mod.rs b/vendor/rustix/src/path/mod.rs index bd6e9fc8b..19bf2c7f0 100644 --- a/vendor/rustix/src/path/mod.rs +++ b/vendor/rustix/src/path/mod.rs @@ -6,6 +6,7 @@ mod dec_int; pub use arg::Arg; #[cfg(feature = "itoa")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "itoa")))] pub use dec_int::DecInt; pub(crate) const SMALL_PATH_BUFFER_SIZE: usize = 256; diff --git a/vendor/rustix/src/pid.rs b/vendor/rustix/src/pid.rs new file mode 100644 index 000000000..bebc1f00c --- /dev/null +++ b/vendor/rustix/src/pid.rs @@ -0,0 +1,93 @@ +#![allow(unsafe_code)] + +use crate::backend::c; +use core::num::NonZeroI32; + +/// A process identifier as a raw integer. +pub type RawPid = c::pid_t; + +/// `pid_t`—A non-zero Unix process ID. +/// +/// This is a pid, and not a pidfd. It is not a file descriptor, and the +/// process it refers to could disappear at any time and be replaced by +/// another, unrelated, process. +#[repr(transparent)] +#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)] +pub struct Pid(NonZeroI32); + +impl Pid { + /// A `Pid` corresponding to the init process (pid 1). + pub const INIT: Self = Self( + // SAFETY: One is non-zero. + unsafe { NonZeroI32::new_unchecked(1) }, + ); + + /// Converts a `RawPid` into a `Pid`. + /// + /// Returns `Some` for strictly positive `RawPid`s. Otherwise, returns + /// `None`. + /// + /// This is always safe because a `Pid` is a number without any guarantees + /// for the kernel. Non-child `Pid`s are always racy for any syscalls, + /// but can only cause logic errors. If you want race-free access or + /// control to non-child processes, please consider other mechanisms + /// like [pidfd] on Linux. + /// + /// [pidfd]: https://man7.org/linux/man-pages/man2/pidfd_open.2.html + #[inline] + pub const fn from_raw(raw: RawPid) -> Option { + if raw > 0 { + // SAFETY: raw > 0. + unsafe { Some(Self::from_raw_unchecked(raw)) } + } else { + None + } + } + + /// Converts a known strictly positive `RawPid` into a `Pid`. + /// + /// # Safety + /// + /// The caller must guarantee `raw` is strictly positive. + #[inline] + pub const unsafe fn from_raw_unchecked(raw: RawPid) -> Self { + debug_assert!(raw > 0); + Self(NonZeroI32::new_unchecked(raw)) + } + + /// Creates a `Pid` holding the ID of the given child process. + #[cfg(feature = "std")] + #[inline] + pub fn from_child(child: &std::process::Child) -> Self { + let id = child.id(); + // SAFETY: We know the returned ID is valid because it came directly + // from an OS API. + unsafe { Self::from_raw_unchecked(id as i32) } + } + + /// Converts a `Pid` into a `NonZeroI32`. + #[inline] + pub const fn as_raw_nonzero(self) -> NonZeroI32 { + self.0 + } + + /// Converts an `Option` into a `RawPid`. + #[inline] + pub fn as_raw(pid: Option) -> RawPid { + pid.map_or(0, |pid| pid.0.get()) + } + + /// Test whether this pid represents the init process (pid 1). + #[inline] + pub const fn is_init(self) -> bool { + self.0.get() == Self::INIT.0.get() + } +} + +#[test] +fn test_sizes() { + use core::mem::size_of; + + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); +} diff --git a/vendor/rustix/src/pipe.rs b/vendor/rustix/src/pipe.rs new file mode 100644 index 000000000..a4c300abd --- /dev/null +++ b/vendor/rustix/src/pipe.rs @@ -0,0 +1,209 @@ +//! `pipe` and related APIs. +//! +//! # Safety +//! +//! `vmsplice` is an unsafe function. + +#![allow(unsafe_code)] + +use crate::fd::OwnedFd; +use crate::{backend, io}; +#[cfg(not(any( + solarish, + windows, + target_os = "haiku", + target_os = "redox", + target_os = "wasi", +)))] +use backend::c; +#[cfg(linux_kernel)] +use backend::fd::AsFd; + +#[cfg(not(apple))] +pub use backend::pipe::types::PipeFlags; + +#[cfg(linux_kernel)] +pub use backend::pipe::types::{IoSliceRaw, SpliceFlags}; + +/// `PIPE_BUF`—The maximum length at which writes to a pipe are atomic. +/// +/// # References +/// - [Linux] +/// - [POSIX] +/// +/// [Linux]: https://man7.org/linux/man-pages/man7/pipe.7.html +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html +#[cfg(not(any( + solarish, + windows, + target_os = "haiku", + target_os = "redox", + target_os = "wasi", +)))] +pub const PIPE_BUF: usize = c::PIPE_BUF; + +/// `pipe()`—Creates a pipe. +/// +/// This function creates a pipe and returns two file descriptors, for the +/// reading and writing ends of the pipe, respectively. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html +/// [Linux]: https://man7.org/linux/man-pages/man2/pipe.2.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/pipe.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=pipe&sektion=2 +/// [NetBSD]: https://man.netbsd.org/pipe.2 +/// [OpenBSD]: https://man.openbsd.org/pipe.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=pipe§ion=2 +/// [illumos]: https://illumos.org/man/2/pipe +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Creating-a-Pipe.html +#[inline] +pub fn pipe() -> io::Result<(OwnedFd, OwnedFd)> { + backend::pipe::syscalls::pipe() +} + +/// `pipe2(flags)`—Creates a pipe, with flags. +/// +/// This function creates a pipe and returns two file descriptors, for the +/// reading and writing ends of the pipe, respectively. +/// +/// # References +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/pipe2.2.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=pipe2&sektion=2 +/// [NetBSD]: https://man.netbsd.org/pipe2.2 +/// [OpenBSD]: https://man.openbsd.org/pipe2.2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=pipe2§ion=2 +/// [illumos]: https://illumos.org/man/2/pipe2 +#[cfg(not(any(apple, target_os = "aix", target_os = "haiku")))] +#[inline] +#[doc(alias = "pipe2")] +pub fn pipe_with(flags: PipeFlags) -> io::Result<(OwnedFd, OwnedFd)> { + backend::pipe::syscalls::pipe_with(flags) +} + +/// `splice(fd_in, off_in, fd_out, off_out, len, flags)`—Transfer data between +/// a file and a pipe. +/// +/// This function transfers up to `len` bytes of data from the file descriptor +/// `fd_in` to the file descriptor `fd_out`, where one of the file descriptors +/// must refer to a pipe. +/// +/// `off_*` must be `None` if the corresponding fd refers to a pipe. +/// Otherwise its value points to the starting offset to the file, +/// from which the data is read/written. +/// on success the number of bytes read/written is added to the offset. +/// +/// passing `None` causes the read/write to start from the file offset, +/// and the file offset is adjusted appropriately. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/splice.2.html +#[cfg(linux_kernel)] +#[inline] +pub fn splice( + fd_in: FdIn, + off_in: Option<&mut u64>, + fd_out: FdOut, + off_out: Option<&mut u64>, + len: usize, + flags: SpliceFlags, +) -> io::Result { + backend::pipe::syscalls::splice(fd_in.as_fd(), off_in, fd_out.as_fd(), off_out, len, flags) +} + +/// `vmsplice(fd, bufs, flags)`—Transfer data between memory and a pipe. +/// +/// If `fd` is the write end of the pipe, +/// the function maps the memory pointer at by `bufs` to the pipe. +/// +/// If `fd` is the read end of the pipe, +/// the function writes data from the pipe to said memory. +/// +/// # Safety +/// +/// If the memory must not be mutated (such as when `bufs` were originally +/// immutable slices), it is up to the caller to ensure that the write end of +/// the pipe is placed in `fd`. +/// +/// Additionally if `SpliceFlags::GIFT` is set, the caller must also ensure +/// that the contents of `bufs` in never modified following the call, +/// and that all of the pointers in `bufs` are page aligned, +/// and the lengths are multiples of a page size in bytes. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/vmsplice.2.html +#[cfg(linux_kernel)] +#[inline] +pub unsafe fn vmsplice( + fd: PipeFd, + bufs: &[IoSliceRaw], + flags: SpliceFlags, +) -> io::Result { + backend::pipe::syscalls::vmsplice(fd.as_fd(), bufs, flags) +} + +/// `tee(fd_in, fd_out, len, flags)`—Copy data between pipes without +/// consuming it. +/// +/// This reads up to `len` bytes from `in_fd` without consuming them, and +/// writes them to `out_fd`. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/tee.2.html +#[cfg(linux_kernel)] +#[inline] +pub fn tee( + fd_in: FdIn, + fd_out: FdOut, + len: usize, + flags: SpliceFlags, +) -> io::Result { + backend::pipe::syscalls::tee(fd_in.as_fd(), fd_out.as_fd(), len, flags) +} + +/// `ioctl(fd, F_GETPIPE_SZ)`—Return the buffer capacity of a pipe. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html +#[cfg(linux_kernel)] +#[inline] +pub fn fcntl_getpipe_size(fd: Fd) -> io::Result { + backend::pipe::syscalls::fcntl_getpipe_sz(fd.as_fd()) +} + +/// `ioctl(fd, F_SETPIPE_SZ)`—Set the buffer capacity of a pipe. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html +#[cfg(linux_kernel)] +#[inline] +pub fn fcntl_setpipe_size(fd: Fd, size: usize) -> io::Result<()> { + backend::pipe::syscalls::fcntl_setpipe_sz(fd.as_fd(), size) +} diff --git a/vendor/rustix/src/prctl.rs b/vendor/rustix/src/prctl.rs new file mode 100644 index 000000000..49cb062d6 --- /dev/null +++ b/vendor/rustix/src/prctl.rs @@ -0,0 +1,68 @@ +//! Helper functions for `prctl` syscalls. + +#![allow(unsafe_code)] + +use crate::backend::c::{c_int, c_void}; +use crate::backend::prctl::syscalls; +use crate::io; +use crate::utils::as_mut_ptr; +use bitflags::bitflags; +use core::mem::MaybeUninit; +use core::ptr::null_mut; + +bitflags! { + /// `PR_PAC_AP*`. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct PointerAuthenticationKeys: u32 { + /// `PR_PAC_APIAKEY`—Instruction authentication key `A`. + const INSTRUCTION_AUTHENTICATION_KEY_A = linux_raw_sys::prctl::PR_PAC_APIAKEY; + /// `PR_PAC_APIBKEY`—Instruction authentication key `B`. + const INSTRUCTION_AUTHENTICATION_KEY_B = linux_raw_sys::prctl::PR_PAC_APIBKEY; + /// `PR_PAC_APDAKEY`—Data authentication key `A`. + const DATA_AUTHENTICATION_KEY_A = linux_raw_sys::prctl::PR_PAC_APDAKEY; + /// `PR_PAC_APDBKEY`—Data authentication key `B`. + const DATA_AUTHENTICATION_KEY_B = linux_raw_sys::prctl::PR_PAC_APDBKEY; + /// `PR_PAC_APGAKEY`—Generic authentication `A` key. + const GENERIC_AUTHENTICATION_KEY_A = linux_raw_sys::prctl::PR_PAC_APGAKEY; + } +} + +#[inline] +pub(crate) unsafe fn prctl_1arg(option: c_int) -> io::Result { + const NULL: *mut c_void = null_mut(); + syscalls::prctl(option, NULL, NULL, NULL, NULL) +} + +#[inline] +pub(crate) unsafe fn prctl_2args(option: c_int, arg2: *mut c_void) -> io::Result { + const NULL: *mut c_void = null_mut(); + syscalls::prctl(option, arg2, NULL, NULL, NULL) +} + +#[inline] +pub(crate) unsafe fn prctl_3args( + option: c_int, + arg2: *mut c_void, + arg3: *mut c_void, +) -> io::Result { + syscalls::prctl(option, arg2, arg3, null_mut(), null_mut()) +} + +#[inline] +pub(crate) unsafe fn prctl_get_at_arg2_optional

(option: i32) -> io::Result

{ + let mut value: MaybeUninit

= MaybeUninit::uninit(); + prctl_2args(option, value.as_mut_ptr().cast())?; + Ok(value.assume_init()) +} + +#[inline] +pub(crate) unsafe fn prctl_get_at_arg2(option: i32) -> io::Result +where + P: Default, + T: TryFrom, +{ + let mut value: P = Default::default(); + prctl_2args(option, as_mut_ptr(&mut value).cast())?; + TryFrom::try_from(value) +} diff --git a/vendor/rustix/src/process/chdir.rs b/vendor/rustix/src/process/chdir.rs index 4951e5670..0da0b5c2e 100644 --- a/vendor/rustix/src/process/chdir.rs +++ b/vendor/rustix/src/process/chdir.rs @@ -1,9 +1,13 @@ -use crate::ffi::CString; -use crate::path::SMALL_PATH_BUFFER_SIZE; -use crate::{backend, io, path}; -use alloc::vec::Vec; #[cfg(not(target_os = "fuchsia"))] -use backend::fd::AsFd; +use crate::backend::fd::AsFd; +#[cfg(any(feature = "fs", not(target_os = "fuchsia")))] +use crate::{backend, io}; +#[cfg(feature = "fs")] +use { + crate::ffi::{CStr, CString}, + crate::path::{self, SMALL_PATH_BUFFER_SIZE}, + alloc::vec::Vec, +}; /// `chdir(path)`—Change the current working directory. /// @@ -14,6 +18,8 @@ use backend::fd::AsFd; /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html /// [Linux]: https://man7.org/linux/man-pages/man2/chdir.2.html #[inline] +#[cfg(feature = "fs")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "fs")))] pub fn chdir(path: P) -> io::Result<()> { path.into_with_c_str(backend::process::syscalls::chdir) } @@ -32,9 +38,9 @@ pub fn fchdir(fd: Fd) -> io::Result<()> { backend::process::syscalls::fchdir(fd.as_fd()) } -/// `getcwd()`—Return the current working directory. +/// `getCWD`—Return the current working directory. /// -/// If `reuse` is non-empty, reuse its buffer to store the result if possible. +/// If `reuse` already has available capacity, reuse it if possible. /// /// # References /// - [POSIX] @@ -42,29 +48,43 @@ pub fn fchdir(fd: Fd) -> io::Result<()> { /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html /// [Linux]: https://man7.org/linux/man-pages/man3/getcwd.3.html +#[cfg(feature = "fs")] #[cfg(not(target_os = "wasi"))] +#[cfg_attr(doc_cfg, doc(cfg(feature = "fs")))] #[inline] pub fn getcwd>>(reuse: B) -> io::Result { _getcwd(reuse.into()) } +#[cfg(feature = "fs")] +#[allow(unsafe_code)] fn _getcwd(mut buffer: Vec) -> io::Result { - // This code would benefit from having a better way to read into - // uninitialized memory, but that requires `unsafe`. buffer.clear(); buffer.reserve(SMALL_PATH_BUFFER_SIZE); - buffer.resize(buffer.capacity(), 0_u8); loop { - match backend::process::syscalls::getcwd(&mut buffer) { + match backend::process::syscalls::getcwd(buffer.spare_capacity_mut()) { Err(io::Errno::RANGE) => { - buffer.reserve(1); // use `Vec` reallocation strategy to grow capacity exponentially - buffer.resize(buffer.capacity(), 0_u8); + buffer.reserve(buffer.capacity() + 1); // use `Vec` reallocation strategy to grow capacity exponentially } Ok(_) => { - let len = buffer.iter().position(|x| *x == b'\0').unwrap(); - buffer.resize(len, 0_u8); - return Ok(CString::new(buffer).unwrap()); + // SAFETY: + // - "These functions return a null-terminated string" + // - [POSIX definition 3.375: String]: "A contiguous sequence of bytes + // terminated by and including the first null byte." + // + // Thus, there will be a single NUL byte at the end of the string. + // + // [POSIX definition 3.375: String]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_375 + unsafe { + buffer.set_len( + CStr::from_ptr(buffer.as_ptr().cast()) + .to_bytes_with_nul() + .len(), + ); + + return Ok(CString::from_vec_with_nul_unchecked(buffer)); + } } Err(errno) => return Err(errno), } diff --git a/vendor/rustix/src/process/chroot.rs b/vendor/rustix/src/process/chroot.rs index d68a8b081..a4fd8d852 100644 --- a/vendor/rustix/src/process/chroot.rs +++ b/vendor/rustix/src/process/chroot.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "fs")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "fs")))] use crate::{backend, io, path}; /// `chroot(path)`—Change the process root directory. @@ -6,6 +8,8 @@ use crate::{backend, io, path}; /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/chroot.2.html +#[cfg(feature = "fs")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "fs")))] #[inline] pub fn chroot(path: P) -> io::Result<()> { path.into_with_c_str(backend::process::syscalls::chroot) diff --git a/vendor/rustix/src/process/id.rs b/vendor/rustix/src/process/id.rs index 687596a31..4cacf1ab0 100644 --- a/vendor/rustix/src/process/id.rs +++ b/vendor/rustix/src/process/id.rs @@ -9,163 +9,28 @@ use crate::{backend, io}; use alloc::vec::Vec; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] use backend::process::types::RawCpuid; /// The raw integer value of a Unix user ID. -pub use backend::process::types::RawUid; +pub use crate::ugid::RawUid; /// The raw integer value of a Unix group ID. -pub use backend::process::types::RawGid; +pub use crate::ugid::RawGid; /// The raw integer value of a Unix process ID. -pub use backend::process::types::RawPid; +pub use crate::pid::RawPid; -/// The raw integer value of a Unix process ID. -pub use backend::process::types::RawNonZeroPid; - -/// `uid_t`—A Unix user ID. -#[repr(transparent)] -#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)] -pub struct Uid(RawUid); - -/// `gid_t`—A Unix group ID. -#[repr(transparent)] -#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)] -pub struct Gid(RawGid); - -/// `pid_t`—A non-zero Unix process ID. -/// -/// This is a pid, and not a pidfd. It is not a file descriptor, and the -/// process it refers to could disappear at any time and be replaced by -/// another, unrelated, process. -#[repr(transparent)] -#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)] -pub struct Pid(RawNonZeroPid); +pub use crate::pid::Pid; +pub use crate::ugid::{Gid, Uid}; /// A Linux CPU ID. -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[repr(transparent)] #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)] pub struct Cpuid(RawCpuid); -impl Uid { - /// A `Uid` corresponding to the root user (uid 0). - pub const ROOT: Self = Self(0); - - /// Converts a `RawUid` into a `Uid`. - /// - /// # Safety - /// - /// `raw` must be the value of a valid Unix user ID. - #[inline] - pub const unsafe fn from_raw(raw: RawUid) -> Self { - Self(raw) - } - - /// Converts a `Uid` into a `RawUid`. - #[inline] - pub const fn as_raw(self) -> RawUid { - self.0 - } - - /// Test whether this uid represents the root user (uid 0). - #[inline] - pub const fn is_root(self) -> bool { - self.0 == Self::ROOT.0 - } -} - -impl Gid { - /// A `Gid` corresponding to the root group (gid 0). - pub const ROOT: Self = Self(0); - - /// Converts a `RawGid` into a `Gid`. - /// - /// # Safety - /// - /// `raw` must be the value of a valid Unix group ID. - #[inline] - pub const unsafe fn from_raw(raw: RawGid) -> Self { - Self(raw) - } - - /// Converts a `Gid` into a `RawGid`. - #[inline] - pub const fn as_raw(self) -> RawGid { - self.0 - } - - /// Test whether this gid represents the root group (gid 0). - #[inline] - pub const fn is_root(self) -> bool { - self.0 == Self::ROOT.0 - } -} - -impl Pid { - /// A `Pid` corresponding to the init process (pid 1). - pub const INIT: Self = Self( - // SAFETY: The init process' pid is always valid. - unsafe { RawNonZeroPid::new_unchecked(1) }, - ); - - /// Converts a `RawPid` into a `Pid`. - /// - /// # Safety - /// - /// `raw` must be the value of a valid Unix process ID, or zero. - #[inline] - pub const unsafe fn from_raw(raw: RawPid) -> Option { - match RawNonZeroPid::new(raw) { - Some(pid) => Some(Self(pid)), - None => None, - } - } - - /// Converts a known non-zero `RawPid` into a `Pid`. - /// - /// # Safety - /// - /// `raw` must be the value of a valid Unix process ID. It must not be - /// zero. - #[inline] - pub const unsafe fn from_raw_nonzero(raw: RawNonZeroPid) -> Self { - Self(raw) - } - - /// Creates a `Pid` holding the ID of the given child process. - #[cfg(feature = "std")] - #[inline] - pub fn from_child(child: &std::process::Child) -> Self { - let id = child.id(); - debug_assert_ne!(id, 0); - - // SAFETY: We know the returned ID is valid because it came directly - // from an OS API. - unsafe { Self::from_raw_nonzero(RawNonZeroPid::new_unchecked(id as _)) } - } - - /// Converts a `Pid` into a `RawNonZeroPid`. - #[inline] - pub const fn as_raw_nonzero(self) -> RawNonZeroPid { - self.0 - } - - /// Converts an `Option` into a `RawPid`. - #[inline] - pub fn as_raw(pid: Option) -> RawPid { - pid.map_or(0, |pid| pid.0.get()) - } - - /// Test whether this pid represents the init process (pid 0). - #[inline] - pub const fn is_init(self) -> bool { - self.0.get() == Self::INIT.0.get() - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] impl Cpuid { /// Converts a `RawCpuid` into a `Cpuid`. /// @@ -195,7 +60,7 @@ impl Cpuid { #[inline] #[must_use] pub fn getuid() -> Uid { - backend::process::syscalls::getuid() + backend::ugid::syscalls::getuid() } /// `geteuid()`—Returns the process' effective user ID. @@ -209,7 +74,7 @@ pub fn getuid() -> Uid { #[inline] #[must_use] pub fn geteuid() -> Uid { - backend::process::syscalls::geteuid() + backend::ugid::syscalls::geteuid() } /// `getgid()`—Returns the process' real group ID. @@ -223,7 +88,7 @@ pub fn geteuid() -> Uid { #[inline] #[must_use] pub fn getgid() -> Gid { - backend::process::syscalls::getgid() + backend::ugid::syscalls::getgid() } /// `getegid()`—Returns the process' effective group ID. @@ -237,7 +102,7 @@ pub fn getgid() -> Gid { #[inline] #[must_use] pub fn getegid() -> Gid { - backend::process::syscalls::getegid() + backend::ugid::syscalls::getegid() } /// `getpid()`—Returns the process' ID. @@ -251,7 +116,7 @@ pub fn getegid() -> Gid { #[inline] #[must_use] pub fn getpid() -> Pid { - backend::process::syscalls::getpid() + backend::pid::syscalls::getpid() } /// `getppid()`—Returns the parent process' ID. @@ -364,20 +229,3 @@ pub fn getgroups() -> io::Result> { buffer.resize(buffer.capacity(), Gid::ROOT); } } - -// Return the raw value of the IDs. In case of `None` it returns `u32::MAX` -// since it has the same bit pattern as `-1` indicating no change to the -// owner/group ID. -pub(crate) fn translate_fchown_args(owner: Option, group: Option) -> (u32, u32) { - let ow = match owner { - Some(o) => o.as_raw(), - None => u32::MAX, - }; - - let gr = match group { - Some(g) => g.as_raw(), - None => u32::MAX, - }; - - (ow, gr) -} diff --git a/vendor/rustix/src/process/ioctl.rs b/vendor/rustix/src/process/ioctl.rs new file mode 100644 index 000000000..46dbbc59b --- /dev/null +++ b/vendor/rustix/src/process/ioctl.rs @@ -0,0 +1,21 @@ +use crate::{backend, io}; +use backend::fd::AsFd; + +/// `ioctl(fd, TIOCSCTTY, 0)`—Sets the controlling terminal for the processs. +/// +/// # References +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// +/// [Linux]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=tty&sektion=4 +/// [NetBSD]: https://man.netbsd.org/tty.4 +/// [OpenBSD]: https://man.openbsd.org/tty.4 +#[cfg(not(any(windows, target_os = "haiku", target_os = "redox", target_os = "wasi")))] +#[inline] +#[doc(alias = "TIOCSCTTY")] +pub fn ioctl_tiocsctty(fd: Fd) -> io::Result<()> { + backend::process::syscalls::ioctl_tiocsctty(fd.as_fd()) +} diff --git a/vendor/rustix/src/process/kill.rs b/vendor/rustix/src/process/kill.rs index 807cc1028..5f6f06c48 100644 --- a/vendor/rustix/src/process/kill.rs +++ b/vendor/rustix/src/process/kill.rs @@ -1,7 +1,7 @@ use crate::process::Pid; use crate::{backend, io}; -pub use backend::process::types::Signal; +pub use crate::signal::Signal; /// `kill(pid, sig)`—Sends a signal to a process. /// diff --git a/vendor/rustix/src/process/membarrier.rs b/vendor/rustix/src/process/membarrier.rs index 8709337bc..df9f1a44c 100644 --- a/vendor/rustix/src/process/membarrier.rs +++ b/vendor/rustix/src/process/membarrier.rs @@ -1,24 +1,20 @@ //! The Linux `membarrier` syscall. -//! -//! # Safety -//! -//! This file defines an enum and a bitflags type that represent the same -//! set of values and are kept in sync. -#![allow(unsafe_code)] use crate::process::Cpuid; use crate::{backend, io}; pub use backend::process::types::MembarrierCommand; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] bitflags::bitflags! { /// A result from [`membarrier_query`]. /// /// These flags correspond to values of [`MembarrierCommand`] which are /// supported in the OS. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct MembarrierQuery: u32 { - /// `MEMBARRIER_CMD_GLOBAL` + /// `MEMBARRIER_CMD_GLOBAL` (also known as `MEMBARRIER_CMD_SHARED`) #[doc(alias = "SHARED")] #[doc(alias = "MEMBARRIER_CMD_SHARED")] const GLOBAL = MembarrierCommand::Global as _; @@ -41,14 +37,14 @@ bitflags::bitflags! { } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] impl MembarrierQuery { /// Test whether this query result contains the given command. #[inline] pub fn contains_command(self, cmd: MembarrierCommand) -> bool { - // SAFETY: `MembarrierCommand` is an enum that only contains values - // also valid in `MembarrierQuery`. - self.contains(unsafe { Self::from_bits_unchecked(cmd as _) }) + // `MembarrierCommand` is an enum that only contains values also valid + // in `MembarrierQuery`. + self.contains(Self::from_bits_retain(cmd as _)) } } diff --git a/vendor/rustix/src/process/mod.rs b/vendor/rustix/src/process/mod.rs index 0002c0f46..7a189b013 100644 --- a/vendor/rustix/src/process/mod.rs +++ b/vendor/rustix/src/process/mod.rs @@ -7,30 +7,26 @@ mod chroot; mod exit; #[cfg(not(target_os = "wasi"))] // WASI doesn't have get[gpu]id. mod id; +mod ioctl; #[cfg(not(target_os = "wasi"))] mod kill; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] mod membarrier; #[cfg(target_os = "linux")] mod pidfd; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(target_os = "linux")] +mod pidfd_getfd; +#[cfg(linux_kernel)] mod prctl; #[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] // WASI doesn't have [gs]etpriority. mod priority; -#[cfg(target_os = "freebsd")] +#[cfg(freebsdlike)] mod procctl; #[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] mod rlimit; -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "dragonfly", target_os = "fuchsia"))] mod sched; mod sched_yield; -#[cfg(not(target_os = "wasi"))] // WASI doesn't have uname. -mod system; #[cfg(not(target_os = "wasi"))] // WASI doesn't have umask. mod umask; #[cfg(not(target_os = "wasi"))] @@ -43,35 +39,27 @@ pub use chroot::*; pub use exit::*; #[cfg(not(target_os = "wasi"))] pub use id::*; +pub use ioctl::*; #[cfg(not(target_os = "wasi"))] pub use kill::*; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use membarrier::*; #[cfg(target_os = "linux")] pub use pidfd::*; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(target_os = "linux")] +pub use pidfd_getfd::*; +#[cfg(linux_kernel)] pub use prctl::*; #[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] pub use priority::*; -#[cfg(target_os = "freebsd")] +#[cfg(freebsdlike)] pub use procctl::*; #[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))] pub use rlimit::*; -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "fuchsia", - target_os = "linux", -))] +#[cfg(any(linux_kernel, target_os = "dragonfly", target_os = "fuchsia"))] pub use sched::*; pub use sched_yield::sched_yield; #[cfg(not(target_os = "wasi"))] -pub use system::*; -#[cfg(not(target_os = "wasi"))] pub use umask::*; #[cfg(not(target_os = "wasi"))] pub use wait::*; - -#[cfg(not(target_os = "wasi"))] -#[cfg(feature = "fs")] -pub(crate) use id::translate_fchown_args; diff --git a/vendor/rustix/src/process/pidfd.rs b/vendor/rustix/src/process/pidfd.rs index c9ddb591f..fb8298117 100644 --- a/vendor/rustix/src/process/pidfd.rs +++ b/vendor/rustix/src/process/pidfd.rs @@ -6,6 +6,8 @@ bitflags::bitflags! { /// `PIDFD_*` flags for use with [`pidfd_open`]. /// /// [`pidfd_open`]: crate::process::pidfd_open + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct PidfdFlags: backend::c::c_uint { /// `PIDFD_NONBLOCK`. const NONBLOCK = backend::c::PIDFD_NONBLOCK; diff --git a/vendor/rustix/src/process/pidfd_getfd.rs b/vendor/rustix/src/process/pidfd_getfd.rs new file mode 100644 index 000000000..7234810c2 --- /dev/null +++ b/vendor/rustix/src/process/pidfd_getfd.rs @@ -0,0 +1,51 @@ +#![allow(unsafe_code)] +use crate::fd::OwnedFd; +use crate::{backend, io}; +use backend::fd::{AsFd, RawFd}; + +/// Raw file descriptor in another process. +/// +/// A distinct type alias is used here to inform the user that normal file +/// descriptors from the calling process should not be used. The provided file +/// descriptor is used by the kernel as the index into the file descriptor +/// table of an entirely different process. +pub type ForeignRawFd = RawFd; + +bitflags::bitflags! { + /// All flags are reserved for future use. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct PidfdGetfdFlags: backend::c::c_uint {} +} + +/// `syscall(SYS_pidfd_getfd, pidfd, flags)`—Obtain a duplicate of another +/// process's file descriptor. +/// +/// # References +/// - [Linux] +/// +/// # Warning +/// +/// This function is generally safe for the calling process, but it can impact +/// the target process in unexpected ways. If you want to ensure that Rust I/O +/// safety assumptions continue to hold in the target process, then the target +/// process must have communicated the file description number to the calling +/// process from a value of a type that implements `AsRawFd`, and the target +/// process must not drop that value until after the calling process has +/// returned from `pidfd_getfd`. +/// +/// When `pidfd_getfd` is used to debug the target, or the target is not a Rust +/// aplication, or `pidfd_getfd` is used in any other way, then extra care +/// should be taken to avoid unexpected behaviour or crashes. +/// +/// For further details, see the references above. +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/pidfd_getfd.2.html +#[inline] +pub fn pidfd_getfd( + pidfd: Fd, + targetfd: ForeignRawFd, + flags: PidfdGetfdFlags, +) -> io::Result { + backend::process::syscalls::pidfd_getfd(pidfd.as_fd(), targetfd, flags) +} diff --git a/vendor/rustix/src/process/prctl.rs b/vendor/rustix/src/process/prctl.rs index a4e1e546c..d79657e98 100644 --- a/vendor/rustix/src/process/prctl.rs +++ b/vendor/rustix/src/process/prctl.rs @@ -5,63 +5,20 @@ #![allow(unsafe_code)] -use core::convert::{TryFrom, TryInto}; -use core::mem::MaybeUninit; -use core::ptr::NonNull; -use core::{mem, ptr}; +use core::mem::size_of; +use core::ptr::{null, null_mut, NonNull}; use bitflags::bitflags; use crate::backend::c::{c_int, c_uint, c_void}; -use crate::backend::process::syscalls; -use crate::backend::process::types::Signal; +use crate::backend::prctl::syscalls; use crate::fd::{AsRawFd, BorrowedFd}; use crate::ffi::CStr; use crate::io; +use crate::prctl::*; use crate::process::{Pid, RawPid}; - -// -// Helper functions. -// - -#[inline] -pub(crate) unsafe fn prctl_1arg(option: c_int) -> io::Result { - const NULL: *mut c_void = ptr::null_mut(); - syscalls::prctl(option, NULL, NULL, NULL, NULL) -} - -#[inline] -pub(crate) unsafe fn prctl_2args(option: c_int, arg2: *mut c_void) -> io::Result { - const NULL: *mut c_void = ptr::null_mut(); - syscalls::prctl(option, arg2, NULL, NULL, NULL) -} - -#[inline] -pub(crate) unsafe fn prctl_3args( - option: c_int, - arg2: *mut c_void, - arg3: *mut c_void, -) -> io::Result { - syscalls::prctl(option, arg2, arg3, ptr::null_mut(), ptr::null_mut()) -} - -#[inline] -pub(crate) unsafe fn prctl_get_at_arg2_optional

(option: i32) -> io::Result

{ - let mut value: MaybeUninit

= MaybeUninit::uninit(); - prctl_2args(option, value.as_mut_ptr().cast())?; - Ok(value.assume_init()) -} - -#[inline] -pub(crate) unsafe fn prctl_get_at_arg2(option: i32) -> io::Result -where - P: Default, - T: TryFrom, -{ - let mut value: P = Default::default(); - prctl_2args(option, ((&mut value) as *mut P).cast())?; - TryFrom::try_from(value) -} +use crate::signal::Signal; +use crate::utils::{as_mut_ptr, as_ptr}; // // PR_GET_PDEATHSIG/PR_SET_PDEATHSIG @@ -78,6 +35,7 @@ const PR_GET_PDEATHSIG: c_int = 2; /// [Linux: `prctl(PR_GET_PDEATHSIG,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html /// [FreeBSD: `procctl(PROC_PDEATHSIG_STATUS,...)`]: https://man.freebsd.org/cgi/man.cgi?query=procctl&sektion=2 #[inline] +#[doc(alias = "PR_GET_PDEATHSIG")] pub fn parent_process_death_signal() -> io::Result> { unsafe { prctl_get_at_arg2_optional::(PR_GET_PDEATHSIG) }.map(Signal::from_raw) } @@ -93,6 +51,7 @@ const PR_SET_PDEATHSIG: c_int = 1; /// [Linux: `prctl(PR_SET_PDEATHSIG,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html /// [FreeBSD: `procctl(PROC_PDEATHSIG_CTL,...)`]: https://man.freebsd.org/cgi/man.cgi?query=procctl&sektion=2 #[inline] +#[doc(alias = "PR_SET_PDEATHSIG")] pub fn set_parent_process_death_signal(signal: Option) -> io::Result<()> { let signal = signal.map_or(0_usize, |signal| signal as usize); unsafe { prctl_2args(PR_SET_PDEATHSIG, signal as *mut _) }.map(|_r| ()) @@ -108,15 +67,19 @@ const SUID_DUMP_DISABLE: i32 = 0; const SUID_DUMP_USER: i32 = 1; const SUID_DUMP_ROOT: i32 = 2; -/// `SUID_DUMP_*`. +/// `SUID_DUMP_*` values for use with [`dumpable_behavior`] and +/// [`set_dumpable_behavior`]. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(i32)] pub enum DumpableBehavior { /// Not dumpable. + #[doc(alias = "SUID_DUMP_DISABLE")] NotDumpable = SUID_DUMP_DISABLE, /// Dumpable. + #[doc(alias = "SUID_DUMP_USER")] Dumpable = SUID_DUMP_USER, /// Dumpable but only readable by root. + #[doc(alias = "SUID_DUMP_ROOT")] DumpableReadableOnlyByRoot = SUID_DUMP_ROOT, } @@ -140,6 +103,7 @@ impl TryFrom for DumpableBehavior { /// /// [`prctl(PR_GET_DUMPABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_GET_DUMPABLE")] pub fn dumpable_behavior() -> io::Result { unsafe { prctl_1arg(PR_GET_DUMPABLE) }.and_then(TryInto::try_into) } @@ -160,6 +124,7 @@ const PR_SET_DUMPABLE: c_int = 4; /// /// [`prctl(PR_SET_DUMPABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_SET_DUMPABLE")] pub fn set_dumpable_behavior(config: DumpableBehavior) -> io::Result<()> { unsafe { prctl_2args(PR_SET_DUMPABLE, config as usize as *mut _) }.map(|_r| ()) } @@ -171,11 +136,17 @@ pub fn set_dumpable_behavior(config: DumpableBehavior) -> io::Result<()> { const PR_GET_UNALIGN: c_int = 5; bitflags! { - /// `PR_UNALIGN_*`. + /// `PR_UNALIGN_*` flags for use with [`unaligned_access_control`] and + /// [`set_unaligned_access_control`]. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct UnalignedAccessControl: u32 { /// Silently fix up unaligned user accesses. + #[doc(alias = "NOPRINT")] + #[doc(alias = "PR_UNALIGN_NOPRINT")] const NO_PRINT = 1; /// Generate a [`Signal::Bus`] signal on unaligned user access. + #[doc(alias = "PR_UNALIGN_SIGBUS")] const SIGBUS = 2; } } @@ -187,6 +158,7 @@ bitflags! { /// /// [`prctl(PR_GET_UNALIGN,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_GET_UNALIGN")] pub fn unaligned_access_control() -> io::Result { let r = unsafe { prctl_get_at_arg2_optional::(PR_GET_UNALIGN)? }; UnalignedAccessControl::from_bits(r).ok_or(io::Errno::RANGE) @@ -201,6 +173,7 @@ const PR_SET_UNALIGN: c_int = 6; /// /// [`prctl(PR_SET_UNALIGN,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_SET_UNALIGN")] pub fn set_unaligned_access_control(config: UnalignedAccessControl) -> io::Result<()> { unsafe { prctl_2args(PR_SET_UNALIGN, config.bits() as usize as *mut _) }.map(|_r| ()) } @@ -212,12 +185,17 @@ pub fn set_unaligned_access_control(config: UnalignedAccessControl) -> io::Resul const PR_GET_FPEMU: c_int = 9; bitflags! { - /// `PR_FPEMU_*`. + /// `PR_FPEMU_*` flags for use with [`floating_point_emulation_control`] + /// and [`set_floating_point_emulation_control`]. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct FloatingPointEmulationControl: u32 { /// Silently emulate floating point operations accesses. + #[doc(alias = "PR_UNALIGN_NOPRINT")] const NO_PRINT = 1; /// Don't emulate floating point operations, send a [`Signal::Fpe`] /// signal instead. + #[doc(alias = "PR_UNALIGN_SIGFPE")] const SIGFPE = 2; } } @@ -229,6 +207,7 @@ bitflags! { /// /// [`prctl(PR_GET_FPEMU,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_GET_FPEMU")] pub fn floating_point_emulation_control() -> io::Result { let r = unsafe { prctl_get_at_arg2_optional::(PR_GET_FPEMU)? }; FloatingPointEmulationControl::from_bits(r).ok_or(io::Errno::RANGE) @@ -243,6 +222,7 @@ const PR_SET_FPEMU: c_int = 10; /// /// [`prctl(PR_SET_FPEMU,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_SET_FPEMU")] pub fn set_floating_point_emulation_control( config: FloatingPointEmulationControl, ) -> io::Result<()> { @@ -257,6 +237,8 @@ const PR_GET_FPEXC: c_int = 11; bitflags! { /// Zero means floating point exceptions are disabled. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct FloatingPointExceptionMode: u32 { /// Async non-recoverable exception mode. const NONRECOV = 1; @@ -287,6 +269,7 @@ bitflags! { /// /// [`prctl(PR_GET_FPEXC,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_GET_FPEXEC")] pub fn floating_point_exception_mode() -> io::Result> { unsafe { prctl_get_at_arg2_optional::(PR_GET_FPEXC) } .map(FloatingPointExceptionMode::from_bits) @@ -301,6 +284,7 @@ const PR_SET_FPEXC: c_int = 12; /// /// [`prctl(PR_SET_FPEXC,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_SET_FPEXEC")] pub fn set_floating_point_exception_mode( config: Option, ) -> io::Result<()> { @@ -317,7 +301,8 @@ const PR_GET_TIMING: c_int = 13; const PR_TIMING_STATISTICAL: i32 = 0; const PR_TIMING_TIMESTAMP: i32 = 1; -/// `PR_TIMING_*`. +/// `PR_TIMING_*` values for use with [`timing_method`] and +/// [`set_timing_method`]. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(i32)] pub enum TimingMethod { @@ -346,6 +331,7 @@ impl TryFrom for TimingMethod { /// /// [`prctl(PR_GET_TIMING,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_GET_TIMING")] pub fn timing_method() -> io::Result { unsafe { prctl_1arg(PR_GET_TIMING) }.and_then(TryInto::try_into) } @@ -360,6 +346,7 @@ const PR_SET_TIMING: c_int = 14; /// /// [`prctl(PR_SET_TIMING,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_SET_TIMING")] pub fn set_timing_method(method: TimingMethod) -> io::Result<()> { unsafe { prctl_2args(PR_SET_TIMING, method as usize as *mut _) }.map(|_r| ()) } @@ -374,7 +361,7 @@ const PR_ENDIAN_BIG: u32 = 0; const PR_ENDIAN_LITTLE: u32 = 1; const PR_ENDIAN_PPC_LITTLE: u32 = 2; -/// `PR_ENDIAN_*`. +/// `PR_ENDIAN_*` values for use with [`endian_mode`]. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(u32)] pub enum EndianMode { @@ -406,6 +393,7 @@ impl TryFrom for EndianMode { /// /// [`prctl(PR_GET_ENDIAN,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_GET_ENDIAN")] pub fn endian_mode() -> io::Result { unsafe { prctl_get_at_arg2::(PR_GET_ENDIAN) } } @@ -424,6 +412,7 @@ const PR_SET_ENDIAN: c_int = 20; /// /// [`prctl(PR_SET_ENDIAN,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_SET_ENDIAN")] pub unsafe fn set_endian_mode(mode: EndianMode) -> io::Result<()> { prctl_2args(PR_SET_ENDIAN, mode as usize as *mut _).map(|_r| ()) } @@ -437,7 +426,8 @@ const PR_GET_TSC: c_int = 25; const PR_TSC_ENABLE: u32 = 1; const PR_TSC_SIGSEGV: u32 = 2; -/// `PR_TSC_*`. +/// `PR_TSC_*` values for use with [`time_stamp_counter_readability`] and +/// [`set_time_stamp_counter_readability`]. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(u32)] pub enum TimeStampCounterReadability { @@ -466,6 +456,7 @@ impl TryFrom for TimeStampCounterReadability { /// /// [`prctl(PR_GET_TSC,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_GET_TSC")] pub fn time_stamp_counter_readability() -> io::Result { unsafe { prctl_get_at_arg2::(PR_GET_TSC) } } @@ -480,6 +471,7 @@ const PR_SET_TSC: c_int = 26; /// /// [`prctl(PR_SET_TSC,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_SET_TSC")] pub fn set_time_stamp_counter_readability( readability: TimeStampCounterReadability, ) -> io::Result<()> { @@ -502,6 +494,8 @@ const PR_TASK_PERF_EVENTS_ENABLE: c_int = 32; /// [`prctl(PR_TASK_PERF_EVENTS_ENABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html /// [`prctl(PR_TASK_PERF_EVENTS_DISABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_TASK_PERF_EVENTS_ENABLE")] +#[doc(alias = "PR_TASK_PERF_EVENTS_DISABLE")] pub fn configure_performance_counters(enable: bool) -> io::Result<()> { let option = if enable { PR_TASK_PERF_EVENTS_ENABLE @@ -522,15 +516,20 @@ const PR_MCE_KILL_LATE: u32 = 0; const PR_MCE_KILL_EARLY: u32 = 1; const PR_MCE_KILL_DEFAULT: u32 = 2; -/// `PR_MCE_KILL_*`. +/// `PR_MCE_KILL_*` values for use with +/// [`machine_check_memory_corruption_kill_policy`] and +/// [`set_machine_check_memory_corruption_kill_policy`]. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(u32)] pub enum MachineCheckMemoryCorruptionKillPolicy { /// Late kill policy. + #[doc(alias = "PR_MCE_KILL_LATE")] Late = PR_MCE_KILL_LATE, /// Early kill policy. + #[doc(alias = "PR_MCE_KILL_EARLY")] Early = PR_MCE_KILL_EARLY, /// System-wide default policy. + #[doc(alias = "PR_MCE_KILL_DEFAULT")] Default = PR_MCE_KILL_DEFAULT, } @@ -554,6 +553,7 @@ impl TryFrom for MachineCheckMemoryCorruptionKillPolicy { /// /// [`prctl(PR_MCE_KILL_GET,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_MCE_KILL_GET")] pub fn machine_check_memory_corruption_kill_policy( ) -> io::Result { let r = unsafe { prctl_1arg(PR_MCE_KILL_GET)? } as c_uint; @@ -572,13 +572,14 @@ const PR_MCE_KILL_SET: usize = 1; /// /// [`prctl(PR_MCE_KILL,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_MCE_KILL")] pub fn set_machine_check_memory_corruption_kill_policy( policy: Option, ) -> io::Result<()> { let (sub_operation, policy) = if let Some(policy) = policy { (PR_MCE_KILL_SET, policy as usize as *mut _) } else { - (PR_MCE_KILL_CLEAR, ptr::null_mut()) + (PR_MCE_KILL_CLEAR, null_mut()) }; unsafe { prctl_3args(PR_MCE_KILL, sub_operation as *mut _, policy) }.map(|_r| ()) @@ -606,7 +607,7 @@ const PR_SET_MM_EXE_FILE: usize = 13; const PR_SET_MM_MAP: usize = 14; const PR_SET_MM_MAP_SIZE: usize = 15; -/// `PR_SET_MM_*`. +/// `PR_SET_MM_*` values for use with [`set_virtual_memory_map_address`]. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(u32)] pub enum VirtualMemoryMapAddress { @@ -650,11 +651,12 @@ pub enum VirtualMemoryMapAddress { /// /// [`prctl(PR_SET_MM,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_SET_MM")] pub unsafe fn set_virtual_memory_map_address( option: VirtualMemoryMapAddress, address: Option>, ) -> io::Result<()> { - let address = address.map_or_else(ptr::null_mut, NonNull::as_ptr); + let address = address.map_or_else(null_mut, NonNull::as_ptr); prctl_3args(PR_SET_MM, option as usize as *mut _, address).map(|_r| ()) } @@ -666,6 +668,8 @@ pub unsafe fn set_virtual_memory_map_address( /// /// [`prctl(PR_SET_MM,PR_SET_MM_EXE_FILE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_SET_MM")] +#[doc(alias = "PR_SET_MM_EXE_FILE")] pub fn set_executable_file(fd: BorrowedFd) -> io::Result<()> { let fd = usize::try_from(fd.as_raw_fd()).map_err(|_r| io::Errno::RANGE)?; unsafe { prctl_3args(PR_SET_MM, PR_SET_MM_EXE_FILE as *mut _, fd as *mut _) }.map(|_r| ()) @@ -683,13 +687,15 @@ pub fn set_executable_file(fd: BorrowedFd) -> io::Result<()> { /// /// [`prctl(PR_SET_MM,PR_SET_MM_AUXV,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_SET_MM")] +#[doc(alias = "PR_SET_MM_AUXV")] pub unsafe fn set_auxiliary_vector(auxv: &[*const c_void]) -> io::Result<()> { syscalls::prctl( PR_SET_MM, PR_SET_MM_AUXV as *mut _, auxv.as_ptr() as *mut _, auxv.len() as *mut _, - ptr::null_mut(), + null_mut(), ) .map(|_r| ()) } @@ -701,9 +707,11 @@ pub unsafe fn set_auxiliary_vector(auxv: &[*const c_void]) -> io::Result<()> { /// /// [`prctl(PR_SET_MM,PR_SET_MM_MAP_SIZE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_SET_MM")] +#[doc(alias = "PR_SET_MM_MAP_SIZE")] pub fn virtual_memory_map_config_struct_size() -> io::Result { let mut value: c_uint = 0; - let value_ptr = (&mut value) as *mut c_uint; + let value_ptr = as_mut_ptr(&mut value); unsafe { prctl_3args(PR_SET_MM, PR_SET_MM_MAP_SIZE as *mut _, value_ptr.cast())? }; Ok(value as usize) } @@ -758,13 +766,15 @@ pub struct PrctlMmMap { /// /// [`prctl(PR_SET_MM,PR_SET_MM_MAP,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_SET_MM")] +#[doc(alias = "PR_SET_MM_MAP")] pub unsafe fn configure_virtual_memory_map(config: &PrctlMmMap) -> io::Result<()> { syscalls::prctl( PR_SET_MM, PR_SET_MM_MAP as *mut _, - config as *const PrctlMmMap as *mut _, - mem::size_of::() as *mut _, - ptr::null_mut(), + as_ptr(config) as *mut _, + size_of::() as *mut _, + null_mut(), ) .map(|_r| ()) } @@ -796,9 +806,10 @@ pub enum PTracer { /// /// [`prctl(PR_SET_PTRACER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_SET_PTRACER")] pub fn set_ptracer(tracer: PTracer) -> io::Result<()> { let pid = match tracer { - PTracer::None => ptr::null_mut(), + PTracer::None => null_mut(), PTracer::Any => PR_SET_PTRACER_ANY as *mut _, PTracer::ProcessID(pid) => pid.as_raw_nonzero().get() as usize as *mut _, }; @@ -819,6 +830,7 @@ const PR_GET_CHILD_SUBREAPER: c_int = 37; /// /// [`prctl(PR_GET_CHILD_SUBREAPER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_GET_CHILD_SUBREAPER")] pub fn child_subreaper() -> io::Result> { unsafe { let r = prctl_get_at_arg2_optional::(PR_GET_CHILD_SUBREAPER)?; @@ -835,6 +847,7 @@ const PR_SET_CHILD_SUBREAPER: c_int = 36; /// /// [`prctl(PR_SET_CHILD_SUBREAPER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_SET_CHILD_SUBREAPER")] pub fn set_child_subreaper(pid: Option) -> io::Result<()> { let pid = pid.map_or(0_usize, |pid| pid.as_raw_nonzero().get() as usize); unsafe { prctl_2args(PR_SET_CHILD_SUBREAPER, pid as *mut _) }.map(|_r| ()) @@ -849,7 +862,8 @@ const PR_GET_FP_MODE: c_int = 46; const PR_FP_MODE_FR: u32 = 1_u32 << 0; const PR_FP_MODE_FRE: u32 = 1_u32 << 1; -/// `PR_FP_MODE_*`. +/// `PR_FP_MODE_*` values for use with [`floating_point_mode`] and +/// [`set_floating_point_mode`]. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(u32)] pub enum FloatingPointMode { @@ -878,6 +892,7 @@ impl TryFrom for FloatingPointMode { /// /// [`prctl(PR_GET_FP_MODE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_GET_FP_MODE")] pub fn floating_point_mode() -> io::Result { let r = unsafe { prctl_1arg(PR_GET_FP_MODE)? } as c_uint; FloatingPointMode::try_from(r) @@ -892,6 +907,7 @@ const PR_SET_FP_MODE: c_int = 45; /// /// [`prctl(PR_SET_FP_MODE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_SET_FP_MODE")] pub fn set_floating_point_mode(mode: FloatingPointMode) -> io::Result<()> { unsafe { prctl_2args(PR_SET_FP_MODE, mode as usize as *mut _) }.map(|_r| ()) } @@ -906,7 +922,8 @@ const PR_SPEC_STORE_BYPASS: u32 = 0; const PR_SPEC_INDIRECT_BRANCH: u32 = 1; const PR_SPEC_L1D_FLUSH: u32 = 2; -/// `PR_SPEC_*`. +/// `PR_SPEC_*` values for use with [`speculative_feature_state`] and +/// [`control_speculative_feature`]. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[repr(u32)] pub enum SpeculationFeature { @@ -932,7 +949,9 @@ impl TryFrom for SpeculationFeature { } bitflags! { - /// `PR_SPEC_*`. + /// `PR_SPEC_*` flags for use with [`control_speculative_feature`]. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct SpeculationFeatureControl: u32 { /// The speculation feature is enabled, mitigation is disabled. const ENABLE = 1_u32 << 1; @@ -947,6 +966,8 @@ bitflags! { bitflags! { /// Zero means the processors are not vulnerable. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct SpeculationFeatureState: u32 { /// Mitigation can be controlled per thread by `PR_SET_SPECULATION_CTRL`. const PRCTL = 1_u32 << 0; @@ -968,6 +989,7 @@ bitflags! { /// /// [`prctl(PR_GET_SPECULATION_CTRL,...)`]: https://www.kernel.org/doc/html/v5.18/userspace-api/spec_ctrl.html #[inline] +#[doc(alias = "PR_GET_SPECULATION_CTRL")] pub fn speculative_feature_state( feature: SpeculationFeature, ) -> io::Result> { @@ -984,6 +1006,7 @@ const PR_SET_SPECULATION_CTRL: c_int = 53; /// /// [`prctl(PR_SET_SPECULATION_CTRL,...)`]: https://www.kernel.org/doc/html/v5.18/userspace-api/spec_ctrl.html #[inline] +#[doc(alias = "PR_SET_SPECULATION_CTRL")] pub fn control_speculative_feature( feature: SpeculationFeature, config: SpeculationFeatureControl, @@ -1006,6 +1029,7 @@ const PR_GET_IO_FLUSHER: c_int = 58; /// /// [`prctl(PR_GET_IO_FLUSHER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_GET_IO_FLUSHER")] pub fn is_io_flusher() -> io::Result { unsafe { prctl_1arg(PR_GET_IO_FLUSHER) }.map(|r| r != 0) } @@ -1020,8 +1044,9 @@ const PR_SET_IO_FLUSHER: c_int = 57; /// /// [`prctl(PR_SET_IO_FLUSHER,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] +#[doc(alias = "PR_SET_IO_FLUSHER")] pub fn configure_io_flusher_behavior(enable: bool) -> io::Result<()> { - unsafe { prctl_2args(PR_SET_IO_FLUSHER, enable as usize as *mut _) }.map(|_r| ()) + unsafe { prctl_2args(PR_SET_IO_FLUSHER, usize::from(enable) as *mut _) }.map(|_r| ()) } // @@ -1030,22 +1055,6 @@ pub fn configure_io_flusher_behavior(enable: bool) -> io::Result<()> { const PR_PAC_GET_ENABLED_KEYS: c_int = 61; -bitflags! { - /// `PR_PAC_AP*`. - pub struct PointerAuthenticationKeys: u32 { - /// Instruction authentication key `A`. - const INSTRUCTION_AUTHENTICATION_KEY_A = 1_u32 << 0; - /// Instruction authentication key `B`. - const INSTRUCTION_AUTHENTICATION_KEY_B = 1_u32 << 1; - /// Data authentication key `A`. - const DATA_AUTHENTICATION_KEY_A = 1_u32 << 2; - /// Data authentication key `B`. - const DATA_AUTHENTICATION_KEY_B = 1_u32 << 3; - /// Generic authentication `A` key. - const GENERIC_AUTHENTICATION_KEY_A = 1_u32 << 4; - } -} - /// Get enabled pointer authentication keys. /// /// # References @@ -1053,6 +1062,7 @@ bitflags! { /// /// [`prctl(PR_PAC_GET_ENABLED_KEYS,...)`]: https://www.kernel.org/doc/html/v5.18/arm64/pointer-authentication.html #[inline] +#[doc(alias = "PR_PAC_GET_ENABLED_KEYS")] pub fn enabled_pointer_authentication_keys() -> io::Result { let r = unsafe { prctl_1arg(PR_PAC_GET_ENABLED_KEYS)? } as c_uint; PointerAuthenticationKeys::from_bits(r).ok_or(io::Errno::RANGE) @@ -1072,6 +1082,7 @@ const PR_PAC_SET_ENABLED_KEYS: c_int = 60; /// /// [`prctl(PR_PAC_SET_ENABLED_KEYS,...)`]: https://www.kernel.org/doc/html/v5.18/arm64/pointer-authentication.html #[inline] +#[doc(alias = "PR_PAC_SET_ENABLED_KEYS")] pub unsafe fn configure_pointer_authentication_keys( config: impl Iterator, ) -> io::Result<()> { @@ -1116,6 +1127,8 @@ const PR_SET_VMA_ANON_NAME: usize = 0; /// /// [`prctl(PR_SET_VMA,PR_SET_VMA_ANON_NAME,...)`]: https://lwn.net/Articles/867818/ #[inline] +#[doc(alias = "PR_SET_VMA")] +#[doc(alias = "PR_SET_VMA_ANON_NAME")] pub fn set_virtual_memory_region_name(region: &[u8], name: Option<&CStr>) -> io::Result<()> { unsafe { syscalls::prctl( @@ -1123,7 +1136,7 @@ pub fn set_virtual_memory_region_name(region: &[u8], name: Option<&CStr>) -> io: PR_SET_VMA_ANON_NAME as *mut _, region.as_ptr() as *mut _, region.len() as *mut _, - name.map_or_else(ptr::null, CStr::as_ptr) as *mut _, + name.map_or_else(null, CStr::as_ptr) as *mut _, ) .map(|_r| ()) } diff --git a/vendor/rustix/src/process/priority.rs b/vendor/rustix/src/process/priority.rs index f8d061c6b..604614ef0 100644 --- a/vendor/rustix/src/process/priority.rs +++ b/vendor/rustix/src/process/priority.rs @@ -25,7 +25,6 @@ pub fn nice(inc: i32) -> io::Result { /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpriority.html /// [Linux]: https://man7.org/linux/man-pages/man2/getpriority.2.html /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setpriority.2.html -#[cfg(not(target_os = "redox"))] #[inline] #[doc(alias = "getpriority")] pub fn getpriority_user(uid: Uid) -> io::Result { @@ -45,7 +44,6 @@ pub fn getpriority_user(uid: Uid) -> io::Result { /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpriority.html /// [Linux]: https://man7.org/linux/man-pages/man2/getpriority.2.html /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setpriority.2.html -#[cfg(not(target_os = "redox"))] #[inline] #[doc(alias = "getpriority")] pub fn getpriority_pgrp(pgid: Option) -> io::Result { @@ -65,7 +63,6 @@ pub fn getpriority_pgrp(pgid: Option) -> io::Result { /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpriority.html /// [Linux]: https://man7.org/linux/man-pages/man2/getpriority.2.html /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setpriority.2.html -#[cfg(not(target_os = "redox"))] #[inline] #[doc(alias = "getpriority")] pub fn getpriority_process(pid: Option) -> io::Result { @@ -83,7 +80,6 @@ pub fn getpriority_process(pid: Option) -> io::Result { /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setpriority.html /// [Linux]: https://man7.org/linux/man-pages/man2/setpriority.2.html /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setpriority.2.html -#[cfg(not(target_os = "redox"))] #[inline] #[doc(alias = "setpriority")] pub fn setpriority_user(uid: Uid, priority: i32) -> io::Result<()> { @@ -103,7 +99,6 @@ pub fn setpriority_user(uid: Uid, priority: i32) -> io::Result<()> { /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setpriority.html /// [Linux]: https://man7.org/linux/man-pages/man2/setpriority.2.html /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setpriority.2.html -#[cfg(not(target_os = "redox"))] #[inline] #[doc(alias = "setpriority")] pub fn setpriority_pgrp(pgid: Option, priority: i32) -> io::Result<()> { @@ -123,7 +118,6 @@ pub fn setpriority_pgrp(pgid: Option, priority: i32) -> io::Result<()> { /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setpriority.html /// [Linux]: https://man7.org/linux/man-pages/man2/setpriority.2.html /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/setpriority.2.html -#[cfg(not(target_os = "redox"))] #[inline] #[doc(alias = "setpriority")] pub fn setpriority_process(pid: Option, priority: i32) -> io::Result<()> { diff --git a/vendor/rustix/src/process/procctl.rs b/vendor/rustix/src/process/procctl.rs index 443aa90a4..8da53d383 100644 --- a/vendor/rustix/src/process/procctl.rs +++ b/vendor/rustix/src/process/procctl.rs @@ -5,6 +5,8 @@ #![allow(unsafe_code)] +use alloc::vec; +use alloc::vec::Vec; use core::mem::MaybeUninit; use core::ptr; @@ -12,9 +14,11 @@ use bitflags::bitflags; use crate::backend::c::{c_int, c_uint, c_void}; use crate::backend::process::syscalls; -use crate::backend::process::types::{RawId, Signal}; +use crate::backend::process::types::RawId; use crate::io; use crate::process::{Pid, RawPid}; +use crate::signal::Signal; +use crate::utils::{as_mut_ptr, as_ptr}; // // Helper functions. @@ -59,7 +63,7 @@ pub(crate) unsafe fn procctl_set

( process: ProcSelector, data: &P, ) -> io::Result<()> { - procctl(option, process, (data as *const P as *mut P).cast()) + procctl(option, process, (as_ptr(data) as *mut P).cast()) } #[inline] @@ -180,7 +184,7 @@ pub fn trace_status(process: ProcSelector) -> io::Result { -1 => Ok(TracingStatus::NotTraceble), 0 => Ok(TracingStatus::Tracable), pid => { - let pid = unsafe { Pid::from_raw(pid as RawPid) }.ok_or(io::Errno::RANGE)?; + let pid = Pid::from_raw(pid as RawPid).ok_or(io::Errno::RANGE)?; Ok(TracingStatus::BeingTraced(pid)) } } @@ -218,6 +222,8 @@ const PROC_REAP_STATUS: c_int = 4; bitflags! { /// `REAPER_STATUS_*`. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct ReaperStatusFlags: c_uint { /// The process has acquired reaper status. const OWNED = 1; @@ -249,7 +255,7 @@ pub struct ReaperStatus { /// The pid of the reaper for the specified process id. pub reaper: Pid, /// The pid of one reaper child if there are any descendants. - pub pid: Pid, + pub pid: Option, } /// Get information about the reaper of the specified process (or the process @@ -263,11 +269,15 @@ pub struct ReaperStatus { pub fn get_reaper_status(process: ProcSelector) -> io::Result { let raw = unsafe { procctl_get_optional::(PROC_REAP_STATUS, process) }?; Ok(ReaperStatus { - flags: ReaperStatusFlags::from_bits_truncate(raw.rs_flags), + flags: ReaperStatusFlags::from_bits_retain(raw.rs_flags), children: raw.rs_children as _, descendants: raw.rs_descendants as _, - reaper: unsafe { Pid::from_raw(raw.rs_reaper) }.ok_or(io::Errno::RANGE)?, - pid: unsafe { Pid::from_raw(raw.rs_pid) }.ok_or(io::Errno::RANGE)?, + reaper: Pid::from_raw(raw.rs_reaper).ok_or(io::Errno::RANGE)?, + pid: if raw.rs_pid == -1 { + None + } else { + Some(Pid::from_raw(raw.rs_pid).ok_or(io::Errno::RANGE)?) + }, }) } @@ -275,12 +285,15 @@ const PROC_REAP_GETPIDS: c_int = 5; bitflags! { /// `REAPER_PIDINFO_*`. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct PidInfoFlags: c_uint { /// This structure was filled by the kernel. const VALID = 1; /// The pid field identifies a direct child of the reaper. const CHILD = 2; - /// The reported process is itself a reaper. Descendants of a subordinate reaper are not reported. + /// The reported process is itself a reaper. Descendants of a + /// subordinate reaper are not reported. const REAPER = 4; /// The reported process is in the zombie state. const ZOMBIE = 8; @@ -335,23 +348,17 @@ pub fn get_reaper_pids(process: ProcSelector) -> io::Result> { rp_pad0: [0; 15], rp_pids: pids.as_mut_slice().as_mut_ptr(), }; - unsafe { - procctl( - PROC_REAP_GETPIDS, - process, - (&mut pinfo as *mut procctl_reaper_pids).cast(), - )? - }; + unsafe { procctl(PROC_REAP_GETPIDS, process, as_mut_ptr(&mut pinfo).cast())? }; let mut result = Vec::new(); for raw in pids.into_iter() { - let flags = PidInfoFlags::from_bits_truncate(raw.pi_flags); + let flags = PidInfoFlags::from_bits_retain(raw.pi_flags); if !flags.contains(PidInfoFlags::VALID) { break; } result.push(PidInfo { flags, - subtree: unsafe { Pid::from_raw(raw.pi_subtree) }.ok_or(io::Errno::RANGE)?, - pid: unsafe { Pid::from_raw(raw.pi_pid) }.ok_or(io::Errno::RANGE)?, + subtree: Pid::from_raw(raw.pi_subtree).ok_or(io::Errno::RANGE)?, + pid: Pid::from_raw(raw.pi_pid).ok_or(io::Errno::RANGE)?, }); } Ok(result) @@ -361,6 +368,8 @@ const PROC_REAP_KILL: c_int = 6; bitflags! { /// `REAPER_KILL_*`. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] struct KillFlags: c_uint { const CHILDREN = 1; const SUBTREE = 2; @@ -409,20 +418,10 @@ pub fn reaper_kill( rk_fpid: 0, rk_pad0: [0; 15], }; - unsafe { - procctl( - PROC_REAP_KILL, - process, - (&mut req as *mut procctl_reaper_kill).cast(), - )? - }; + unsafe { procctl(PROC_REAP_KILL, process, as_mut_ptr(&mut req).cast())? }; Ok(KillResult { killed: req.rk_killed as _, - first_failed: if req.rk_fpid == -1 { - None - } else { - unsafe { Pid::from_raw(req.rk_fpid) } - }, + first_failed: Pid::from_raw(req.rk_fpid), }) } diff --git a/vendor/rustix/src/process/rlimit.rs b/vendor/rustix/src/process/rlimit.rs index 089f6b4bb..ea760c22f 100644 --- a/vendor/rustix/src/process/rlimit.rs +++ b/vendor/rustix/src/process/rlimit.rs @@ -1,4 +1,4 @@ -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] use crate::process::Pid; use crate::{backend, io}; @@ -46,7 +46,7 @@ pub fn setrlimit(resource: Resource, new: Rlimit) -> io::Result<()> { /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/prlimit.2.html -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] #[inline] pub fn prlimit(pid: Option, resource: Resource, new: Rlimit) -> io::Result { backend::process::syscalls::prlimit(pid, resource, new) diff --git a/vendor/rustix/src/process/sched.rs b/vendor/rustix/src/process/sched.rs index 88e661670..239b7df82 100644 --- a/vendor/rustix/src/process/sched.rs +++ b/vendor/rustix/src/process/sched.rs @@ -55,7 +55,7 @@ impl CpuSet { } /// Count the number of CPUs set in the `CpuSet`. - #[cfg(any(target_os = "android", target_os = "linux"))] + #[cfg(linux_kernel)] #[inline] pub fn count(&self) -> u32 { backend::process::cpu_set::CPU_COUNT(&self.cpu_set) diff --git a/vendor/rustix/src/process/system.rs b/vendor/rustix/src/process/system.rs deleted file mode 100644 index cf9a312fc..000000000 --- a/vendor/rustix/src/process/system.rs +++ /dev/null @@ -1,137 +0,0 @@ -//! Uname and other system-level functions. -//! -//! # Safety -//! -//! This function converts from `struct utsname` fields provided from the -//! kernel into `&str` references, which assumes that they're NUL-terminated. -#![allow(unsafe_code)] - -use crate::backend; -use crate::ffi::CStr; -#[cfg(not(target_os = "emscripten"))] -use crate::io; -use core::fmt; - -#[cfg(any(target_os = "android", target_os = "linux"))] -pub use backend::process::types::Sysinfo; - -/// `uname()`—Returns high-level information about the runtime OS and -/// hardware. -/// -/// # References -/// - [POSIX] -/// - [Linux] -/// -/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/uname.html -/// [Linux]: https://man7.org/linux/man-pages/man2/uname.2.html -#[inline] -pub fn uname() -> Uname { - Uname(backend::process::syscalls::uname()) -} - -/// `struct utsname`—Return type for [`uname`]. -#[doc(alias = "utsname")] -pub struct Uname(backend::process::types::RawUname); - -impl Uname { - /// `sysname`—Operating system release name - #[inline] - pub fn sysname(&self) -> &CStr { - Self::to_cstr(self.0.sysname.as_ptr().cast()) - } - - /// `nodename`—Name with vague meaning - /// - /// This is intended to be a network name, however it's unable to convey - /// information about hosts that have multiple names, or any information - /// about where the names are visible. - #[inline] - pub fn nodename(&self) -> &CStr { - Self::to_cstr(self.0.nodename.as_ptr().cast()) - } - - /// `release`—Operating system release version string - #[inline] - pub fn release(&self) -> &CStr { - Self::to_cstr(self.0.release.as_ptr().cast()) - } - - /// `version`—Operating system build identifiers - #[inline] - pub fn version(&self) -> &CStr { - Self::to_cstr(self.0.version.as_ptr().cast()) - } - - /// `machine`—Hardware architecture identifier - #[inline] - pub fn machine(&self) -> &CStr { - Self::to_cstr(self.0.machine.as_ptr().cast()) - } - - /// `domainname`—NIS or YP domain identifier - #[cfg(any(target_os = "android", target_os = "linux"))] - #[inline] - pub fn domainname(&self) -> &CStr { - Self::to_cstr(self.0.domainname.as_ptr().cast()) - } - - #[inline] - fn to_cstr<'a>(ptr: *const u8) -> &'a CStr { - // SAFETY: Strings returned from the kernel are always NUL-terminated. - unsafe { CStr::from_ptr(ptr.cast()) } - } -} - -impl fmt::Debug for Uname { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - #[cfg(not(any(target_os = "android", target_os = "linux")))] - { - write!( - fmt, - "{} {} {} {} {}", - self.sysname().to_string_lossy(), - self.nodename().to_string_lossy(), - self.release().to_string_lossy(), - self.version().to_string_lossy(), - self.machine().to_string_lossy(), - ) - } - #[cfg(any(target_os = "android", target_os = "linux"))] - { - write!( - fmt, - "{} {} {} {} {} {}", - self.sysname().to_string_lossy(), - self.nodename().to_string_lossy(), - self.release().to_string_lossy(), - self.version().to_string_lossy(), - self.machine().to_string_lossy(), - self.domainname().to_string_lossy(), - ) - } - } -} - -/// `sysinfo()`—Returns status information about the runtime OS. -/// -/// # References -/// - [Linux] -/// -/// [Linux]: https://man7.org/linux/man-pages/man2/uname.2.html -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -pub fn sysinfo() -> Sysinfo { - backend::process::syscalls::sysinfo() -} - -/// `sethostname(name)—Sets the system host name. -/// -/// # References -/// - [Linux] -/// -/// [Linux]: https://man7.org/linux/man-pages/man2/sethostname.2.html -#[cfg(not(any(target_os = "emscripten", target_os = "redox", target_os = "wasi")))] -#[inline] -pub fn sethostname(name: &[u8]) -> io::Result<()> { - backend::process::syscalls::sethostname(name) -} diff --git a/vendor/rustix/src/process/umask.rs b/vendor/rustix/src/process/umask.rs index 7d83d6686..01779d7ed 100644 --- a/vendor/rustix/src/process/umask.rs +++ b/vendor/rustix/src/process/umask.rs @@ -13,9 +13,9 @@ use crate::fs::Mode; /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/umask.html /// [Linux]: https://man7.org/linux/man-pages/man2/umask.2.html -#[inline] -#[cfg_attr(doc_cfg, doc(cfg(feature = "fs")))] #[cfg(feature = "fs")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "fs")))] +#[inline] pub fn umask(mask: Mode) -> Mode { backend::process::syscalls::umask(mask) } diff --git a/vendor/rustix/src/process/wait.rs b/vendor/rustix/src/process/wait.rs index ea2691ae1..d46c96005 100644 --- a/vendor/rustix/src/process/wait.rs +++ b/vendor/rustix/src/process/wait.rs @@ -10,34 +10,38 @@ use crate::backend::process::wait::SiginfoExt; bitflags! { /// Options for modifying the behavior of wait/waitpid + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct WaitOptions: u32 { /// Return immediately if no child has exited. - const NOHANG = backend::process::wait::WNOHANG as _; + const NOHANG = bitcast!(backend::process::wait::WNOHANG); /// Return if a child has stopped (but not traced via [`ptrace`]) /// /// [`ptrace`]: https://man7.org/linux/man-pages/man2/ptrace.2.html - const UNTRACED = backend::process::wait::WUNTRACED as _; + const UNTRACED = bitcast!(backend::process::wait::WUNTRACED); /// Return if a stopped child has been resumed by delivery of /// [`Signal::Cont`]. - const CONTINUED = backend::process::wait::WCONTINUED as _; + const CONTINUED = bitcast!(backend::process::wait::WCONTINUED); } } #[cfg(not(any(target_os = "wasi", target_os = "redox", target_os = "openbsd")))] bitflags! { /// Options for modifying the behavior of waitid + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct WaitidOptions: u32 { /// Return immediately if no child has exited. - const NOHANG = backend::process::wait::WNOHANG as _; + const NOHANG = bitcast!(backend::process::wait::WNOHANG); /// Return if a stopped child has been resumed by delivery of /// [`Signal::Cont`] - const CONTINUED = backend::process::wait::WCONTINUED as _; + const CONTINUED = bitcast!(backend::process::wait::WCONTINUED); /// Wait for processed that have exited. - const EXITED = backend::process::wait::WEXITED as _; + const EXITED = bitcast!(backend::process::wait::WEXITED); /// Keep processed in a waitable state. - const NOWAIT = backend::process::wait::WNOWAIT as _; + const NOWAIT = bitcast!(backend::process::wait::WNOWAIT); /// Wait for processes that have been stopped. - const STOPPED = backend::process::wait::WSTOPPED as _; + const STOPPED = bitcast!(backend::process::wait::WSTOPPED); } } @@ -230,8 +234,8 @@ impl WaitidStatus { #[cfg(not(any(target_os = "netbsd", target_os = "fuchsia", target_os = "emscripten")))] #[allow(unsafe_code)] fn si_status(&self) -> backend::c::c_int { - // SAFETY: POSIX [specifies] that the `siginfo_t` returned by a `waitid` - // call always has a valid `si_status` value. + // SAFETY: POSIX [specifies] that the `siginfo_t` returned by a + // `waitid` call always has a valid `si_status` value. // // [specifies]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html unsafe { self.0.si_status() } @@ -256,7 +260,7 @@ pub enum WaitId<'a> { /// Eat the lifetime for non-Linux platforms. #[doc(hidden)] #[cfg(not(target_os = "linux"))] - __EatLifetime(std::marker::PhantomData<&'a ()>), + __EatLifetime(core::marker::PhantomData<&'a ()>), // TODO(notgull): Once this crate has the concept of PGIDs, add a WaitId::Pgid } diff --git a/vendor/rustix/src/procfs.rs b/vendor/rustix/src/procfs.rs new file mode 100644 index 000000000..e04793977 --- /dev/null +++ b/vendor/rustix/src/procfs.rs @@ -0,0 +1,468 @@ +//! Utilities for working with `/proc`, where Linux's `procfs` is typically +//! mounted. +//! +//! `/proc` serves as an adjunct to Linux's main syscall surface area, +//! providing additional features with an awkward interface. +//! +//! This module does a considerable amount of work to determine whether `/proc` +//! is mounted, with actual `procfs`, and without any additional mount points +//! on top of the paths we open. +//! +//! Why all the effort to detect bind mount points? People are doing all kinds +//! of things with Linux containers these days, with many different privilege +//! schemes, and we want to avoid making any unnecessary assumptions. Rustix +//! and its users will sometimes use procfs *implicitly* (when Linux gives them +//! no better options), in ways that aren't obvious from their public APIs. +//! These filesystem accesses might not be visible to someone auditing the main +//! code of an application for places which may be influenced by the filesystem +//! namespace. So with the checking here, they may fail, but they won't be able +//! to succeed with bogus results. + +use crate::backend::pid::syscalls::getpid; +use crate::fd::{AsFd, BorrowedFd, OwnedFd}; +use crate::ffi::CStr; +use crate::fs::{ + fstat, fstatfs, major, openat, renameat, Dir, FileType, Mode, OFlags, Stat, CWD, + PROC_SUPER_MAGIC, +}; +use crate::io; +use crate::path::DecInt; +#[cfg(feature = "rustc-dep-of-std")] +use core::lazy::OnceCell; +#[cfg(not(feature = "rustc-dep-of-std"))] +use once_cell::sync::OnceCell; + +/// Linux's procfs always uses inode 1 for its root directory. +const PROC_ROOT_INO: u64 = 1; + +// Identify an entry within "/proc", to determine which anomalies to check for. +#[derive(Copy, Clone, Debug)] +enum Kind { + Proc, + Pid, + Fd, + File, +} + +/// Check a subdirectory of "/proc" for anomalies. +fn check_proc_entry( + kind: Kind, + entry: BorrowedFd<'_>, + proc_stat: Option<&Stat>, +) -> io::Result { + let entry_stat = fstat(entry)?; + check_proc_entry_with_stat(kind, entry, entry_stat, proc_stat) +} + +/// Check a subdirectory of "/proc" for anomalies, using the provided `Stat`. +fn check_proc_entry_with_stat( + kind: Kind, + entry: BorrowedFd<'_>, + entry_stat: Stat, + proc_stat: Option<&Stat>, +) -> io::Result { + // Check the filesystem magic. + check_procfs(entry)?; + + match kind { + Kind::Proc => check_proc_root(entry, &entry_stat)?, + Kind::Pid | Kind::Fd => check_proc_subdir(entry, &entry_stat, proc_stat)?, + Kind::File => check_proc_file(&entry_stat, proc_stat)?, + } + + // "/proc" directories are typically mounted r-xr-xr-x. + // "/proc/self/fd" is r-x------. Allow them to have fewer permissions, but + // not more. + let expected_mode = if let Kind::Fd = kind { 0o500 } else { 0o555 }; + if entry_stat.st_mode & 0o777 & !expected_mode != 0 { + return Err(io::Errno::NOTSUP); + } + + match kind { + Kind::Fd => { + // Check that the "/proc/self/fd" directory doesn't have any + // extraneous links into it (which might include unexpected + // subdirectories). + if entry_stat.st_nlink != 2 { + return Err(io::Errno::NOTSUP); + } + } + Kind::Pid | Kind::Proc => { + // Check that the "/proc" and "/proc/self" directories aren't + // empty. + if entry_stat.st_nlink <= 2 { + return Err(io::Errno::NOTSUP); + } + } + Kind::File => { + // Check that files in procfs don't have extraneous hard links to + // them (which might indicate hard links to other things). + if entry_stat.st_nlink != 1 { + return Err(io::Errno::NOTSUP); + } + } + } + + Ok(entry_stat) +} + +fn check_proc_root(entry: BorrowedFd<'_>, stat: &Stat) -> io::Result<()> { + // We use `O_DIRECTORY` for proc directories, so open should fail if we + // don't get a directory when we expect one. + assert_eq!(FileType::from_raw_mode(stat.st_mode), FileType::Directory); + + // Check the root inode number. + if stat.st_ino != PROC_ROOT_INO { + return Err(io::Errno::NOTSUP); + } + + // Proc is a non-device filesystem, so check for major number 0. + // + if major(stat.st_dev) != 0 { + return Err(io::Errno::NOTSUP); + } + + // Check that "/proc" is a mountpoint. + if !is_mountpoint(entry) { + return Err(io::Errno::NOTSUP); + } + + Ok(()) +} + +fn check_proc_subdir( + entry: BorrowedFd<'_>, + stat: &Stat, + proc_stat: Option<&Stat>, +) -> io::Result<()> { + // We use `O_DIRECTORY` for proc directories, so open should fail if we + // don't get a directory when we expect one. + assert_eq!(FileType::from_raw_mode(stat.st_mode), FileType::Directory); + + check_proc_nonroot(stat, proc_stat)?; + + // Check that subdirectories of "/proc" are not mount points. + if is_mountpoint(entry) { + return Err(io::Errno::NOTSUP); + } + + Ok(()) +} + +fn check_proc_file(stat: &Stat, proc_stat: Option<&Stat>) -> io::Result<()> { + // Check that we have a regular file. + if FileType::from_raw_mode(stat.st_mode) != FileType::RegularFile { + return Err(io::Errno::NOTSUP); + } + + check_proc_nonroot(stat, proc_stat)?; + + Ok(()) +} + +fn check_proc_nonroot(stat: &Stat, proc_stat: Option<&Stat>) -> io::Result<()> { + // Check that we haven't been linked back to the root of "/proc". + if stat.st_ino == PROC_ROOT_INO { + return Err(io::Errno::NOTSUP); + } + + // Check that we're still in procfs. + if stat.st_dev != proc_stat.unwrap().st_dev { + return Err(io::Errno::NOTSUP); + } + + Ok(()) +} + +/// Check that `file` is opened on a `procfs` filesystem. +fn check_procfs(file: BorrowedFd<'_>) -> io::Result<()> { + let statfs = fstatfs(file)?; + let f_type = statfs.f_type; + if f_type != PROC_SUPER_MAGIC { + return Err(io::Errno::NOTSUP); + } + + Ok(()) +} + +/// Check whether the given directory handle is a mount point. +fn is_mountpoint(file: BorrowedFd<'_>) -> bool { + // We use a `renameat` call that would otherwise fail, but which fails with + // `XDEV` first if it would cross a mount point. + let err = renameat(file, cstr!("../."), file, cstr!(".")).unwrap_err(); + match err { + io::Errno::XDEV => true, // the rename failed due to crossing a mount point + io::Errno::BUSY => false, // the rename failed normally + _ => panic!("Unexpected error from `renameat`: {:?}", err), + } +} + +/// Open a directory in `/proc`, mapping all errors to `io::Errno::NOTSUP`. +fn proc_opendirat(dirfd: Fd, path: P) -> io::Result { + // We could add `PATH`|`NOATIME` here but Linux 2.6.32 doesn't support it. + // Also for `NOATIME` see the comment in `open_and_check_file`. + let oflags = OFlags::NOFOLLOW | OFlags::DIRECTORY | OFlags::CLOEXEC | OFlags::NOCTTY; + openat(dirfd, path, oflags, Mode::empty()).map_err(|_err| io::Errno::NOTSUP) +} + +/// Returns a handle to Linux's `/proc` directory. +/// +/// This ensures that `/proc` is procfs, that nothing is mounted on top of it, +/// and that it looks normal. It also returns the `Stat` of `/proc`. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html +fn proc() -> io::Result<(BorrowedFd<'static>, &'static Stat)> { + static PROC: StaticFd = StaticFd::new(); + + // `OnceBox` is "racey" in that the initialization function may run + // multiple times. We're ok with that, since the initialization function + // has no side effects. + PROC.get_or_try_init(|| { + // Open "/proc". + let proc = proc_opendirat(CWD, cstr!("/proc"))?; + let proc_stat = + check_proc_entry(Kind::Proc, proc.as_fd(), None).map_err(|_err| io::Errno::NOTSUP)?; + + Ok(new_static_fd(proc, proc_stat)) + }) + .map(|(fd, stat)| (fd.as_fd(), stat)) +} + +/// Returns a handle to Linux's `/proc/self` directory. +/// +/// This ensures that `/proc/self` is procfs, that nothing is mounted on top of +/// it, and that it looks normal. It also returns the `Stat` of `/proc/self`. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html +fn proc_self() -> io::Result<(BorrowedFd<'static>, &'static Stat)> { + static PROC_SELF: StaticFd = StaticFd::new(); + + // The init function here may run multiple times; see above. + PROC_SELF + .get_or_try_init(|| { + let (proc, proc_stat) = proc()?; + + let pid = getpid(); + + // Open "/proc/self". Use our pid to compute the name rather than + // literally using "self", as "self" is a symlink. + let proc_self = proc_opendirat(proc, DecInt::new(pid.as_raw_nonzero().get()))?; + let proc_self_stat = check_proc_entry(Kind::Pid, proc_self.as_fd(), Some(proc_stat)) + .map_err(|_err| io::Errno::NOTSUP)?; + + Ok(new_static_fd(proc_self, proc_self_stat)) + }) + .map(|(owned, stat)| (owned.as_fd(), stat)) +} + +/// Returns a handle to Linux's `/proc/self/fd` directory. +/// +/// This ensures that `/proc/self/fd` is `procfs`, that nothing is mounted on +/// top of it, and that it looks normal. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html +#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))] +pub fn proc_self_fd() -> io::Result> { + static PROC_SELF_FD: StaticFd = StaticFd::new(); + + // The init function here may run multiple times; see above. + PROC_SELF_FD + .get_or_try_init(|| { + let (_, proc_stat) = proc()?; + + let (proc_self, _proc_self_stat) = proc_self()?; + + // Open "/proc/self/fd". + let proc_self_fd = proc_opendirat(proc_self, cstr!("fd"))?; + let proc_self_fd_stat = + check_proc_entry(Kind::Fd, proc_self_fd.as_fd(), Some(proc_stat)) + .map_err(|_err| io::Errno::NOTSUP)?; + + Ok(new_static_fd(proc_self_fd, proc_self_fd_stat)) + }) + .map(|(owned, _stat)| owned.as_fd()) +} + +type StaticFd = OnceCell<(OwnedFd, Stat)>; + +#[inline] +fn new_static_fd(fd: OwnedFd, stat: Stat) -> (OwnedFd, Stat) { + (fd, stat) +} + +/// Returns a handle to Linux's `/proc/self/fdinfo` directory. +/// +/// This ensures that `/proc/self/fdinfo` is `procfs`, that nothing is mounted +/// on top of it, and that it looks normal. It also returns the `Stat` of +/// `/proc/self/fd`. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html +fn proc_self_fdinfo() -> io::Result<(BorrowedFd<'static>, &'static Stat)> { + static PROC_SELF_FDINFO: StaticFd = StaticFd::new(); + + PROC_SELF_FDINFO + .get_or_try_init(|| { + let (_, proc_stat) = proc()?; + + let (proc_self, _proc_self_stat) = proc_self()?; + + // Open "/proc/self/fdinfo". + let proc_self_fdinfo = proc_opendirat(proc_self, cstr!("fdinfo"))?; + let proc_self_fdinfo_stat = + check_proc_entry(Kind::Fd, proc_self_fdinfo.as_fd(), Some(proc_stat)) + .map_err(|_err| io::Errno::NOTSUP)?; + + Ok((proc_self_fdinfo, proc_self_fdinfo_stat)) + }) + .map(|(owned, stat)| (owned.as_fd(), stat)) +} + +/// Returns a handle to a Linux `/proc/self/fdinfo/` file. +/// +/// This ensures that `/proc/self/fdinfo/` is `procfs`, that nothing is +/// mounted on top of it, and that it looks normal. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html +#[inline] +#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))] +pub fn proc_self_fdinfo_fd(fd: Fd) -> io::Result { + _proc_self_fdinfo(fd.as_fd()) +} + +fn _proc_self_fdinfo(fd: BorrowedFd<'_>) -> io::Result { + let (proc_self_fdinfo, proc_self_fdinfo_stat) = proc_self_fdinfo()?; + let fd_str = DecInt::from_fd(fd); + open_and_check_file(proc_self_fdinfo, proc_self_fdinfo_stat, fd_str.as_c_str()) +} + +/// Returns a handle to a Linux `/proc/self/pagemap` file. +/// +/// This ensures that `/proc/self/pagemap` is `procfs`, that nothing is +/// mounted on top of it, and that it looks normal. +/// +/// # References +/// - [Linux] +/// - [Linux pagemap] +/// +/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html +/// [Linux pagemap]: https://www.kernel.org/doc/Documentation/vm/pagemap.txt +#[inline] +#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))] +pub fn proc_self_pagemap() -> io::Result { + proc_self_file(cstr!("pagemap")) +} + +/// Returns a handle to a Linux `/proc/self/maps` file. +/// +/// This ensures that `/proc/self/maps` is `procfs`, that nothing is +/// mounted on top of it, and that it looks normal. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html +#[inline] +#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))] +pub fn proc_self_maps() -> io::Result { + proc_self_file(cstr!("maps")) +} + +/// Returns a handle to a Linux `/proc/self/status` file. +/// +/// This ensures that `/proc/self/status` is `procfs`, that nothing is +/// mounted on top of it, and that it looks normal. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man5/proc.5.html +#[inline] +#[cfg_attr(doc_cfg, doc(cfg(feature = "procfs")))] +pub fn proc_self_status() -> io::Result { + proc_self_file(cstr!("status")) +} + +/// Open a file under `/proc/self`. +fn proc_self_file(name: &CStr) -> io::Result { + let (proc_self, proc_self_stat) = proc_self()?; + open_and_check_file(proc_self, proc_self_stat, name) +} + +/// Open a procfs file within in `dir` and check it for bind mounts. +fn open_and_check_file(dir: BorrowedFd, dir_stat: &Stat, name: &CStr) -> io::Result { + let (_, proc_stat) = proc()?; + + // Don't use `NOATIME`, because it [requires us to own the file], and when + // a process sets itself non-dumpable Linux changes the user:group of its + // `/proc/` files [to root:root]. + // + // [requires us to own the file]: https://man7.org/linux/man-pages/man2/openat.2.html + // [to root:root]: https://man7.org/linux/man-pages/man5/proc.5.html + let oflags = OFlags::RDONLY | OFlags::CLOEXEC | OFlags::NOFOLLOW | OFlags::NOCTTY; + let file = openat(dir, name, oflags, Mode::empty()).map_err(|_err| io::Errno::NOTSUP)?; + let file_stat = fstat(&file)?; + + // `is_mountpoint` only works on directory mount points, not file mount + // points. To detect file mount points, scan the parent directory to see + // if we can find a regular file with an inode and name that matches the + // file we just opened. If we can't find it, there could be a file bind + // mount on top of the file we want. + // + // As we scan, we also check for ".", to make sure it's the same directory + // as our original directory, to detect mount points, since + // `Dir::read_from` reopens ".". + // + // TODO: With Linux 5.8 we might be able to use `statx` and + // `STATX_ATTR_MOUNT_ROOT` to detect mountpoints directly instead of doing + // this scanning. + let dir = Dir::read_from(dir).map_err(|_err| io::Errno::NOTSUP)?; + + // Confirm that we got the same inode. + let dot_stat = dir.stat().map_err(|_err| io::Errno::NOTSUP)?; + if (dot_stat.st_dev, dot_stat.st_ino) != (dir_stat.st_dev, dir_stat.st_ino) { + return Err(io::Errno::NOTSUP); + } + + let mut found_file = false; + let mut found_dot = false; + for entry in dir { + let entry = entry.map_err(|_err| io::Errno::NOTSUP)?; + if entry.ino() == file_stat.st_ino + && entry.file_type() == FileType::RegularFile + && entry.file_name() == name + { + // We found the file. Proceed to check the file handle. + let _ = + check_proc_entry_with_stat(Kind::File, file.as_fd(), file_stat, Some(proc_stat))?; + + found_file = true; + } else if entry.ino() == dir_stat.st_ino + && entry.file_type() == FileType::Directory + && entry.file_name() == cstr!(".") + { + // We found ".", and it's the right ".". + found_dot = true; + } + } + + if found_file && found_dot { + Ok(file) + } else { + Err(io::Errno::NOTSUP) + } +} diff --git a/vendor/rustix/src/pty.rs b/vendor/rustix/src/pty.rs new file mode 100644 index 000000000..d7d250250 --- /dev/null +++ b/vendor/rustix/src/pty.rs @@ -0,0 +1,170 @@ +//! Pseudoterminal operations. +//! +//! For the `openpty` and `login_tty` functions, see the +//! [rustix-openpty crate]. +//! +//! [rustix-openpty crate]: https://crates.io/crates/rustix-openpty + +use crate::backend::c; +use crate::fd::{AsFd, OwnedFd}; +use crate::fs::OFlags; +use crate::{backend, io}; +#[cfg(any(apple, linux_like, target_os = "freebsd", target_os = "fuchsia"))] +use {crate::ffi::CString, alloc::vec::Vec}; + +bitflags::bitflags! { + /// `O_*` flags for use with [`openpt`] and [`ioctl_tiocgptpeer`]. + /// + /// [`ioctl_tiocgtpeer`]: https://docs.rs/rustix/*/x86_64-unknown-linux-gnu/rustix/pty/fn.ioctl_tiocgtpeer.html + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct OpenptFlags: u32 { + /// `O_RDWR` + const RDWR = c::O_RDWR as c::c_uint; + + /// `O_NOCTTY` + #[cfg(not(target_os = "redox"))] + const NOCTTY = c::O_NOCTTY as c::c_uint; + + /// `O_CLOEXEC` + /// + /// The standard `posix_openpt` function doesn't support `CLOEXEC`, but + /// rustix supports it on Linux, and FreeBSD and NetBSD support it. + #[cfg(any(linux_kernel, target_os = "freebsd", target_os = "netbsd"))] + const CLOEXEC = c::O_CLOEXEC as c::c_uint; + } +} + +impl From for OFlags { + #[inline] + fn from(flags: OpenptFlags) -> Self { + // `OpenptFlags` is a subset of `OFlags`. + Self::from_bits_retain(flags.bits() as _) + } +} + +/// `posix_openpt(flags)`—Open a pseudoterminal device. +/// +/// On Linux, an additional `CLOEXEC` flag value may be passed to request the +/// close-on-exec flag be set. +/// +/// On Linux, if the system has no free pseudoterminals available, the +/// underlying system call fails with [`io::Errno::NOSPC`], however this rustix +/// function translates that to [`io::Errno::AGAIN`], so that the linux_raw and +/// libc backends have the same behavior. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [Apple] +/// - [FreeBSD] +/// - [DragonFly BSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [illumos] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_openpt.html +/// [Linux]: https://man7.org/linux/man-pages/man3/posix_openpt.3.html +/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/posix_openpt.3.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=posix_openpt&sektion=2 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=posix_openpt§ion=3 +/// [NetBSD]: https://man.netbsd.org/posix_openpt.3 +/// [OpenBSD]: https://man.openbsd.org/posix_openpt +/// [illumos]: https://illumos.org/man/3C/posix_openpt +#[inline] +#[doc(alias = "posix_openpt")] +pub fn openpt(flags: OpenptFlags) -> io::Result { + // On Linux, open the device ourselves so that we can support `CLOEXEC`. + #[cfg(linux_kernel)] + { + use crate::fs::{open, Mode}; + match open(cstr!("/dev/ptmx"), flags.into(), Mode::empty()) { + // Match libc `openat` behavior with `ENOSPC`. + Err(io::Errno::NOSPC) => Err(io::Errno::AGAIN), + otherwise => otherwise, + } + } + + // On all other platforms, use `openpt`. + #[cfg(not(linux_kernel))] + { + backend::pty::syscalls::openpt(flags) + } +} + +/// `ptsname(fd)`—Return the name of a pseudoterminal. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/ptsname.html +/// [Linux]: https://man7.org/linux/man-pages/man3/ptsname.3.html +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Allocation.html#index-ptsname +#[inline] +#[doc(alias = "ptsname_r")] +#[cfg(any(apple, linux_like, target_os = "freebsd", target_os = "fuchsia"))] +pub fn ptsname>>(fd: Fd, reuse: B) -> io::Result { + backend::pty::syscalls::ptsname(fd.as_fd(), reuse.into()) +} + +/// `unlockpt(fd)`—Unlock a pseudoterminal. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlockpt.html +/// [Linux]: https://man7.org/linux/man-pages/man3/unlockpt.3.html +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Allocation.html#index-unlockpt +#[inline] +pub fn unlockpt(fd: Fd) -> io::Result<()> { + backend::pty::syscalls::unlockpt(fd.as_fd()) +} + +/// `grantpt(fd)`—Grant access to the user side of a pseudoterminal. +/// +/// On Linux, calling this function has no effect, as the kernel is expected to +/// grant the appropriate access. On all other platorms, this function has +/// unspecified behavior if the calling process has a `SIGCHLD` signal handler +/// installed. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/grantpt.html +/// [Linux]: https://man7.org/linux/man-pages/man3/grantpt.3.html +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Allocation.html#index-grantpt +#[inline] +pub fn grantpt(fd: Fd) -> io::Result<()> { + #[cfg(not(linux_kernel))] + { + backend::pty::syscalls::grantpt(fd.as_fd()) + } + + // On Linux, we assume the kernel has already granted the needed + // permissions to the user side of the pseudoterminal. + #[cfg(linux_kernel)] + { + let _ = fd; + Ok(()) + } +} + +/// `ioctl(fd, TIOCGPTPEER)`—Open the user side of a pseduoterminal. +/// +/// This function is currently only implemented on Linux. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/ioctl_tty.2.html +#[cfg(target_os = "linux")] +#[inline] +pub fn ioctl_tiocgptpeer(fd: Fd, flags: OpenptFlags) -> io::Result { + backend::pty::syscalls::ioctl_tiocgptpeer(fd.as_fd(), flags) +} diff --git a/vendor/rustix/src/rand/getrandom.rs b/vendor/rustix/src/rand/getrandom.rs index 79d5319d5..c66e50d56 100644 --- a/vendor/rustix/src/rand/getrandom.rs +++ b/vendor/rustix/src/rand/getrandom.rs @@ -1,6 +1,6 @@ use crate::{backend, io}; -/// `GRND_*` constants for use with `getrandom`. +/// `GRND_*` constants for use with [`getrandom`]. pub use backend::rand::types::GetRandomFlags; /// `getrandom(buf, flags)`—Reads a sequence of random bytes. diff --git a/vendor/rustix/src/rand/mod.rs b/vendor/rustix/src/rand/mod.rs index 4a0936d6c..e767c590d 100644 --- a/vendor/rustix/src/rand/mod.rs +++ b/vendor/rustix/src/rand/mod.rs @@ -1,7 +1,7 @@ //! Random-related operations. -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] mod getrandom; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use getrandom::{getrandom, GetRandomFlags}; diff --git a/vendor/rustix/src/runtime.rs b/vendor/rustix/src/runtime.rs index 587ad1e2a..9c850d5e3 100644 --- a/vendor/rustix/src/runtime.rs +++ b/vendor/rustix/src/runtime.rs @@ -1,6 +1,10 @@ //! Low-level implementation details for libc-like runtime libraries such as //! [origin]. //! +//! Do not use the functions in this module unless you've read all of their +//! code, *and* you know all the relevant internal implementation details of +//! any libc in the process they'll be used. +//! //! These functions are for implementing thread-local storage (TLS), managing //! threads, loaded libraries, and other process-wide resources. Most of //! `rustix` doesn't care about what other libraries are linked into the @@ -28,7 +32,9 @@ use crate::fs::AtFlags; #[cfg(linux_raw)] use crate::io; #[cfg(linux_raw)] -use crate::process::{Pid, Signal}; +use crate::pid::Pid; +#[cfg(linux_raw)] +use crate::signal::Signal; #[cfg(linux_raw)] #[cfg(feature = "fs")] use backend::fd::AsFd; @@ -51,7 +57,7 @@ pub type Sigset = linux_raw_sys::general::kernel_sigset_t; #[cfg(linux_raw)] pub type Siginfo = linux_raw_sys::general::siginfo_t; -pub use backend::time::types::{Nsecs, Secs, Timespec}; +pub use crate::timespec::{Nsecs, Secs, Timespec}; /// `SIG_*` constants for use with [`sigprocmask`]. #[cfg(linux_raw)] @@ -67,28 +73,36 @@ pub enum How { SETMASK = linux_raw_sys::general::SIG_SETMASK, } -#[cfg(linux_raw)] #[cfg(target_arch = "x86")] #[inline] pub unsafe fn set_thread_area(u_info: &mut UserDesc) -> io::Result<()> { backend::runtime::syscalls::tls::set_thread_area(u_info) } -#[cfg(linux_raw)] #[cfg(target_arch = "arm")] #[inline] pub unsafe fn arm_set_tls(data: *mut c_void) -> io::Result<()> { backend::runtime::syscalls::tls::arm_set_tls(data) } -#[cfg(linux_raw)] +/// `prctl(PR_SET_FS, data)`—Set the x86_64 `fs` register. +/// +/// # Safety +/// +/// This is a very low-level feature for implementing threading libraries. +/// See the references links above. #[cfg(target_arch = "x86_64")] #[inline] pub unsafe fn set_fs(data: *mut c_void) { backend::runtime::syscalls::tls::set_fs(data) } -#[cfg(linux_raw)] +/// Set the x86_64 thread ID address. +/// +/// # Safety +/// +/// This is a very low-level feature for implementing threading libraries. +/// See the references links above. #[inline] pub unsafe fn set_tid_address(data: *mut c_void) -> Pid { backend::runtime::syscalls::tls::set_tid_address(data) @@ -105,7 +119,6 @@ pub unsafe fn set_tid_address(data: *mut c_void) -> Pid { /// See the references links above. /// /// [Linux]: https://man7.org/linux/man-pages/man2/prctl.2.html -#[cfg(linux_raw)] #[inline] pub unsafe fn set_thread_name(name: &CStr) -> io::Result<()> { backend::runtime::syscalls::tls::set_thread_name(name) @@ -120,7 +133,6 @@ pub use backend::runtime::tls::UserDesc; /// # Safety /// /// This is a very low-level feature for implementing threading libraries. -#[cfg(linux_raw)] #[inline] pub unsafe fn exit_thread(status: i32) -> ! { backend::runtime::syscalls::tls::exit_thread(status) @@ -146,12 +158,11 @@ pub unsafe fn exit_thread(status: i32) -> ! { #[doc(alias = "_Exit")] #[inline] pub fn exit_group(status: i32) -> ! { - backend::process::syscalls::exit_group(status) + backend::runtime::syscalls::exit_group(status) } /// Return fields from the main executable segment headers ("phdrs") relevant /// to initializing TLS provided to the program at startup. -#[cfg(linux_raw)] #[inline] pub fn startup_tls_info() -> StartupTlsInfo { backend::runtime::tls::startup_tls_info() @@ -164,8 +175,6 @@ pub fn startup_tls_info() -> StartupTlsInfo { /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man3/getauxval.3.html -#[cfg(linux_raw)] -#[cfg(any(target_os = "android", target_os = "linux"))] #[inline] pub fn exe_phdrs() -> (*const c_void, usize) { backend::param::auxv::exe_phdrs() @@ -251,7 +260,6 @@ pub use backend::runtime::tls::StartupTlsInfo; /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html /// [Linux]: https://man7.org/linux/man-pages/man2/fork.2.html /// [async-signal-safe]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03 -#[cfg(linux_raw)] pub unsafe fn fork() -> io::Result> { backend::runtime::syscalls::fork() } @@ -268,7 +276,6 @@ pub unsafe fn fork() -> io::Result> { /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/execveat.2.html -#[cfg(linux_raw)] #[inline] #[cfg(feature = "fs")] #[cfg_attr(doc_cfg, doc(cfg(feature = "fs")))] @@ -294,7 +301,6 @@ pub unsafe fn execveat( /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/execve.2.html -#[cfg(linux_raw)] #[inline] pub unsafe fn execve(path: &CStr, argv: *const *const u8, envp: *const *const u8) -> io::Errno { backend::runtime::syscalls::execve(path, argv, envp) @@ -305,7 +311,8 @@ pub unsafe fn execve(path: &CStr, argv: *const *const u8, envp: *const *const u8 /// # Safety /// /// You're on your own. And on top of all the troubles with signal handlers, -/// this implementation is highly experimental. +/// this implementation is highly experimental. Even further, it differs from +/// the libc `sigaction` in several non-obvious and unsafe ways. /// /// # References /// - [POSIX] @@ -313,7 +320,6 @@ pub unsafe fn execve(path: &CStr, argv: *const *const u8, envp: *const *const u8 /// /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html /// [Linux]: https://man7.org/linux/man-pages/man2/sigaction.2.html -#[cfg(linux_raw)] #[inline] pub unsafe fn sigaction(signal: Signal, new: Option) -> io::Result { backend::runtime::syscalls::sigaction(signal, new) @@ -332,7 +338,6 @@ pub unsafe fn sigaction(signal: Signal, new: Option) -> io::Result) -> io::Result { backend::runtime::syscalls::sigaltstack(new) @@ -343,13 +348,13 @@ pub unsafe fn sigaltstack(new: Option) -> io::Result { /// # Safety /// /// You're on your own. And on top of all the troubles with signal handlers, -/// this implementation is highly experimental. +/// this implementation is highly experimental. The warning about the hazard +/// of recycled thread ID's applies. /// /// # References /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/tkill.2.html -#[cfg(linux_raw)] #[inline] pub unsafe fn tkill(tid: Pid, sig: Signal) -> io::Result<()> { backend::runtime::syscalls::tkill(tid, sig) @@ -360,7 +365,8 @@ pub unsafe fn tkill(tid: Pid, sig: Signal) -> io::Result<()> { /// # Safety /// /// You're on your own. And on top of all the troubles with signal handlers, -/// this implementation is highly experimental. +/// this implementation is highly experimental. Even further, it differs from +/// the libc `sigprocmask` in several non-obvious and unsafe ways. /// /// # References /// - [Linux `sigprocmask`] @@ -368,45 +374,59 @@ pub unsafe fn tkill(tid: Pid, sig: Signal) -> io::Result<()> { /// /// [Linux `sigprocmask`]: https://man7.org/linux/man-pages/man2/sigprocmask.2.html /// [Linux `pthread_sigmask`]: https://man7.org/linux/man-pages/man3/pthread_sigmask.3.html -#[cfg(linux_raw)] #[inline] #[doc(alias = "pthread_sigmask")] -pub unsafe fn sigprocmask(how: How, set: &Sigset) -> io::Result { +pub unsafe fn sigprocmask(how: How, set: Option<&Sigset>) -> io::Result { backend::runtime::syscalls::sigprocmask(how, set) } /// `sigwait(set)`—Wait for signals. /// +/// # Safety +/// +/// If code elsewhere in the process is depending on delivery of a signal to +/// prevent it from executing some code, this could cause it to miss that +/// signal and execute that code. +/// /// # References /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man3/sigwait.3.html -#[cfg(linux_raw)] #[inline] -pub fn sigwait(set: &Sigset) -> io::Result { +pub unsafe fn sigwait(set: &Sigset) -> io::Result { backend::runtime::syscalls::sigwait(set) } /// `sigwait(set)`—Wait for signals, returning a [`Siginfo`]. /// +/// # Safety +/// +/// If code elsewhere in the process is depending on delivery of a signal to +/// prevent it from executing some code, this could cause it to miss that +/// signal and execute that code. +/// /// # References /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/sigwaitinfo.2.html -#[cfg(linux_raw)] #[inline] -pub fn sigwaitinfo(set: &Sigset) -> io::Result { +pub unsafe fn sigwaitinfo(set: &Sigset) -> io::Result { backend::runtime::syscalls::sigwaitinfo(set) } /// `sigtimedwait(set)`—Wait for signals, optionally with a timeout. /// +/// # Safety +/// +/// If code elsewhere in the process is depending on delivery of a signal to +/// prevent it from executing some code, this could cause it to miss that +/// signal and execute that code. +/// /// # References /// - [Linux] /// /// [Linux]: https://man7.org/linux/man-pages/man2/sigtimedwait.2.html -#[cfg(linux_raw)] #[inline] -pub fn sigtimedwait(set: &Sigset, timeout: Option) -> io::Result { +pub unsafe fn sigtimedwait(set: &Sigset, timeout: Option) -> io::Result { backend::runtime::syscalls::sigtimedwait(set, timeout) } diff --git a/vendor/rustix/src/signal.rs b/vendor/rustix/src/signal.rs new file mode 100644 index 000000000..e1723c990 --- /dev/null +++ b/vendor/rustix/src/signal.rs @@ -0,0 +1,212 @@ +use crate::backend::c; + +/// A signal number for use with [`kill_process`], [`kill_process_group`], +/// and [`kill_current_process_group`]. +/// +/// [`kill_process`]: crate::process::kill_process +/// [`kill_process_group`]: crate::process::kill_process_group +/// [`kill_current_process_group`]: crate::process::kill_current_process_group +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[repr(i32)] +pub enum Signal { + /// `SIGHUP` + Hup = c::SIGHUP, + /// `SIGINT` + Int = c::SIGINT, + /// `SIGQUIT` + Quit = c::SIGQUIT, + /// `SIGILL` + Ill = c::SIGILL, + /// `SIGTRAP` + Trap = c::SIGTRAP, + /// `SIGABRT`, aka `SIGIOT` + #[doc(alias = "Iot")] + #[doc(alias = "Abrt")] + Abort = c::SIGABRT, + /// `SIGBUS` + Bus = c::SIGBUS, + /// `SIGFPE` + Fpe = c::SIGFPE, + /// `SIGKILL` + Kill = c::SIGKILL, + /// `SIGUSR1` + Usr1 = c::SIGUSR1, + /// `SIGSEGV` + Segv = c::SIGSEGV, + /// `SIGUSR2` + Usr2 = c::SIGUSR2, + /// `SIGPIPE` + Pipe = c::SIGPIPE, + /// `SIGALRM` + #[doc(alias = "Alrm")] + Alarm = c::SIGALRM, + /// `SIGTERM` + Term = c::SIGTERM, + /// `SIGSTKFLT` + #[cfg(not(any( + bsd, + solarish, + target_os = "aix", + target_os = "haiku", + all( + linux_kernel, + any( + target_arch = "mips", + target_arch = "mips64", + target_arch = "sparc", + target_arch = "sparc64" + ), + ) + )))] + Stkflt = c::SIGSTKFLT, + /// `SIGCHLD` + #[doc(alias = "Chld")] + Child = c::SIGCHLD, + /// `SIGCONT` + Cont = c::SIGCONT, + /// `SIGSTOP` + Stop = c::SIGSTOP, + /// `SIGTSTP` + Tstp = c::SIGTSTP, + /// `SIGTTIN` + Ttin = c::SIGTTIN, + /// `SIGTTOU` + Ttou = c::SIGTTOU, + /// `SIGURG` + Urg = c::SIGURG, + /// `SIGXCPU` + Xcpu = c::SIGXCPU, + /// `SIGXFSZ` + Xfsz = c::SIGXFSZ, + /// `SIGVTALRM` + #[doc(alias = "Vtalrm")] + Vtalarm = c::SIGVTALRM, + /// `SIGPROF` + Prof = c::SIGPROF, + /// `SIGWINCH` + Winch = c::SIGWINCH, + /// `SIGIO`, aka `SIGPOLL` + #[doc(alias = "Poll")] + #[cfg(not(target_os = "haiku"))] + Io = c::SIGIO, + /// `SIGPWR` + #[cfg(not(any(bsd, target_os = "haiku")))] + #[doc(alias = "Pwr")] + Power = c::SIGPWR, + /// `SIGSYS`, aka `SIGUNUSED` + #[doc(alias = "Unused")] + Sys = c::SIGSYS, + /// `SIGEMT` + #[cfg(any( + bsd, + solarish, + target_os = "aix", + target_os = "hermit", + all( + linux_kernel, + any( + target_arch = "mips", + target_arch = "mips64", + target_arch = "sparc", + target_arch = "sparc64" + ) + ) + ))] + Emt = c::SIGEMT, + /// `SIGINFO` + #[cfg(bsd)] + Info = c::SIGINFO, + /// `SIGTHR` + #[cfg(target_os = "freebsd")] + #[doc(alias = "Lwp")] + Thr = c::SIGTHR, + /// `SIGLIBRT` + #[cfg(target_os = "freebsd")] + Librt = c::SIGLIBRT, +} + +impl Signal { + /// Convert a raw signal number into a `Signal`, if possible. + pub fn from_raw(sig: c::c_int) -> Option { + match sig { + c::SIGHUP => Some(Self::Hup), + c::SIGINT => Some(Self::Int), + c::SIGQUIT => Some(Self::Quit), + c::SIGILL => Some(Self::Ill), + c::SIGTRAP => Some(Self::Trap), + c::SIGABRT => Some(Self::Abort), + c::SIGBUS => Some(Self::Bus), + c::SIGFPE => Some(Self::Fpe), + c::SIGKILL => Some(Self::Kill), + c::SIGUSR1 => Some(Self::Usr1), + c::SIGSEGV => Some(Self::Segv), + c::SIGUSR2 => Some(Self::Usr2), + c::SIGPIPE => Some(Self::Pipe), + c::SIGALRM => Some(Self::Alarm), + c::SIGTERM => Some(Self::Term), + #[cfg(not(any( + bsd, + solarish, + target_os = "aix", + target_os = "haiku", + all( + linux_kernel, + any( + target_arch = "mips", + target_arch = "mips64", + target_arch = "sparc", + target_arch = "sparc64" + ), + ) + )))] + c::SIGSTKFLT => Some(Self::Stkflt), + c::SIGCHLD => Some(Self::Child), + c::SIGCONT => Some(Self::Cont), + c::SIGSTOP => Some(Self::Stop), + c::SIGTSTP => Some(Self::Tstp), + c::SIGTTIN => Some(Self::Ttin), + c::SIGTTOU => Some(Self::Ttou), + c::SIGURG => Some(Self::Urg), + c::SIGXCPU => Some(Self::Xcpu), + c::SIGXFSZ => Some(Self::Xfsz), + c::SIGVTALRM => Some(Self::Vtalarm), + c::SIGPROF => Some(Self::Prof), + c::SIGWINCH => Some(Self::Winch), + #[cfg(not(target_os = "haiku"))] + c::SIGIO => Some(Self::Io), + #[cfg(not(any(bsd, target_os = "haiku")))] + c::SIGPWR => Some(Self::Power), + c::SIGSYS => Some(Self::Sys), + #[cfg(any( + bsd, + solarish, + target_os = "aix", + target_os = "hermit", + all( + linux_kernel, + any( + target_arch = "mips", + target_arch = "mips64", + target_arch = "sparc", + target_arch = "sparc64" + ) + ) + ))] + c::SIGEMT => Some(Self::Emt), + #[cfg(bsd)] + c::SIGINFO => Some(Self::Info), + #[cfg(target_os = "freebsd")] + c::SIGTHR => Some(Self::Thr), + #[cfg(target_os = "freebsd")] + c::SIGLIBRT => Some(Self::Librt), + _ => None, + } + } +} + +#[test] +fn test_sizes() { + use core::mem::size_of; + + assert_eq!(size_of::(), size_of::()); +} diff --git a/vendor/rustix/src/stdio.rs b/vendor/rustix/src/stdio.rs new file mode 100644 index 000000000..278aba06c --- /dev/null +++ b/vendor/rustix/src/stdio.rs @@ -0,0 +1,511 @@ +//! Functions returning the stdio file descriptors. +//! +//! # Safety +//! +//! These access the file descriptors by absolute index value, and nothing +//! prevents them from being closed and reused. They should only be used in +//! `main` or other situations where one is in control of the process' +//! stdio streams. +#![allow(unsafe_code)] + +use crate::backend; +use crate::fd::OwnedFd; +use backend::c; +use backend::fd::{BorrowedFd, FromRawFd, RawFd}; + +#[cfg(not(any(windows, target_os = "wasi")))] +use {crate::io, backend::fd::AsFd, core::mem::forget}; + +/// `STDIN_FILENO`—Standard input, borrowed. +/// +/// In `std`-using configurations, this is a safe function, because the +/// standard library already assumes that the stdin file descriptor is always +/// valid. In `no_std` configurations, it is `unsafe`. +/// +/// # Warning +/// +/// This function allows reading directly from stdin without coordinating +/// with the buffering performed by [`std::io::Stdin`], so it could cause +/// corrupted input. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html +/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdin&sektion=4 +/// [NetBSD]: https://man.netbsd.org/stdin.4 +/// [OpenBSD]: https://man.openbsd.org/stdin.4 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdin§ion=4 +/// [illumos]: https://illumos.org/man/4FS/stdin +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stdin +#[cfg(feature = "std")] +#[doc(alias = "STDIN_FILENO")] +#[inline] +pub const fn stdin() -> BorrowedFd<'static> { + // SAFETY: When "std" is enabled, the standard library assumes that the + // stdio file descriptors are all valid. + unsafe { BorrowedFd::borrow_raw(c::STDIN_FILENO as RawFd) } +} + +/// `STDIN_FILENO`—Standard input, borrowed. +/// +/// In `std`-using configurations, this is a safe function, because the +/// standard library already assumes that the stdin file descriptor is always +/// valid. In `no_std` configurations, it is `unsafe`. +/// +/// # Safety +/// +/// In `no_std` configurations, the stdin file descriptor can be closed, +/// potentially on other threads, in which case the file descriptor index +/// value could be dynamically reused for other purposes, potentially on +/// different threads. +/// +/// # Warning +/// +/// This function allows reading directly from stdin without coordinating +/// with the buffering performed by [`std::io::Stdin`], so it could cause +/// corrupted input. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html +/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdin&sektion=4 +/// [NetBSD]: https://man.netbsd.org/stdin.4 +/// [OpenBSD]: https://man.openbsd.org/stdin.4 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdin§ion=4 +/// [illumos]: https://illumos.org/man/4FS/stdin +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stdin +#[cfg(not(feature = "std"))] +#[doc(alias = "STDIN_FILENO")] +#[inline] +pub const unsafe fn stdin() -> BorrowedFd<'static> { + BorrowedFd::borrow_raw(c::STDIN_FILENO as RawFd) +} + +/// `STDIN_FILENO`—Standard input, owned. +/// +/// This is similar to [`stdin`], however it returns an `OwnedFd` which closes +/// standard input when it is dropped. +/// +/// # Safety +/// +/// Safe `std`-using Rust code is permitted to assume that the stdin file +/// descriptor is always valid. This function returns an `OwnedFd` which will +/// close the stdin file descriptor when dropped. +/// +/// # Warning +/// +/// This has the same hazards as [`stdin`]. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html +/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdin&sektion=4 +/// [NetBSD]: https://man.netbsd.org/stdin.4 +/// [OpenBSD]: https://man.openbsd.org/stdin.4 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdin§ion=4 +/// [illumos]: https://illumos.org/man/4FS/stdin +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stdin +#[doc(alias = "STDIN_FILENO")] +#[inline] +pub unsafe fn take_stdin() -> OwnedFd { + backend::fd::OwnedFd::from_raw_fd(c::STDIN_FILENO as RawFd) +} + +/// `STDOUT_FILENO`—Standard output, borrowed. +/// +/// In `std`-using configurations, this is a safe function, because the +/// standard library already assumes that the stdout file descriptor is always +/// valid. In `no_std` configurations, it is `unsafe`. +/// +/// # Warning +/// +/// This function allows reading directly from stdout without coordinating +/// with the buffering performed by [`std::io::Stdout`], so it could cause +/// corrupted input. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdout.html +/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdout&sektion=4 +/// [NetBSD]: https://man.netbsd.org/stdout.4 +/// [OpenBSD]: https://man.openbsd.org/stdout.4 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdout§ion=4 +/// [illumos]: https://illumos.org/man/4FS/stdout +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stdout +#[cfg(feature = "std")] +#[doc(alias = "STDOUT_FILENO")] +#[inline] +pub const fn stdout() -> BorrowedFd<'static> { + // SAFETY: When "std" is enabled, the standard library assumes that the + // stdio file descriptors are all valid. + unsafe { BorrowedFd::borrow_raw(c::STDOUT_FILENO as RawFd) } +} + +/// `STDOUT_FILENO`—Standard output, borrowed. +/// +/// In `std`-using configurations, this is a safe function, because the +/// standard library already assumes that the stdout file descriptor is always +/// valid. In `no_std` configurations, it is `unsafe`. +/// +/// # Safety +/// +/// In `no_std` configurations, the stdout file descriptor can be closed, +/// potentially on other threads, in which case the file descriptor index +/// value could be dynamically reused for other purposes, potentially on +/// different threads. +/// +/// # Warning +/// +/// This function allows reading directly from stdout without coordinating +/// with the buffering performed by [`std::io::Stdout`], so it could cause +/// corrupted input. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdout.html +/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdout&sektion=4 +/// [NetBSD]: https://man.netbsd.org/stdout.4 +/// [OpenBSD]: https://man.openbsd.org/stdout.4 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdout§ion=4 +/// [illumos]: https://illumos.org/man/4FS/stdout +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stdout +#[cfg(not(feature = "std"))] +#[doc(alias = "STDOUT_FILENO")] +#[inline] +pub const unsafe fn stdout() -> BorrowedFd<'static> { + BorrowedFd::borrow_raw(c::STDOUT_FILENO as RawFd) +} + +/// `STDOUT_FILENO`—Standard output, owned. +/// +/// This is similar to [`stdout`], however it returns an `OwnedFd` which closes +/// standard output when it is dropped. +/// +/// # Safety +/// +/// Safe `std`-using Rust code is permitted to assume that the stdout file +/// descriptor is always valid. This function returns an `OwnedFd` which will +/// close the stdout file descriptor when dropped. +/// +/// # Warning +/// +/// This has the same hazards as [`stdout`]. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdout.html +/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdout&sektion=4 +/// [NetBSD]: https://man.netbsd.org/stdout.4 +/// [OpenBSD]: https://man.openbsd.org/stdout.4 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdout§ion=4 +/// [illumos]: https://illumos.org/man/4FS/stdout +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stdout +#[doc(alias = "STDOUT_FILENO")] +#[inline] +pub unsafe fn take_stdout() -> OwnedFd { + backend::fd::OwnedFd::from_raw_fd(c::STDOUT_FILENO as RawFd) +} + +/// `STDERR_FILENO`—Standard error, borrowed. +/// +/// In `std`-using configurations, this is a safe function, because the +/// standard library already assumes that the stderr file descriptor is always +/// valid. In `no_std` configurations, it is `unsafe`. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stderr.html +/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stderr&sektion=4 +/// [NetBSD]: https://man.netbsd.org/stderr.4 +/// [OpenBSD]: https://man.openbsd.org/stderr.4 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stderr§ion=4 +/// [illumos]: https://illumos.org/man/4FS/stderr +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stderr +#[cfg(feature = "std")] +#[doc(alias = "STDERR_FILENO")] +#[inline] +pub const fn stderr() -> BorrowedFd<'static> { + // SAFETY: When "std" is enabled, the standard library assumes that the + // stdio file descriptors are all valid. + unsafe { BorrowedFd::borrow_raw(c::STDERR_FILENO as RawFd) } +} + +/// `STDERR_FILENO`—Standard error, borrowed. +/// +/// In `std`-using configurations, this is a safe function, because the +/// standard library already assumes that the stderr file descriptor is always +/// valid. In `no_std` configurations, it is `unsafe`. +/// +/// # Safety +/// +/// In `no_std` configurations, the stderr file descriptor can be closed, +/// potentially on other threads, in which case the file descriptor index +/// value could be dynamically reused for other purposes, potentially on +/// different threads. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stderr.html +/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stderr&sektion=4 +/// [NetBSD]: https://man.netbsd.org/stderr.4 +/// [OpenBSD]: https://man.openbsd.org/stderr.4 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stderr§ion=4 +/// [illumos]: https://illumos.org/man/4FS/stderr +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stderr +#[cfg(not(feature = "std"))] +#[doc(alias = "STDERR_FILENO")] +#[inline] +pub const unsafe fn stderr() -> BorrowedFd<'static> { + BorrowedFd::borrow_raw(c::STDERR_FILENO as RawFd) +} + +/// `STDERR_FILENO`—Standard error, owned. +/// +/// This is similar to [`stderr`], however it returns an `OwnedFd` which closes +/// standard output when it is dropped. +/// +/// # Safety +/// +/// Safe std-using Rust code is permitted to assume that the stderr file +/// descriptor is always valid. This function returns an `OwnedFd` which will +/// close the stderr file descriptor when dropped. +/// +/// # Other hazards +/// +/// This has the same hazards as [`stderr`]. +/// +/// And, when the `OwnedFd` is dropped, subsequent newly created file +/// descriptors may unknowingly reuse the stderr file descriptor number, which +/// may break common assumptions, so it should typically only be dropped at the +/// end of a program when no more file descriptors will be created. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stderr.html +/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stderr&sektion=4 +/// [NetBSD]: https://man.netbsd.org/stderr.4 +/// [OpenBSD]: https://man.openbsd.org/stderr.4 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stderr§ion=4 +/// [illumos]: https://illumos.org/man/4FS/stderr +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stderr +#[doc(alias = "STDERR_FILENO")] +#[inline] +pub unsafe fn take_stderr() -> OwnedFd { + backend::fd::OwnedFd::from_raw_fd(c::STDERR_FILENO as RawFd) +} + +/// `STDIN_FILENO`—Standard input, raw. +/// +/// This is similar to [`stdin`], however it returns a `RawFd`. +/// +/// # Other hazards +/// +/// This has the same hazards as [`stdin`]. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdin.html +/// [Linux]: https://man7.org/linux/man-pages/man3/stdin.3.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdin&sektion=4 +/// [NetBSD]: https://man.netbsd.org/stdin.4 +/// [OpenBSD]: https://man.openbsd.org/stdin.4 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdin§ion=4 +/// [illumos]: https://illumos.org/man/4FS/stdin +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stdin +#[doc(alias = "STDIN_FILENO")] +#[inline] +pub const fn raw_stdin() -> RawFd { + c::STDIN_FILENO as RawFd +} + +/// `STDOUT_FILENO`—Standard output, raw. +/// +/// This is similar to [`stdout`], however it returns a `RawFd`. +/// +/// # Other hazards +/// +/// This has the same hazards as [`stdout`]. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stdout.html +/// [Linux]: https://man7.org/linux/man-pages/man3/stdout.3.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stdout&sektion=4 +/// [NetBSD]: https://man.netbsd.org/stdout.4 +/// [OpenBSD]: https://man.openbsd.org/stdout.4 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stdout§ion=4 +/// [illumos]: https://illumos.org/man/4FS/stdout +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stdout +#[doc(alias = "STDOUT_FILENO")] +#[inline] +pub const fn raw_stdout() -> RawFd { + c::STDOUT_FILENO as RawFd +} + +/// `STDERR_FILENO`—Standard error, raw. +/// +/// This is similar to [`stderr`], however it returns a `RawFd`. +/// +/// # Other hazards +/// +/// This has the same hazards as [`stderr`]. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// - [DragonFly BSD] +/// - [illumos] +/// - [glibc] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/stderr.html +/// [Linux]: https://man7.org/linux/man-pages/man3/stderr.3.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=stderr&sektion=4 +/// [NetBSD]: https://man.netbsd.org/stderr.4 +/// [OpenBSD]: https://man.openbsd.org/stderr.4 +/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=stderr§ion=4 +/// [illumos]: https://illumos.org/man/4FS/stderr +/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Standard-Streams.html#index-stderr +#[doc(alias = "STDERR_FILENO")] +#[inline] +pub const fn raw_stderr() -> RawFd { + c::STDERR_FILENO as RawFd +} + +/// Utility function to safely `dup2` over stdin (fd 0). +#[cfg(not(any(windows, target_os = "wasi")))] +#[allow(clippy::mem_forget)] +#[inline] +pub fn dup2_stdin(fd: Fd) -> io::Result<()> { + // SAFETY: We pass the returned `OwnedFd` to `forget` so that it isn't + // dropped. + let mut target = unsafe { take_stdin() }; + backend::io::syscalls::dup2(fd.as_fd(), &mut target)?; + forget(target); + Ok(()) +} + +/// Utility function to safely `dup2` over stdout (fd 1). +#[cfg(not(any(windows, target_os = "wasi")))] +#[allow(clippy::mem_forget)] +#[inline] +pub fn dup2_stdout(fd: Fd) -> io::Result<()> { + // SAFETY: We pass the returned `OwnedFd` to `forget` so that it isn't + // dropped. + let mut target = unsafe { take_stdout() }; + backend::io::syscalls::dup2(fd.as_fd(), &mut target)?; + forget(target); + Ok(()) +} + +/// Utility function to safely `dup2` over stderr (fd 2). +#[cfg(not(any(windows, target_os = "wasi")))] +#[allow(clippy::mem_forget)] +#[inline] +pub fn dup2_stderr(fd: Fd) -> io::Result<()> { + // SAFETY: We pass the returned `OwnedFd` to `forget` so that it isn't + // dropped. + let mut target = unsafe { take_stderr() }; + backend::io::syscalls::dup2(fd.as_fd(), &mut target)?; + forget(target); + Ok(()) +} diff --git a/vendor/rustix/src/system.rs b/vendor/rustix/src/system.rs new file mode 100644 index 000000000..1f04c6b20 --- /dev/null +++ b/vendor/rustix/src/system.rs @@ -0,0 +1,137 @@ +//! Uname and other system-level functions. +//! +//! # Safety +//! +//! This function converts from `struct utsname` fields provided from the +//! kernel into `&str` references, which assumes that they're NUL-terminated. +#![allow(unsafe_code)] + +use crate::backend; +use crate::ffi::CStr; +#[cfg(not(target_os = "emscripten"))] +use crate::io; +use core::fmt; + +#[cfg(linux_kernel)] +pub use backend::system::types::Sysinfo; + +/// `uname()`—Returns high-level information about the runtime OS and +/// hardware. +/// +/// # References +/// - [POSIX] +/// - [Linux] +/// +/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/uname.html +/// [Linux]: https://man7.org/linux/man-pages/man2/uname.2.html +#[inline] +pub fn uname() -> Uname { + Uname(backend::system::syscalls::uname()) +} + +/// `struct utsname`—Return type for [`uname`]. +#[doc(alias = "utsname")] +pub struct Uname(backend::system::types::RawUname); + +impl Uname { + /// `sysname`—Operating system release name + #[inline] + pub fn sysname(&self) -> &CStr { + Self::to_cstr(self.0.sysname.as_ptr().cast()) + } + + /// `nodename`—Name with vague meaning + /// + /// This is intended to be a network name, however it's unable to convey + /// information about hosts that have multiple names, or any information + /// about where the names are visible. + #[inline] + pub fn nodename(&self) -> &CStr { + Self::to_cstr(self.0.nodename.as_ptr().cast()) + } + + /// `release`—Operating system release version string + #[inline] + pub fn release(&self) -> &CStr { + Self::to_cstr(self.0.release.as_ptr().cast()) + } + + /// `version`—Operating system build identifiers + #[inline] + pub fn version(&self) -> &CStr { + Self::to_cstr(self.0.version.as_ptr().cast()) + } + + /// `machine`—Hardware architecture identifier + #[inline] + pub fn machine(&self) -> &CStr { + Self::to_cstr(self.0.machine.as_ptr().cast()) + } + + /// `domainname`—NIS or YP domain identifier + #[cfg(linux_kernel)] + #[inline] + pub fn domainname(&self) -> &CStr { + Self::to_cstr(self.0.domainname.as_ptr().cast()) + } + + #[inline] + fn to_cstr<'a>(ptr: *const u8) -> &'a CStr { + // SAFETY: Strings returned from the kernel are always NUL-terminated. + unsafe { CStr::from_ptr(ptr.cast()) } + } +} + +impl fmt::Debug for Uname { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + #[cfg(not(linux_kernel))] + { + write!( + fmt, + "{} {} {} {} {}", + self.sysname().to_string_lossy(), + self.nodename().to_string_lossy(), + self.release().to_string_lossy(), + self.version().to_string_lossy(), + self.machine().to_string_lossy(), + ) + } + #[cfg(linux_kernel)] + { + write!( + fmt, + "{} {} {} {} {} {}", + self.sysname().to_string_lossy(), + self.nodename().to_string_lossy(), + self.release().to_string_lossy(), + self.version().to_string_lossy(), + self.machine().to_string_lossy(), + self.domainname().to_string_lossy(), + ) + } + } +} + +/// `sysinfo()`—Returns status information about the runtime OS. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/uname.2.html +#[cfg(linux_kernel)] +#[inline] +pub fn sysinfo() -> Sysinfo { + backend::system::syscalls::sysinfo() +} + +/// `sethostname(name)`—Sets the system host name. +/// +/// # References +/// - [Linux] +/// +/// [Linux]: https://man7.org/linux/man-pages/man2/sethostname.2.html +#[cfg(not(any(target_os = "emscripten", target_os = "redox", target_os = "wasi")))] +#[inline] +pub fn sethostname(name: &[u8]) -> io::Result<()> { + backend::system::syscalls::sethostname(name) +} diff --git a/vendor/rustix/src/termios/cf.rs b/vendor/rustix/src/termios/cf.rs deleted file mode 100644 index d79eab5c8..000000000 --- a/vendor/rustix/src/termios/cf.rs +++ /dev/null @@ -1,40 +0,0 @@ -use crate::termios::{Speed, Termios}; -use crate::{backend, io}; - -/// `cfgetospeed(termios)` -#[inline] -#[must_use] -pub fn cfgetospeed(termios: &Termios) -> Speed { - backend::termios::syscalls::cfgetospeed(termios) -} - -/// `cfgetispeed(termios)` -#[inline] -#[must_use] -pub fn cfgetispeed(termios: &Termios) -> Speed { - backend::termios::syscalls::cfgetispeed(termios) -} - -/// `cfmakeraw(termios)` -#[inline] -pub fn cfmakeraw(termios: &mut Termios) { - backend::termios::syscalls::cfmakeraw(termios) -} - -/// `cfsetospeed(termios, speed)` -#[inline] -pub fn cfsetospeed(termios: &mut Termios, speed: Speed) -> io::Result<()> { - backend::termios::syscalls::cfsetospeed(termios, speed) -} - -/// `cfsetispeed(termios, speed)` -#[inline] -pub fn cfsetispeed(termios: &mut Termios, speed: Speed) -> io::Result<()> { - backend::termios::syscalls::cfsetispeed(termios, speed) -} - -/// `cfsetspeed(termios, speed)` -#[inline] -pub fn cfsetspeed(termios: &mut Termios, speed: Speed) -> io::Result<()> { - backend::termios::syscalls::cfsetspeed(termios, speed) -} diff --git a/vendor/rustix/src/termios/constants.rs b/vendor/rustix/src/termios/constants.rs deleted file mode 100644 index 99b75c06e..000000000 --- a/vendor/rustix/src/termios/constants.rs +++ /dev/null @@ -1,101 +0,0 @@ -use crate::backend; - -pub use backend::termios::types::*; - -/// Translate from a `Speed` code to a speed value `u32`. -/// -/// ``` -/// let speed = rustix::termios::speed_value(rustix::termios::B57600); -/// assert_eq!(speed, Some(57600)); -/// ``` -pub fn speed_value(speed: backend::termios::types::Speed) -> Option { - match speed { - backend::termios::types::B0 => Some(0), - backend::termios::types::B50 => Some(50), - backend::termios::types::B75 => Some(75), - backend::termios::types::B110 => Some(110), - backend::termios::types::B134 => Some(134), - backend::termios::types::B150 => Some(150), - backend::termios::types::B200 => Some(200), - backend::termios::types::B300 => Some(300), - backend::termios::types::B600 => Some(600), - backend::termios::types::B1200 => Some(1200), - backend::termios::types::B1800 => Some(1800), - backend::termios::types::B2400 => Some(2400), - backend::termios::types::B4800 => Some(4800), - backend::termios::types::B9600 => Some(9600), - backend::termios::types::B19200 => Some(19200), - backend::termios::types::B38400 => Some(38400), - #[cfg(not(target_os = "aix"))] - backend::termios::types::B57600 => Some(57600), - #[cfg(not(target_os = "aix"))] - backend::termios::types::B115200 => Some(115_200), - #[cfg(not(target_os = "aix"))] - backend::termios::types::B230400 => Some(230_400), - #[cfg(not(any( - apple, - target_os = "aix", - target_os = "dragonfly", - target_os = "haiku", - target_os = "openbsd" - )))] - backend::termios::types::B460800 => Some(460_800), - #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] - backend::termios::types::B500000 => Some(500_000), - #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] - backend::termios::types::B576000 => Some(576_000), - #[cfg(not(any( - apple, - target_os = "aix", - target_os = "dragonfly", - target_os = "haiku", - target_os = "openbsd" - )))] - backend::termios::types::B921600 => Some(921_600), - #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] - backend::termios::types::B1000000 => Some(1_000_000), - #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] - backend::termios::types::B1152000 => Some(1_152_000), - #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] - backend::termios::types::B1500000 => Some(1_500_000), - #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] - backend::termios::types::B2000000 => Some(2_000_000), - #[cfg(not(any( - target_arch = "sparc", - target_arch = "sparc64", - bsd, - target_os = "aix", - target_os = "haiku", - target_os = "solaris", - )))] - backend::termios::types::B2500000 => Some(2_500_000), - #[cfg(not(any( - target_arch = "sparc", - target_arch = "sparc64", - bsd, - target_os = "aix", - target_os = "haiku", - target_os = "solaris", - )))] - backend::termios::types::B3000000 => Some(3_000_000), - #[cfg(not(any( - target_arch = "sparc", - target_arch = "sparc64", - bsd, - target_os = "aix", - target_os = "haiku", - target_os = "solaris", - )))] - backend::termios::types::B3500000 => Some(3_500_000), - #[cfg(not(any( - target_arch = "sparc", - target_arch = "sparc64", - bsd, - target_os = "aix", - target_os = "haiku", - target_os = "solaris", - )))] - backend::termios::types::B4000000 => Some(4_000_000), - _ => None, - } -} diff --git a/vendor/rustix/src/termios/ioctl.rs b/vendor/rustix/src/termios/ioctl.rs new file mode 100644 index 000000000..2e8a28ed6 --- /dev/null +++ b/vendor/rustix/src/termios/ioctl.rs @@ -0,0 +1,42 @@ +//! Terminal-related `ioctl` functions. + +use crate::fd::AsFd; +use crate::{backend, io}; + +/// `ioctl(fd, TIOCEXCL)`—Enables exclusive mode on a terminal. +/// +/// # References +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// +/// [Linux]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=tty&sektion=4 +/// [NetBSD]: https://man.netbsd.org/tty.4 +/// [OpenBSD]: https://man.openbsd.org/tty.4 +#[cfg(not(any(windows, target_os = "haiku", target_os = "redox", target_os = "wasi")))] +#[inline] +#[doc(alias = "TIOCEXCL")] +pub fn ioctl_tiocexcl(fd: Fd) -> io::Result<()> { + backend::termios::syscalls::ioctl_tiocexcl(fd.as_fd()) +} + +/// `ioctl(fd, TIOCNXCL)`—Disables exclusive mode on a terminal. +/// +/// # References +/// - [Linux] +/// - [FreeBSD] +/// - [NetBSD] +/// - [OpenBSD] +/// +/// [Linux]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html +/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=tty&sektion=4 +/// [NetBSD]: https://man.netbsd.org/tty.4 +/// [OpenBSD]: https://man.openbsd.org/tty.4 +#[cfg(not(any(windows, target_os = "haiku", target_os = "redox", target_os = "wasi")))] +#[inline] +#[doc(alias = "TIOCNXCL")] +pub fn ioctl_tiocnxcl(fd: Fd) -> io::Result<()> { + backend::termios::syscalls::ioctl_tiocnxcl(fd.as_fd()) +} diff --git a/vendor/rustix/src/termios/mod.rs b/vendor/rustix/src/termios/mod.rs index ffbb1b663..28abc0488 100644 --- a/vendor/rustix/src/termios/mod.rs +++ b/vendor/rustix/src/termios/mod.rs @@ -1,19 +1,27 @@ //! Terminal I/O stream operations. +//! +//! This API automatically supports setting arbitrary I/O speeds, on any +//! platform that supports them, including Linux and the BSDs. +//! +//! The [`speed`] module contains various predefined speed constants which +//! are more likely to be portable, however any `u32` value can be passed to +//! [`Termios::set_input_speed`], and it will simply fail if the speed is not +//! supported by the platform. #[cfg(not(target_os = "wasi"))] -mod cf; -#[cfg(not(target_os = "wasi"))] -mod constants; +mod ioctl; #[cfg(not(target_os = "wasi"))] mod tc; #[cfg(not(windows))] mod tty; - #[cfg(not(target_os = "wasi"))] -pub use cf::*; +mod types; + #[cfg(not(target_os = "wasi"))] -pub use constants::*; +pub use ioctl::*; #[cfg(not(target_os = "wasi"))] pub use tc::*; #[cfg(not(windows))] pub use tty::*; +#[cfg(not(target_os = "wasi"))] +pub use types::*; diff --git a/vendor/rustix/src/termios/tc.rs b/vendor/rustix/src/termios/tc.rs index 12f7f543c..9deb7798c 100644 --- a/vendor/rustix/src/termios/tc.rs +++ b/vendor/rustix/src/termios/tc.rs @@ -1,28 +1,11 @@ use crate::fd::AsFd; -use crate::process::Pid; +use crate::pid::Pid; +use crate::termios::{Action, OptionalActions, QueueSelector, Termios, Winsize}; use crate::{backend, io}; -#[cfg(all( - any(target_os = "android", target_os = "linux"), - any( - target_arch = "x86", - target_arch = "x86_64", - target_arch = "x32", - target_arch = "riscv64", - target_arch = "aarch64", - target_arch = "arm", - target_arch = "mips", - target_arch = "mips64", - ) -))] -pub use backend::termios::types::Termios2; -pub use backend::termios::types::{ - Action, OptionalActions, QueueSelector, Speed, Tcflag, Termios, Winsize, -}; - /// `tcgetattr(fd)`—Get terminal attributes. /// -/// Also known as the `TCGETS` operation with `ioctl`. +/// Also known as the `TCGETS` (or `TCGETS2` on Linux) operation with `ioctl`. /// /// # References /// - [POSIX `tcgetattr`] @@ -35,41 +18,12 @@ pub use backend::termios::types::{ #[cfg(not(any(windows, target_os = "wasi")))] #[inline] #[doc(alias = "TCGETS")] +#[doc(alias = "TCGETS2")] +#[doc(alias = "tcgetattr2")] pub fn tcgetattr(fd: Fd) -> io::Result { backend::termios::syscalls::tcgetattr(fd.as_fd()) } -/// `tcgetattr2(fd)`—Get terminal attributes. -/// -/// Also known as the `TCGETS2` operation with `ioctl`. -/// -/// # References -/// - [POSIX `tcgetattr`] -/// - [Linux `ioctl_tty`] -/// - [Linux `termios`] -/// -/// [POSIX `tcgetattr`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html -/// [Linux `ioctl_tty`]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html -/// [Linux `termios`]: https://man7.org/linux/man-pages/man3/termios.3.html -#[inline] -#[doc(alias = "TCGETS2")] -#[cfg(all( - any(target_os = "android", target_os = "linux"), - any( - target_arch = "x86", - target_arch = "x86_64", - target_arch = "x32", - target_arch = "riscv64", - target_arch = "aarch64", - target_arch = "arm", - target_arch = "mips", - target_arch = "mips64", - ) -))] -pub fn tcgetattr2(fd: Fd) -> io::Result { - backend::termios::syscalls::tcgetattr2(fd.as_fd()) -} - /// `tcgetwinsize(fd)`—Get the current terminal window size. /// /// Also known as the `TIOCGWINSZ` operation with `ioctl`. @@ -121,7 +75,7 @@ pub fn tcsetpgrp(fd: Fd, pid: Pid) -> io::Result<()> { /// `tcsetattr(fd)`—Set terminal attributes. /// -/// Also known as the `TCSETS` operation with `ioctl`. +/// Also known as the `TCSETS` (or `TCSETS2 on Linux) operation with `ioctl`. /// /// # References /// - [POSIX `tcsetattr`] @@ -133,6 +87,8 @@ pub fn tcsetpgrp(fd: Fd, pid: Pid) -> io::Result<()> { /// [Linux `termios`]: https://man7.org/linux/man-pages/man3/termios.3.html #[inline] #[doc(alias = "TCSETS")] +#[doc(alias = "TCSETS2")] +#[doc(alias = "tcsetattr2")] pub fn tcsetattr( fd: Fd, optional_actions: OptionalActions, @@ -141,41 +97,6 @@ pub fn tcsetattr( backend::termios::syscalls::tcsetattr(fd.as_fd(), optional_actions, termios) } -/// `tcsetattr2(fd)`—Set terminal attributes. -/// -/// Also known as the `TCSETS2` operation with `ioctl`. -/// -/// # References -/// - [POSIX `tcsetattr`] -/// - [Linux `ioctl_tty`] -/// - [Linux `termios`] -/// -/// [POSIX `tcsetattr`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetattr.html -/// [Linux `ioctl_tty`]: https://man7.org/linux/man-pages/man4/tty_ioctl.4.html -/// [Linux `termios`]: https://man7.org/linux/man-pages/man3/termios.3.html -#[inline] -#[doc(alias = "TCSETS2")] -#[cfg(all( - any(target_os = "android", target_os = "linux"), - any( - target_arch = "x86", - target_arch = "x86_64", - target_arch = "x32", - target_arch = "riscv64", - target_arch = "aarch64", - target_arch = "arm", - target_arch = "mips", - target_arch = "mips64", - ) -))] -pub fn tcsetattr2( - fd: Fd, - optional_actions: OptionalActions, - termios: &Termios2, -) -> io::Result<()> { - backend::termios::syscalls::tcsetattr2(fd.as_fd(), optional_actions, termios) -} - /// `tcsendbreak(fd, 0)`—Transmit zero-valued bits. /// /// Also known as the `TCSBRK` operation with `ioctl`, with a duration of 0. diff --git a/vendor/rustix/src/termios/tty.rs b/vendor/rustix/src/termios/tty.rs index 76ffd8609..00787a568 100644 --- a/vendor/rustix/src/termios/tty.rs +++ b/vendor/rustix/src/termios/tty.rs @@ -1,18 +1,11 @@ //! Functions which operate on file descriptors which might be terminals. use crate::backend; -#[cfg(any( - all(linux_raw, feature = "procfs"), - all(libc, not(any(target_os = "fuchsia", target_os = "wasi"))), -))] -use crate::io; use backend::fd::AsFd; -#[cfg(any( - all(linux_raw, feature = "procfs"), - all(libc, not(any(target_os = "fuchsia", target_os = "wasi"))), -))] +#[cfg(feature = "procfs")] +#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] use { - crate::ffi::CString, crate::path::SMALL_PATH_BUFFER_SIZE, alloc::vec::Vec, + crate::ffi::CString, crate::io, crate::path::SMALL_PATH_BUFFER_SIZE, alloc::vec::Vec, backend::fd::BorrowedFd, }; @@ -31,7 +24,7 @@ pub fn isatty(fd: Fd) -> bool { /// `ttyname_r(fd)` /// -/// If `reuse` is non-empty, reuse its buffer to store the result if possible. +/// If `reuse` already has available capacity, reuse it if possible. /// /// # References /// - [POSIX] @@ -50,22 +43,36 @@ pub fn ttyname>>(dirfd: Fd, reuse: B) -> io::Result, mut buffer: Vec) -> io::Result { - // This code would benefit from having a better way to read into - // uninitialized memory, but that requires `unsafe`. buffer.clear(); buffer.reserve(SMALL_PATH_BUFFER_SIZE); - buffer.resize(buffer.capacity(), 0_u8); loop { - match backend::termios::syscalls::ttyname(dirfd, &mut buffer) { + match backend::termios::syscalls::ttyname(dirfd, buffer.spare_capacity_mut()) { Err(io::Errno::RANGE) => { - buffer.reserve(1); // use `Vec` reallocation strategy to grow capacity exponentially - buffer.resize(buffer.capacity(), 0_u8); + buffer.reserve(buffer.capacity() + 1); // use `Vec` reallocation strategy to grow capacity exponentially } Ok(len) => { - buffer.resize(len, 0_u8); - return Ok(CString::new(buffer).unwrap()); + // SAFETY: assume the backend returns the length of the string + unsafe { + buffer.set_len(len); + } + + // SAFETY: + // - "ttyname_r stores this pathname in the buffer buf" + // - [POSIX definition 3.271: Pathname]: "A string that is used to identify a + // file." + // - [POSIX definition 3.375: String]: "A contiguous sequence of bytes + // terminated by and including the first null byte." + // + // Thus, there will be a single NUL byte at the end of the string. + // + // [POSIX definition 3.271: Pathname]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_271 + // [POSIX definition 3.375: String]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_375 + unsafe { + return Ok(CString::from_vec_with_nul_unchecked(buffer)); + } } Err(errno) => return Err(errno), } diff --git a/vendor/rustix/src/termios/types.rs b/vendor/rustix/src/termios/types.rs new file mode 100644 index 000000000..d978bfcca --- /dev/null +++ b/vendor/rustix/src/termios/types.rs @@ -0,0 +1,1273 @@ +use crate::backend::c; +use crate::{backend, io}; +use bitflags::bitflags; + +/// `struct termios` for use with [`tcgetattr`] and [`tcsetattr`]. +/// +/// [`tcgetattr`]: crate::termios::tcgetattr +/// [`tcsetattr`]: crate::termios::tcsetattr +#[repr(C)] +#[derive(Clone)] +pub struct Termios { + /// How is input interpreted? + #[doc(alias = "c_iflag")] + pub input_modes: InputModes, + + /// How is output translated? + #[doc(alias = "c_oflag")] + pub output_modes: OutputModes, + + /// Low-level configuration flags. + #[doc(alias = "c_cflag")] + pub control_modes: ControlModes, + + /// High-level configuration flags. + #[doc(alias = "c_lflag")] + pub local_modes: LocalModes, + + /// Line discipline. + #[doc(alias = "c_line")] + #[cfg(not(all(linux_raw, any(target_arch = "powerpc", target_arch = "powerpc64"))))] + #[cfg(any( + linux_like, + target_env = "newlib", + target_os = "haiku", + target_os = "fuchsia", + target_os = "redox" + ))] + pub line_discipline: c::cc_t, + + /// How are various special control codes handled? + #[doc(alias = "c_cc")] + pub special_codes: SpecialCodes, + + /// Line discipline. + // On PowerPC, this field comes after `c_cc`. + #[doc(alias = "c_line")] + #[cfg(all(linux_raw, any(target_arch = "powerpc", target_arch = "powerpc64")))] + pub line_discipline: c::cc_t, + + /// See the `input_speed` and `set_input_seed` functions. + /// + /// On Linux and BSDs, this is the arbitrary integer speed value. On all + /// other platforms, this is the encoded speed value. + pub(crate) input_speed: c::speed_t, + + /// See the `output_speed` and `set_output_seed` functions. + /// + /// On Linux and BSDs, this is the integer speed value. On all other + /// platforms, this is the encoded speed value. + pub(crate) output_speed: c::speed_t, +} + +impl Termios { + /// `cfmakeraw(self)`—Set a `Termios` value to the settings for "raw" mode. + /// + /// In raw mode, input is available a byte at a time, echoing is disabled, + /// and special terminal input and output codes are disabled. + #[doc(alias = "cfmakeraw")] + #[inline] + pub fn make_raw(&mut self) { + backend::termios::syscalls::cfmakeraw(self) + } + + /// Return the input communication speed. + /// + /// Unlike the `c_ispeed` field in GLIBC and others, this returns the + /// integer value of the speed, rather than the `B*` encoded constant + /// value. + #[doc(alias = "c_ispeed")] + #[doc(alias = "cfgetispeed")] + #[doc(alias = "cfgetspeed")] + #[inline] + pub fn input_speed(&self) -> u32 { + // On Linux and BSDs, `input_speed` is the arbitrary integer speed. + #[cfg(any(linux_kernel, bsd))] + { + debug_assert!(u32::try_from(self.input_speed).is_ok()); + self.input_speed as u32 + } + + // On other platforms, it's the encoded speed. + #[cfg(not(any(linux_kernel, bsd)))] + { + speed::decode(self.input_speed).unwrap() + } + } + + /// Return the output communication speed. + /// + /// Unlike the `c_ospeed` field in GLIBC and others, this returns the + /// arbitrary integer value of the speed, rather than the `B*` encoded + /// constant value. + #[inline] + pub fn output_speed(&self) -> u32 { + // On Linux and BSDs, `input_speed` is the arbitrary integer speed. + #[cfg(any(linux_kernel, bsd))] + { + debug_assert!(u32::try_from(self.output_speed).is_ok()); + self.output_speed as u32 + } + + // On other platforms, it's the encoded speed. + #[cfg(not(any(linux_kernel, bsd)))] + { + speed::decode(self.output_speed).unwrap() + } + } + + /// Set the input and output communication speeds. + /// + /// Unlike the `c_ispeed` and `c_ospeed` fields in GLIBC and others, this + /// takes the arbitrary integer value of the speed, rather than the `B*` + /// encoded constant value. Not all implementations support all integer + /// values; use the constants in the [`speed`] module for likely-supported + /// speeds. + #[doc(alias = "cfsetspeed")] + #[doc(alias = "CBAUD")] + #[doc(alias = "CBAUDEX")] + #[doc(alias = "CIBAUD")] + #[doc(alias = "CIBAUDEX")] + #[inline] + pub fn set_speed(&mut self, new_speed: u32) -> io::Result<()> { + backend::termios::syscalls::set_speed(self, new_speed) + } + + /// Set the input communication speed. + /// + /// Unlike the `c_ispeed` field in GLIBC and others, this takes the + /// arbitrary integer value of the speed, rather than the `B*` encoded + /// constant value. Not all implementations support all integer values; use + /// the constants in the [`speed`] module for known-supported speeds. + /// + /// On some platforms, changing the input speed changes the output speed + /// to the same speed. + #[doc(alias = "c_ispeed")] + #[doc(alias = "cfsetispeed")] + #[doc(alias = "CIBAUD")] + #[doc(alias = "CIBAUDEX")] + #[inline] + pub fn set_input_speed(&mut self, new_speed: u32) -> io::Result<()> { + backend::termios::syscalls::set_input_speed(self, new_speed) + } + + /// Set the output communication speed. + /// + /// Unlike the `c_ospeed` field in GLIBC and others, this takes the + /// arbitrary integer value of the speed, rather than the `B*` encoded + /// constant value. Not all implementations support all integer values; use + /// the constants in the [`speed`] module for known-supported speeds. + /// + /// On some platforms, changing the output speed changes the input speed + /// to the same speed. + #[doc(alias = "c_ospeed")] + #[doc(alias = "cfsetospeed")] + #[doc(alias = "CBAUD")] + #[doc(alias = "CBAUDEX")] + #[inline] + pub fn set_output_speed(&mut self, new_speed: u32) -> io::Result<()> { + backend::termios::syscalls::set_output_speed(self, new_speed) + } +} + +impl core::fmt::Debug for Termios { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut d = f.debug_struct("Termios"); + d.field("input_modes", &self.input_modes); + d.field("output_modes", &self.output_modes); + d.field("control_modes", &self.control_modes); + d.field("local_modes", &self.local_modes); + #[cfg(any( + linux_like, + target_env = "newlib", + target_os = "haiku", + target_os = "fuchsia", + target_os = "redox" + ))] + { + d.field("line_discipline", &self.line_discipline); + } + d.field("special_codes", &self.special_codes); + d.field("input_speed", &self.input_speed()); + d.field("output_speed", &self.output_speed()); + d.finish() + } +} + +bitflags! { + /// Flags controlling terminal input. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct InputModes: c::tcflag_t { + /// `IGNBRK` + const IGNBRK = c::IGNBRK; + + /// `BRKINT` + const BRKINT = c::BRKINT; + + /// `IGNPAR` + const IGNPAR = c::IGNPAR; + + /// `PARMRK` + const PARMRK = c::PARMRK; + + /// `INPCK` + const INPCK = c::INPCK; + + /// `ISTRIP` + const ISTRIP = c::ISTRIP; + + /// `INLCR` + const INLCR = c::INLCR; + + /// `IGNCR` + const IGNCR = c::IGNCR; + + /// `ICRNL` + const ICRNL = c::ICRNL; + + /// `IUCLC` + #[cfg(any(linux_kernel, solarish, target_os = "haiku"))] + const IUCLC = c::IUCLC; + + /// `IXON` + const IXON = c::IXON; + + /// `IXANY` + #[cfg(not(target_os = "redox"))] + const IXANY = c::IXANY; + + /// `IXOFF` + const IXOFF = c::IXOFF; + + /// `IMAXBEL` + #[cfg(not(any(target_os = "haiku", target_os = "redox")))] + const IMAXBEL = c::IMAXBEL; + + /// `IUTF8` + #[cfg(not(any( + solarish, + target_os = "aix", + target_os = "dragonfly", + target_os = "emscripten", + target_os = "freebsd", + target_os = "haiku", + target_os = "netbsd", + target_os = "openbsd", + target_os = "redox", + )))] + const IUTF8 = c::IUTF8; + } +} + +bitflags! { + /// Flags controlling terminal output. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct OutputModes: c::tcflag_t { + /// `OPOST` + const OPOST = c::OPOST; + + /// `OLCUC` + #[cfg(not(any( + apple, + target_os = "aix", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd", + target_os = "redox", + )))] + const OLCUC = c::OLCUC; + + /// `ONLCR` + const ONLCR = c::ONLCR; + + /// `OCRNL` + const OCRNL = c::OCRNL; + + /// `ONOCR` + const ONOCR = c::ONOCR; + + /// `ONLRET` + const ONLRET = c::ONLRET; + + /// `OFILL` + #[cfg(not(bsd))] + const OFILL = c::OFILL; + + /// `OFDEL` + #[cfg(not(bsd))] + const OFDEL = c::OFDEL; + + /// `NLDLY` + #[cfg(not(any(bsd, solarish, target_os = "redox")))] + const NLDLY = c::NLDLY; + + /// `NL0` + #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] + const NL0 = c::NL0; + + /// `NL1` + #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] + const NL1 = c::NL1; + + /// `CRDLY` + #[cfg(not(any(bsd, solarish, target_os = "redox")))] + const CRDLY = c::CRDLY; + + /// `CR0` + #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] + const CR0 = c::CR0; + + /// `CR1` + #[cfg(not(any( + target_env = "musl", + bsd, + solarish, + target_os = "emscripten", + target_os = "fuchsia", + target_os = "redox", + )))] + const CR1 = c::CR1; + + /// `CR2` + #[cfg(not(any( + target_env = "musl", + bsd, + solarish, + target_os = "emscripten", + target_os = "fuchsia", + target_os = "redox", + )))] + const CR2 = c::CR2; + + /// `CR3` + #[cfg(not(any( + target_env = "musl", + bsd, + solarish, + target_os = "emscripten", + target_os = "fuchsia", + target_os = "redox", + )))] + const CR3 = c::CR3; + + /// `TABDLY` + #[cfg(not(any( + netbsdlike, + solarish, + target_os = "dragonfly", + target_os = "redox", + )))] + const TABDLY = c::TABDLY; + + /// `TAB0` + #[cfg(not(any( + netbsdlike, + solarish, + target_os = "dragonfly", + target_os = "fuchsia", + target_os = "redox", + )))] + const TAB0 = c::TAB0; + + /// `TAB1` + #[cfg(not(any( + target_env = "musl", + bsd, + solarish, + target_os = "emscripten", + target_os = "fuchsia", + target_os = "redox", + )))] + const TAB1 = c::TAB1; + + /// `TAB2` + #[cfg(not(any( + target_env = "musl", + bsd, + solarish, + target_os = "emscripten", + target_os = "fuchsia", + target_os = "redox", + )))] + const TAB2 = c::TAB2; + + /// `TAB3` + #[cfg(not(any( + target_env = "musl", + bsd, + solarish, + target_os = "emscripten", + target_os = "fuchsia", + target_os = "redox", + )))] + const TAB3 = c::TAB3; + + /// `XTABS` + #[cfg(not(any( + bsd, + solarish, + target_os = "aix", + target_os = "haiku", + target_os = "redox", + )))] + const XTABS = c::XTABS; + + /// `BSDLY` + #[cfg(not(any(bsd, solarish, target_os = "redox")))] + const BSDLY = c::BSDLY; + + /// `BS0` + #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] + const BS0 = c::BS0; + + /// `BS1` + #[cfg(not(any( + target_env = "musl", + bsd, + solarish, + target_os = "emscripten", + target_os = "fuchsia", + target_os = "redox", + )))] + const BS1 = c::BS1; + + /// `FFDLY` + #[cfg(not(any(bsd, solarish, target_os = "redox")))] + const FFDLY = c::FFDLY; + + /// `FF0` + #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] + const FF0 = c::FF0; + + /// `FF1` + #[cfg(not(any( + target_env = "musl", + bsd, + solarish, + target_os = "emscripten", + target_os = "fuchsia", + target_os = "redox", + )))] + const FF1 = c::FF1; + + /// `VTDLY` + #[cfg(not(any(bsd, solarish, target_os = "redox")))] + const VTDLY = c::VTDLY; + + /// `VT0` + #[cfg(not(any(bsd, solarish, target_os = "fuchsia", target_os = "redox")))] + const VT0 = c::VT0; + + /// `VT1` + #[cfg(not(any( + target_env = "musl", + bsd, + solarish, + target_os = "emscripten", + target_os = "fuchsia", + target_os = "redox", + )))] + const VT1 = c::VT1; + } +} + +bitflags! { + /// Flags controlling special terminal modes. + /// + /// `CBAUD`, `CBAUDEX`, `CIBAUD`, and `CIBAUDEX` are not defined here, + /// because they're handled automatically by [`Termios::set_speed`] and + /// related functions. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct ControlModes: c::tcflag_t { + /// `CSIZE` + const CSIZE = c::CSIZE; + + /// `CS5` + const CS5 = c::CS5; + + /// `CS6` + const CS6 = c::CS6; + + /// `CS7` + const CS7 = c::CS7; + + /// `CS8` + const CS8 = c::CS8; + + /// `CSTOPB` + const CSTOPB = c::CSTOPB; + + /// `CREAD` + const CREAD = c::CREAD; + + /// `PARENB` + const PARENB = c::PARENB; + + /// `PARODD` + const PARODD = c::PARODD; + + /// `HUPCL` + const HUPCL = c::HUPCL; + + /// `CLOCAL` + const CLOCAL = c::CLOCAL; + + /// `CRTSCTS` + #[cfg(not(any(target_os = "aix", target_os = "redox")))] + const CRTSCTS = c::CRTSCTS; + + /// `CMSPAR` + #[cfg(not(any( + bsd, + solarish, + target_os = "aix", + target_os = "emscripten", + target_os = "haiku", + target_os = "redox", + )))] + const CMSPAR = c::CMSPAR; + } +} + +bitflags! { + /// Flags controlling "local" terminal modes. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct LocalModes: c::tcflag_t { + /// `XCASE` + #[cfg(any(linux_kernel, target_arch = "s390x", target_os = "haiku"))] + const XCASE = c::XCASE; + + /// `ECHOCTL` + #[cfg(not(target_os = "redox"))] + const ECHOCTL = c::ECHOCTL; + + /// `ECHOPRT` + #[cfg(not(target_os = "redox"))] + const ECHOPRT = c::ECHOPRT; + + /// `ECHOKE` + #[cfg(not(target_os = "redox"))] + const ECHOKE = c::ECHOKE; + + /// `FLUSHO` + #[cfg(not(target_os = "redox"))] + const FLUSHO = c::FLUSHO; + + /// `PENDIN` + #[cfg(not(target_os = "redox"))] + const PENDIN = c::PENDIN; + + /// `EXTPROC` + #[cfg(not(any(target_os = "aix", target_os = "haiku", target_os = "redox")))] + const EXTPROC = c::EXTPROC; + + /// `ISIG` + const ISIG = c::ISIG; + + /// `ICANON`—A flag for the `c_lflag` field of [`Termios`] indicating + /// canonical mode. + const ICANON = c::ICANON; + + /// `ECHO` + const ECHO = c::ECHO; + + /// `ECHOE` + const ECHOE = c::ECHOE; + + /// `ECHOK` + const ECHOK = c::ECHOK; + + /// `ECHONL` + const ECHONL = c::ECHONL; + + /// `NOFLSH` + const NOFLSH = c::NOFLSH; + + /// `TOSTOP` + const TOSTOP = c::TOSTOP; + + /// `IEXTEN` + const IEXTEN = c::IEXTEN; + } +} + +/// Speeds for use with [`Termios::set_input_speed`] and +/// [`Termios::set_output_speed`]. +/// +/// Unlike in some platforms' libc APIs, these always have the same numerical +/// value as their names; for example, `B50` has the value `50`, and so on. +/// Consequently, it's not necessary to use them. They are provided here +/// because they help identify speeds which are likely to be supported, on +/// platforms which don't support arbitrary speeds. +pub mod speed { + #[cfg(not(bsd))] + use crate::backend::c; + + /// `B0` + pub const B0: u32 = 0; + + /// `B50` + pub const B50: u32 = 50; + + /// `B75` + pub const B75: u32 = 75; + + /// `B110` + pub const B110: u32 = 110; + + /// `B134` + pub const B134: u32 = 134; + + /// `B150` + pub const B150: u32 = 150; + + /// `B200` + pub const B200: u32 = 200; + + /// `B300` + pub const B300: u32 = 300; + + /// `B600` + pub const B600: u32 = 600; + + /// `B1200` + pub const B1200: u32 = 1200; + + /// `B1800` + pub const B1800: u32 = 1800; + + /// `B2400` + pub const B2400: u32 = 2400; + + /// `B4800` + pub const B4800: u32 = 4800; + + /// `B9600` + pub const B9600: u32 = 9600; + + /// `B19200` + #[doc(alias = "EXTA")] + pub const B19200: u32 = 19200; + + /// `B38400` + #[doc(alias = "EXTB")] + pub const B38400: u32 = 38400; + + /// `B57600` + #[cfg(not(target_os = "aix"))] + pub const B57600: u32 = 57600; + + /// `B115200` + #[cfg(not(target_os = "aix"))] + pub const B115200: u32 = 115_200; + + /// `B230400` + #[cfg(not(target_os = "aix"))] + pub const B230400: u32 = 230_400; + + /// `B460800` + #[cfg(not(any( + apple, + target_os = "aix", + target_os = "dragonfly", + target_os = "haiku", + target_os = "openbsd" + )))] + pub const B460800: u32 = 460_800; + + /// `B500000` + #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] + pub const B500000: u32 = 500_000; + + /// `B576000` + #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] + pub const B576000: u32 = 576_000; + + /// `B921600` + #[cfg(not(any( + apple, + target_os = "aix", + target_os = "dragonfly", + target_os = "haiku", + target_os = "openbsd" + )))] + pub const B921600: u32 = 921_600; + + /// `B1000000` + #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] + pub const B1000000: u32 = 1_000_000; + + /// `B1152000` + #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] + pub const B1152000: u32 = 1_152_000; + + /// `B1500000` + #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] + pub const B1500000: u32 = 1_500_000; + + /// `B2000000` + #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] + pub const B2000000: u32 = 2_000_000; + + /// `B2500000` + #[cfg(not(any( + target_arch = "sparc", + target_arch = "sparc64", + bsd, + target_os = "aix", + target_os = "haiku", + target_os = "solaris", + )))] + pub const B2500000: u32 = 2_500_000; + + /// `B3000000` + #[cfg(not(any( + target_arch = "sparc", + target_arch = "sparc64", + bsd, + target_os = "aix", + target_os = "haiku", + target_os = "solaris", + )))] + pub const B3000000: u32 = 3_000_000; + + /// `B3500000` + #[cfg(not(any( + target_arch = "sparc", + target_arch = "sparc64", + bsd, + target_os = "aix", + target_os = "haiku", + target_os = "solaris", + )))] + pub const B3500000: u32 = 3_500_000; + + /// `B4000000` + #[cfg(not(any( + target_arch = "sparc", + target_arch = "sparc64", + bsd, + target_os = "aix", + target_os = "haiku", + target_os = "solaris", + )))] + pub const B4000000: u32 = 4_000_000; + + /// Translate from a `c::speed_t` code to an arbitrary integer speed value + /// `u32`. + #[cfg(not(any(linux_kernel, bsd)))] + pub(crate) fn decode(encoded_speed: c::speed_t) -> Option { + match encoded_speed { + c::B0 => Some(0), + c::B50 => Some(50), + c::B75 => Some(75), + c::B110 => Some(110), + c::B134 => Some(134), + c::B150 => Some(150), + c::B200 => Some(200), + c::B300 => Some(300), + c::B600 => Some(600), + c::B1200 => Some(1200), + c::B1800 => Some(1800), + c::B2400 => Some(2400), + c::B4800 => Some(4800), + c::B9600 => Some(9600), + c::B19200 => Some(19200), + c::B38400 => Some(38400), + #[cfg(not(target_os = "aix"))] + c::B57600 => Some(57600), + #[cfg(not(target_os = "aix"))] + c::B115200 => Some(115_200), + #[cfg(not(target_os = "aix"))] + c::B230400 => Some(230_400), + #[cfg(not(any( + apple, + target_os = "aix", + target_os = "dragonfly", + target_os = "haiku", + target_os = "openbsd" + )))] + c::B460800 => Some(460_800), + #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] + c::B500000 => Some(500_000), + #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] + c::B576000 => Some(576_000), + #[cfg(not(any( + apple, + target_os = "aix", + target_os = "dragonfly", + target_os = "haiku", + target_os = "openbsd" + )))] + c::B921600 => Some(921_600), + #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] + c::B1000000 => Some(1_000_000), + #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] + c::B1152000 => Some(1_152_000), + #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] + c::B1500000 => Some(1_500_000), + #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] + c::B2000000 => Some(2_000_000), + #[cfg(not(any( + target_arch = "sparc", + target_arch = "sparc64", + bsd, + target_os = "aix", + target_os = "haiku", + target_os = "solaris", + )))] + c::B2500000 => Some(2_500_000), + #[cfg(not(any( + target_arch = "sparc", + target_arch = "sparc64", + bsd, + target_os = "aix", + target_os = "haiku", + target_os = "solaris", + )))] + c::B3000000 => Some(3_000_000), + #[cfg(not(any( + target_arch = "sparc", + target_arch = "sparc64", + bsd, + target_os = "aix", + target_os = "haiku", + target_os = "solaris", + )))] + c::B3500000 => Some(3_500_000), + #[cfg(not(any( + target_arch = "sparc", + target_arch = "sparc64", + bsd, + target_os = "aix", + target_os = "haiku", + target_os = "solaris", + )))] + c::B4000000 => Some(4_000_000), + _ => None, + } + } + + /// Translate from an arbitrary `u32` arbitrary integer speed value to a + /// `c::speed_t` code. + #[cfg(not(bsd))] + pub(crate) fn encode(speed: u32) -> Option { + match speed { + 0 => Some(c::B0), + 50 => Some(c::B50), + 75 => Some(c::B75), + 110 => Some(c::B110), + 134 => Some(c::B134), + 150 => Some(c::B150), + 200 => Some(c::B200), + 300 => Some(c::B300), + 600 => Some(c::B600), + 1200 => Some(c::B1200), + 1800 => Some(c::B1800), + 2400 => Some(c::B2400), + 4800 => Some(c::B4800), + 9600 => Some(c::B9600), + 19200 => Some(c::B19200), + 38400 => Some(c::B38400), + #[cfg(not(target_os = "aix"))] + 57600 => Some(c::B57600), + #[cfg(not(target_os = "aix"))] + 115_200 => Some(c::B115200), + #[cfg(not(target_os = "aix"))] + 230_400 => Some(c::B230400), + #[cfg(not(any( + apple, + target_os = "aix", + target_os = "dragonfly", + target_os = "haiku", + target_os = "openbsd" + )))] + 460_800 => Some(c::B460800), + #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] + 500_000 => Some(c::B500000), + #[cfg(not(any(bsd, solarish, target_os = "aix", target_os = "haiku")))] + 576_000 => Some(c::B576000), + #[cfg(not(any( + apple, + target_os = "aix", + target_os = "dragonfly", + target_os = "haiku", + target_os = "openbsd" + )))] + 921_600 => Some(c::B921600), + #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] + 1_000_000 => Some(c::B1000000), + #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] + 1_152_000 => Some(c::B1152000), + #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] + 1_500_000 => Some(c::B1500000), + #[cfg(not(any(bsd, target_os = "aix", target_os = "haiku", target_os = "solaris")))] + 2_000_000 => Some(c::B2000000), + #[cfg(not(any( + target_arch = "sparc", + target_arch = "sparc64", + bsd, + target_os = "aix", + target_os = "haiku", + target_os = "solaris", + )))] + 2_500_000 => Some(c::B2500000), + #[cfg(not(any( + target_arch = "sparc", + target_arch = "sparc64", + bsd, + target_os = "aix", + target_os = "haiku", + target_os = "solaris", + )))] + 3_000_000 => Some(c::B3000000), + #[cfg(not(any( + target_arch = "sparc", + target_arch = "sparc64", + bsd, + target_os = "aix", + target_os = "haiku", + target_os = "solaris", + )))] + 3_500_000 => Some(c::B3500000), + #[cfg(not(any( + target_arch = "sparc", + target_arch = "sparc64", + bsd, + target_os = "aix", + target_os = "haiku", + target_os = "solaris", + )))] + 4_000_000 => Some(c::B4000000), + _ => None, + } + } +} + +/// An array indexed by [`SpecialCodeIndex`] indicating the current values +/// of various special control codes. +#[repr(transparent)] +#[derive(Clone, Debug)] +pub struct SpecialCodes(pub(crate) [c::cc_t; c::NCCS as usize]); + +impl core::ops::Index for SpecialCodes { + type Output = c::cc_t; + + fn index(&self, index: SpecialCodeIndex) -> &Self::Output { + &self.0[index.0] + } +} + +impl core::ops::IndexMut for SpecialCodes { + fn index_mut(&mut self, index: SpecialCodeIndex) -> &mut Self::Output { + &mut self.0[index.0] + } +} + +/// Indices for use with [`Termios::special_codes`]. +pub struct SpecialCodeIndex(usize); + +#[rustfmt::skip] +impl SpecialCodeIndex { + /// `VINTR` + pub const VINTR: Self = Self(c::VINTR as usize); + + /// `VQUIT` + pub const VQUIT: Self = Self(c::VQUIT as usize); + + /// `VERASE` + pub const VERASE: Self = Self(c::VERASE as usize); + + /// `VKILL` + pub const VKILL: Self = Self(c::VKILL as usize); + + /// `VEOF` + pub const VEOF: Self = Self(c::VEOF as usize); + + /// `VTIME` + pub const VTIME: Self = Self(c::VTIME as usize); + + /// `VMIN` + pub const VMIN: Self = Self(c::VMIN as usize); + + /// `VSWTC` + #[cfg(not(any( + apple, + solarish, + target_os = "aix", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "haiku", + target_os = "netbsd", + target_os = "openbsd", + )))] + pub const VSWTC: Self = Self(c::VSWTC as usize); + + /// `VSTART` + pub const VSTART: Self = Self(c::VSTART as usize); + + /// `VSTOP` + pub const VSTOP: Self = Self(c::VSTOP as usize); + + /// `VSUSP` + pub const VSUSP: Self = Self(c::VSUSP as usize); + + /// `VEOL` + pub const VEOL: Self = Self(c::VEOL as usize); + + /// `VREPRINT` + #[cfg(not(target_os = "haiku"))] + pub const VREPRINT: Self = Self(c::VREPRINT as usize); + + /// `VDISCARD` + #[cfg(not(any(target_os = "aix", target_os = "haiku")))] + pub const VDISCARD: Self = Self(c::VDISCARD as usize); + + /// `VWERASE` + #[cfg(not(any(target_os = "aix", target_os = "haiku")))] + pub const VWERASE: Self = Self(c::VWERASE as usize); + + /// `VLNEXT` + #[cfg(not(target_os = "haiku"))] + pub const VLNEXT: Self = Self(c::VLNEXT as usize); + + /// `VEOL2` + pub const VEOL2: Self = Self(c::VEOL2 as usize); +} + +/// `TCSA*` values for use with [`tcsetattr`]. +/// +/// [`tcsetattr`]: crate::termios::tcsetattr +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[repr(u32)] +pub enum OptionalActions { + /// `TCSANOW`—Make the change immediately. + #[doc(alias = "TCSANOW")] + Now = c::TCSANOW as u32, + + /// `TCSADRAIN`—Make the change after all output has been transmitted. + #[doc(alias = "TCSADRAIN")] + Drain = c::TCSADRAIN as u32, + + /// `TCSAFLUSH`—Discard any pending input and then make the change + /// after all output has been transmitted. + #[doc(alias = "TCSAFLUSH")] + Flush = c::TCSAFLUSH as u32, +} + +/// `TC*` values for use with [`tcflush`]. +/// +/// [`tcflush`]: crate::termios::tcflush +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[repr(u32)] +pub enum QueueSelector { + /// `TCIFLUSH`—Flush data received but not read. + #[doc(alias = "TCIFLUSH")] + IFlush = c::TCIFLUSH as u32, + + /// `TCOFLUSH`—Flush data written but not transmitted. + #[doc(alias = "TCOFLUSH")] + OFlush = c::TCOFLUSH as u32, + + /// `TCIOFLUSH`—`IFlush` and `OFlush` combined. + #[doc(alias = "TCIOFLUSH")] + IOFlush = c::TCIOFLUSH as u32, +} + +/// `TC*` values for use with [`tcflow`]. +/// +/// [`tcflow`]: crate::termios::tcflow +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +#[repr(u32)] +pub enum Action { + /// `TCOOFF`—Suspend output. + #[doc(alias = "TCOOFF")] + OOff = c::TCOOFF as u32, + + /// `TCOON`—Restart suspended output. + #[doc(alias = "TCOON")] + OOn = c::TCOON as u32, + + /// `TCIOFF`—Transmits a STOP byte. + #[doc(alias = "TCIOFF")] + IOff = c::TCIOFF as u32, + + /// `TCION`—Transmits a START byte. + #[doc(alias = "TCION")] + IOn = c::TCION as u32, +} + +/// `struct winsize` for use with [`tcgetwinsize`]. +/// +/// [`tcgetwinsize`]: crate::termios::tcgetwinsize +#[doc(alias = "winsize")] +pub type Winsize = c::winsize; + +#[test] +fn termios_layouts() { + check_renamed_type!(InputModes, tcflag_t); + check_renamed_type!(OutputModes, tcflag_t); + check_renamed_type!(ControlModes, tcflag_t); + check_renamed_type!(LocalModes, tcflag_t); + + // On platforms with a termios/termios2 split, check `termios`. + #[cfg(linux_raw)] + { + check_renamed_type!(Termios, termios2); + check_renamed_struct_renamed_field!(Termios, termios2, input_modes, c_iflag); + check_renamed_struct_renamed_field!(Termios, termios2, output_modes, c_oflag); + check_renamed_struct_renamed_field!(Termios, termios2, control_modes, c_cflag); + check_renamed_struct_renamed_field!(Termios, termios2, local_modes, c_lflag); + check_renamed_struct_renamed_field!(Termios, termios2, line_discipline, c_line); + check_renamed_struct_renamed_field!(Termios, termios2, special_codes, c_cc); + check_renamed_struct_renamed_field!(Termios, termios2, input_speed, c_ispeed); + check_renamed_struct_renamed_field!(Termios, termios2, output_speed, c_ospeed); + + // We assume that `termios` has the same layout as `termios2` minus the + // `c_ispeed` and `c_ospeed` fields. + check_renamed_struct_renamed_field!(Termios, termios, input_modes, c_iflag); + check_renamed_struct_renamed_field!(Termios, termios, output_modes, c_oflag); + check_renamed_struct_renamed_field!(Termios, termios, control_modes, c_cflag); + check_renamed_struct_renamed_field!(Termios, termios, local_modes, c_lflag); + check_renamed_struct_renamed_field!(Termios, termios, special_codes, c_cc); + + // On everything except PowerPC, `termios` matches `termios2` except for + // the addition of `c_ispeed` and `c_ospeed`. + #[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))] + assert_eq!( + memoffset::offset_of!(Termios, input_speed), + core::mem::size_of::() + ); + + // On PowerPC, `termios2` is `termios`. + #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] + assert_eq!( + core::mem::size_of::(), + core::mem::size_of::() + ); + } + + #[cfg(not(linux_raw))] + { + #[cfg(not(all( + target_env = "gnu", + any( + target_arch = "sparc", + target_arch = "sparc64", + target_arch = "mips", + target_arch = "mips64" + ) + )))] + check_renamed_type!(Termios, termios); + check_renamed_struct_renamed_field!(Termios, termios, input_modes, c_iflag); + check_renamed_struct_renamed_field!(Termios, termios, output_modes, c_oflag); + check_renamed_struct_renamed_field!(Termios, termios, control_modes, c_cflag); + check_renamed_struct_renamed_field!(Termios, termios, local_modes, c_lflag); + #[cfg(any( + linux_like, + target_env = "newlib", + target_os = "haiku", + target_os = "fuchsia", + target_os = "redox" + ))] + check_renamed_struct_renamed_field!(Termios, termios, line_discipline, c_line); + check_renamed_struct_renamed_field!(Termios, termios, special_codes, c_cc); + #[cfg(not(any( + linux_kernel, + solarish, + target_os = "emscripten", + target_os = "fuchsia" + )))] + { + check_renamed_struct_renamed_field!(Termios, termios, input_speed, c_ispeed); + check_renamed_struct_renamed_field!(Termios, termios, output_speed, c_ospeed); + } + #[cfg(any(target_env = "musl", target_os = "fuchsia"))] + { + check_renamed_struct_renamed_field!(Termios, termios, input_speed, __c_ispeed); + check_renamed_struct_renamed_field!(Termios, termios, output_speed, __c_ospeed); + } + } + + check_renamed_type!(OptionalActions, c_int); + check_renamed_type!(QueueSelector, c_int); + check_renamed_type!(Action, c_int); +} + +#[test] +#[cfg(not(any(solarish, target_os = "emscripten")))] +fn termios_legacy() { + // Check that our doc aliases above are correct. + assert_eq!(c::EXTA, c::B19200); + assert_eq!(c::EXTB, c::B38400); +} + +#[cfg(bsd)] +#[test] +fn termios_bsd() { + // On BSD platforms we can assume that the `B*` constants have their + // arbitrary integer speed value. Confirm this. + assert_eq!(c::B0, 0); + assert_eq!(c::B50, 50); + assert_eq!(c::B19200, 19200); + assert_eq!(c::B38400, 38400); +} + +#[test] +#[cfg(not(bsd))] +fn termios_speed_encoding() { + assert_eq!(speed::encode(0), Some(c::B0)); + assert_eq!(speed::encode(50), Some(c::B50)); + assert_eq!(speed::encode(19200), Some(c::B19200)); + assert_eq!(speed::encode(38400), Some(c::B38400)); + assert_eq!(speed::encode(1), None); + assert_eq!(speed::encode(!0), None); + + #[cfg(not(linux_kernel))] + { + assert_eq!(speed::decode(c::B0), Some(0)); + assert_eq!(speed::decode(c::B50), Some(50)); + assert_eq!(speed::decode(c::B19200), Some(19200)); + assert_eq!(speed::decode(c::B38400), Some(38400)); + } +} + +#[cfg(linux_kernel)] +#[test] +fn termios_ioctl_contiguity() { + // When using `termios2`, we assume that we can add the optional actions + // value to the ioctl request code. Test this assumption. + + assert_eq!(c::TCSETS2, c::TCSETS2 + 0); + assert_eq!(c::TCSETSW2, c::TCSETS2 + 1); + assert_eq!(c::TCSETSF2, c::TCSETS2 + 2); + + assert_eq!(c::TCSANOW - c::TCSANOW, 0); + assert_eq!(c::TCSADRAIN - c::TCSANOW, 1); + assert_eq!(c::TCSAFLUSH - c::TCSANOW, 2); + + // MIPS is different here. + #[cfg(any(target_arch = "mips", target_arch = "mips64"))] + { + assert_eq!(i128::from(c::TCSANOW) - i128::from(c::TCSETS), 0); + assert_eq!(i128::from(c::TCSADRAIN) - i128::from(c::TCSETS), 1); + assert_eq!(i128::from(c::TCSAFLUSH) - i128::from(c::TCSETS), 2); + } + #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] + { + assert_eq!(c::TCSANOW, 0); + assert_eq!(c::TCSADRAIN, 1); + assert_eq!(c::TCSAFLUSH, 2); + } +} + +#[cfg(linux_kernel)] +#[test] +fn termios_cibaud() { + // Test an assumption. + assert_eq!(c::CIBAUD, c::CBAUD << c::IBSHIFT); +} diff --git a/vendor/rustix/src/thread/clock.rs b/vendor/rustix/src/thread/clock.rs index 620cb4ec0..7a8c11968 100644 --- a/vendor/rustix/src/thread/clock.rs +++ b/vendor/rustix/src/thread/clock.rs @@ -1,6 +1,6 @@ use crate::{backend, io}; -pub use backend::time::types::Timespec; +pub use crate::timespec::Timespec; #[cfg(not(any( apple, @@ -11,7 +11,7 @@ pub use backend::time::types::Timespec; target_os = "redox", target_os = "wasi", )))] -pub use backend::time::types::ClockId; +pub use crate::clockid::ClockId; /// `clock_nanosleep(id, 0, request, remain)`—Sleeps for a duration on a /// given clock. diff --git a/vendor/rustix/src/thread/id.rs b/vendor/rustix/src/thread/id.rs index 3143b068b..6e193c366 100644 --- a/vendor/rustix/src/thread/id.rs +++ b/vendor/rustix/src/thread/id.rs @@ -1,4 +1,5 @@ -use crate::process::{Gid, Pid, Uid}; +use crate::pid::Pid; +use crate::ugid::{Gid, Uid}; use crate::{backend, io}; /// `gettid()`—Returns the thread ID. diff --git a/vendor/rustix/src/thread/libcap.rs b/vendor/rustix/src/thread/libcap.rs index f4798b8f4..8d2368720 100644 --- a/vendor/rustix/src/thread/libcap.rs +++ b/vendor/rustix/src/thread/libcap.rs @@ -1,7 +1,7 @@ use bitflags::bitflags; use core::mem::MaybeUninit; -use crate::process::Pid; +use crate::pid::Pid; use crate::{backend, io}; /// `__user_cap_data_struct` @@ -17,6 +17,8 @@ pub struct CapabilitySets { bitflags! { /// `CAP_*` constants. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct CapabilityFlags: u64 { /// `CAP_CHOWN` const CHOWN = 1 << linux_raw_sys::general::CAP_CHOWN; @@ -140,32 +142,25 @@ fn capget(pid: Option) -> io::Result { }; backend::thread::syscalls::capget(&mut header, &mut data)?; - // SAFETY: v3 is a 64-bit implementation, so the kernel filled in both data - // structs. + // SAFETY: v3 is a 64-bit implementation, so the kernel filled in both + // data structs. unsafe { (data[0].assume_init(), data[1].assume_init()) } }; - { - // TODO: With Rust 1.53, we can use u32::BITS in the shifts. - const BITS: u32 = 32; - let effective = u64::from(data.0.effective) | (u64::from(data.1.effective) << BITS); - let permitted = u64::from(data.0.permitted) | (u64::from(data.1.permitted) << BITS); - let inheritable = u64::from(data.0.inheritable) | (u64::from(data.1.inheritable) << BITS); + let effective = u64::from(data.0.effective) | (u64::from(data.1.effective) << u32::BITS); + let permitted = u64::from(data.0.permitted) | (u64::from(data.1.permitted) << u32::BITS); + let inheritable = u64::from(data.0.inheritable) | (u64::from(data.1.inheritable) << u32::BITS); - // SAFETY: the kernel returns a partitioned bitset that we just combined above - Ok(CapabilitySets { - effective: unsafe { CapabilityFlags::from_bits_unchecked(effective) }, - permitted: unsafe { CapabilityFlags::from_bits_unchecked(permitted) }, - inheritable: unsafe { CapabilityFlags::from_bits_unchecked(inheritable) }, - }) - } + // The kernel returns a partitioned bitset that we just combined above. + Ok(CapabilitySets { + effective: CapabilityFlags::from_bits_retain(effective), + permitted: CapabilityFlags::from_bits_retain(permitted), + inheritable: CapabilityFlags::from_bits_retain(inheritable), + }) } #[inline] fn capset(pid: Option, sets: CapabilitySets) -> io::Result<()> { - // TODO: With Rust 1.53, we can use u32::BITS in the shifts. - const BITS: u32 = 32; - let mut header = linux_raw_sys::general::__user_cap_header_struct { version: linux_raw_sys::general::_LINUX_CAPABILITY_VERSION_3, pid: Pid::as_raw(pid) as backend::c::c_int, @@ -177,9 +172,9 @@ fn capset(pid: Option, sets: CapabilitySets) -> io::Result<()> { inheritable: sets.inheritable.bits() as u32, }, linux_raw_sys::general::__user_cap_data_struct { - effective: (sets.effective.bits() >> BITS) as u32, - permitted: (sets.permitted.bits() >> BITS) as u32, - inheritable: (sets.inheritable.bits() >> BITS) as u32, + effective: (sets.effective.bits() >> u32::BITS) as u32, + permitted: (sets.permitted.bits() >> u32::BITS) as u32, + inheritable: (sets.inheritable.bits() >> u32::BITS) as u32, }, ]; diff --git a/vendor/rustix/src/thread/mod.rs b/vendor/rustix/src/thread/mod.rs index 86f231bcb..fa4897025 100644 --- a/vendor/rustix/src/thread/mod.rs +++ b/vendor/rustix/src/thread/mod.rs @@ -4,24 +4,24 @@ mod clock; #[cfg(linux_raw)] mod futex; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] mod id; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] mod libcap; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] mod prctl; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] mod setns; #[cfg(not(target_os = "redox"))] pub use clock::*; #[cfg(linux_raw)] pub use futex::{futex, FutexFlags, FutexOperation}; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use id::{gettid, set_thread_gid, set_thread_res_gid, set_thread_res_uid, set_thread_uid}; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use libcap::{capabilities, set_capabilities, CapabilityFlags, CapabilitySets}; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use prctl::*; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] pub use setns::*; diff --git a/vendor/rustix/src/thread/prctl.rs b/vendor/rustix/src/thread/prctl.rs index 2e11ff247..a9f411640 100644 --- a/vendor/rustix/src/thread/prctl.rs +++ b/vendor/rustix/src/thread/prctl.rs @@ -9,7 +9,6 @@ //! correctly. #![allow(unsafe_code)] -use core::convert::TryFrom; use core::mem::MaybeUninit; use core::num::NonZeroU64; use core::ptr; @@ -19,13 +18,14 @@ use core::sync::atomic::AtomicU8; use bitflags::bitflags; use crate::backend::c::{c_int, c_uint, c_void}; -use crate::backend::process::syscalls; +use crate::backend::prctl::syscalls; use crate::ffi::{CStr, CString}; use crate::io; -use crate::process::{ - prctl_1arg, prctl_2args, prctl_3args, prctl_get_at_arg2_optional, Pid, - PointerAuthenticationKeys, +use crate::pid::Pid; +use crate::prctl::{ + prctl_1arg, prctl_2args, prctl_3args, prctl_get_at_arg2_optional, PointerAuthenticationKeys, }; +use crate::utils::as_ptr; // // PR_GET_KEEPCAPS/PR_SET_KEEPCAPS @@ -54,7 +54,7 @@ const PR_SET_KEEPCAPS: c_int = 8; /// [`prctl(PR_SET_KEEPCAPS,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] pub fn set_keep_capabilities(enable: bool) -> io::Result<()> { - unsafe { prctl_2args(PR_SET_KEEPCAPS, enable as usize as *mut _) }.map(|_r| ()) + unsafe { prctl_2args(PR_SET_KEEPCAPS, usize::from(enable) as *mut _) }.map(|_r| ()) } // @@ -411,6 +411,8 @@ const PR_GET_SECUREBITS: c_int = 27; bitflags! { /// `SECBIT_*`. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct CapabilitiesSecureBits: u32 { /// If this bit is set, then the kernel does not grant capabilities when /// a `set-user-ID-root` program is executed, or when a process with an effective or real @@ -520,7 +522,7 @@ const PR_SET_NO_NEW_PRIVS: c_int = 38; /// [`prctl(PR_SET_NO_NEW_PRIVS,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] pub fn set_no_new_privs(no_new_privs: bool) -> io::Result<()> { - unsafe { prctl_2args(PR_SET_NO_NEW_PRIVS, no_new_privs as usize as *mut _) }.map(|_r| ()) + unsafe { prctl_2args(PR_SET_NO_NEW_PRIVS, usize::from(no_new_privs) as *mut _) }.map(|_r| ()) } // @@ -568,7 +570,7 @@ const PR_SET_THP_DISABLE: c_int = 41; /// [`prctl(PR_SET_THP_DISABLE,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html #[inline] pub fn disable_transparent_huge_pages(thp_disable: bool) -> io::Result<()> { - unsafe { prctl_2args(PR_SET_THP_DISABLE, thp_disable as usize as *mut _) }.map(|_r| ()) + unsafe { prctl_2args(PR_SET_THP_DISABLE, usize::from(thp_disable) as *mut _) }.map(|_r| ()) } // @@ -732,6 +734,8 @@ const PR_MTE_TAG_MASK: u32 = 0xffff_u32 << PR_MTE_TAG_SHIFT; bitflags! { /// Zero means addresses that are passed for the purpose of being dereferenced by the kernel must be untagged. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct TaggedAddressMode: u32 { /// Addresses that are passed for the purpose of being dereferenced by the kernel may be tagged. const ENABLED = 1_u32 << 0; @@ -854,7 +858,7 @@ pub unsafe fn enable_syscall_user_dispatch( PR_SYS_DISPATCH_ON as *mut _, always_allowed_region.as_ptr() as *mut _, always_allowed_region.len() as *mut _, - fast_switch_flag as *const AtomicU8 as *mut _, + as_ptr(fast_switch_flag) as *mut _, ) .map(|_r| ()) } diff --git a/vendor/rustix/src/thread/setns.rs b/vendor/rustix/src/thread/setns.rs index 81c9225e3..2669cc7a7 100644 --- a/vendor/rustix/src/thread/setns.rs +++ b/vendor/rustix/src/thread/setns.rs @@ -11,6 +11,8 @@ use crate::io; bitflags! { /// Thread name space type. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct ThreadNameSpaceType: u32 { /// Time name space. const TIME = CLONE_NEWTIME; @@ -55,6 +57,8 @@ pub enum LinkNameSpaceType { bitflags! { /// `CLONE_*` for use with [`unshare`]. + #[repr(transparent)] + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct UnshareFlags: u32 { /// `CLONE_FILES`. const FILES = CLONE_FILES; diff --git a/vendor/rustix/src/time/clock.rs b/vendor/rustix/src/time/clock.rs index 2aa38b213..db585d1cc 100644 --- a/vendor/rustix/src/time/clock.rs +++ b/vendor/rustix/src/time/clock.rs @@ -1,10 +1,10 @@ use crate::{backend, io}; -pub use backend::time::types::{Nsecs, Secs, Timespec}; +pub use crate::timespec::{Nsecs, Secs, Timespec}; /// `clockid_t` #[cfg(not(target_os = "wasi"))] -pub use backend::time::types::{ClockId, DynamicClockId}; +pub use crate::clockid::{ClockId, DynamicClockId}; /// `clock_getres(id)`—Returns the resolution of a clock. /// diff --git a/vendor/rustix/src/time/mod.rs b/vendor/rustix/src/time/mod.rs index 9a0dcb4d7..c633e767f 100644 --- a/vendor/rustix/src/time/mod.rs +++ b/vendor/rustix/src/time/mod.rs @@ -1,13 +1,11 @@ //! Time-related operations. mod clock; -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] -#[cfg(feature = "time")] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] mod timerfd; // TODO: Convert WASI'S clock APIs to use handles rather than ambient clock // identifiers, update `wasi-libc`, and then add support in `rustix`. pub use clock::*; -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] -#[cfg(feature = "time")] +#[cfg(any(linux_kernel, target_os = "fuchsia"))] pub use timerfd::*; diff --git a/vendor/rustix/src/timespec.rs b/vendor/rustix/src/timespec.rs new file mode 100644 index 000000000..55c4c061b --- /dev/null +++ b/vendor/rustix/src/timespec.rs @@ -0,0 +1,108 @@ +//! `Timespec` and related types, which are used by multiple public API +//! modules. + +use crate::backend::c; + +/// `struct timespec` +#[cfg(not(all( + libc, + any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), + target_env = "gnu", +)))] +pub type Timespec = c::timespec; + +/// `struct timespec` +#[cfg(all( + libc, + any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), + target_env = "gnu", +))] +#[derive(Debug, Clone, Copy)] +#[repr(C)] +pub struct Timespec { + /// Seconds. + pub tv_sec: Secs, + + /// Nanoseconds. Must be less than 1_000_000_000. + pub tv_nsec: Nsecs, +} + +/// A type for the `tv_sec` field of [`Timespec`]. +#[cfg(not(all( + any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), + target_env = "gnu", +)))] +#[allow(deprecated)] +pub type Secs = c::time_t; + +/// A type for the `tv_sec` field of [`Timespec`]. +#[cfg(all( + any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), + target_env = "gnu", +))] +pub type Secs = i64; + +/// A type for the `tv_nsec` field of [`Timespec`]. +#[cfg(all(libc, target_arch = "x86_64", target_pointer_width = "32"))] +pub type Nsecs = i64; + +/// A type for the `tv_nsec` field of [`Timespec`]. +#[cfg(all(libc, not(all(target_arch = "x86_64", target_pointer_width = "32"))))] +pub type Nsecs = c::c_long; + +/// A type for the `tv_nsec` field of [`Timespec`]. +#[cfg(linux_raw)] +pub type Nsecs = i64; + +/// On 32-bit glibc platforms, `timespec` has anonymous padding fields, which +/// Rust doesn't support yet (see `unnamed_fields`), so we define our own +/// struct with explicit padding, with bidirectional `From` impls. +#[cfg(all( + libc, + any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), + target_env = "gnu", +))] +#[repr(C)] +#[derive(Debug, Clone)] +pub(crate) struct LibcTimespec { + pub(crate) tv_sec: Secs, + + #[cfg(target_endian = "big")] + padding: core::mem::MaybeUninit, + + pub(crate) tv_nsec: Nsecs, + + #[cfg(target_endian = "little")] + padding: core::mem::MaybeUninit, +} + +#[cfg(all( + libc, + any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), + target_env = "gnu", +))] +impl From for Timespec { + #[inline] + fn from(t: LibcTimespec) -> Self { + Self { + tv_sec: t.tv_sec, + tv_nsec: t.tv_nsec, + } + } +} + +#[cfg(all( + libc, + any(target_arch = "arm", target_arch = "mips", target_arch = "x86"), + target_env = "gnu", +))] +impl From for LibcTimespec { + #[inline] + fn from(t: Timespec) -> Self { + Self { + tv_sec: t.tv_sec, + tv_nsec: t.tv_nsec, + padding: core::mem::MaybeUninit::uninit(), + } + } +} diff --git a/vendor/rustix/src/ugid.rs b/vendor/rustix/src/ugid.rs new file mode 100644 index 000000000..fc1082adb --- /dev/null +++ b/vendor/rustix/src/ugid.rs @@ -0,0 +1,101 @@ +//! User and Group ID types. + +#![allow(unsafe_code)] + +use crate::backend::c; + +/// A group identifier as a raw integer. +#[cfg(not(target_os = "wasi"))] +pub type RawGid = c::gid_t; +/// A user identifier as a raw integer. +#[cfg(not(target_os = "wasi"))] +pub type RawUid = c::uid_t; + +/// `uid_t`—A Unix user ID. +#[repr(transparent)] +#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)] +pub struct Uid(RawUid); + +/// `gid_t`—A Unix group ID. +#[repr(transparent)] +#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)] +pub struct Gid(RawGid); + +impl Uid { + /// A `Uid` corresponding to the root user (uid 0). + pub const ROOT: Self = Self(0); + + /// Converts a `RawUid` into a `Uid`. + /// + /// # Safety + /// + /// `raw` must be the value of a valid Unix user ID. + #[inline] + pub const unsafe fn from_raw(raw: RawUid) -> Self { + Self(raw) + } + + /// Converts a `Uid` into a `RawUid`. + #[inline] + pub const fn as_raw(self) -> RawUid { + self.0 + } + + /// Test whether this uid represents the root user (uid 0). + #[inline] + pub const fn is_root(self) -> bool { + self.0 == Self::ROOT.0 + } +} + +impl Gid { + /// A `Gid` corresponding to the root group (gid 0). + pub const ROOT: Self = Self(0); + + /// Converts a `RawGid` into a `Gid`. + /// + /// # Safety + /// + /// `raw` must be the value of a valid Unix group ID. + #[inline] + pub const unsafe fn from_raw(raw: RawGid) -> Self { + Self(raw) + } + + /// Converts a `Gid` into a `RawGid`. + #[inline] + pub const fn as_raw(self) -> RawGid { + self.0 + } + + /// Test whether this gid represents the root group (gid 0). + #[inline] + pub const fn is_root(self) -> bool { + self.0 == Self::ROOT.0 + } +} + +// Return the raw value of the IDs. In case of `None` it returns `u32::MAX` +// since it has the same bit pattern as `-1` indicating no change to the +// owner/group ID. +pub(crate) fn translate_fchown_args(owner: Option, group: Option) -> (u32, u32) { + let ow = match owner { + Some(o) => o.as_raw(), + None => u32::MAX, + }; + + let gr = match group { + Some(g) => g.as_raw(), + None => u32::MAX, + }; + + (ow, gr) +} + +#[test] +fn test_sizes() { + use core::mem::size_of; + + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); +} diff --git a/vendor/rustix/src/utils.rs b/vendor/rustix/src/utils.rs index d6ad43b54..df2ac315b 100644 --- a/vendor/rustix/src/utils.rs +++ b/vendor/rustix/src/utils.rs @@ -1,49 +1,48 @@ +#![allow(dead_code)] + +use core::ffi::c_void; +use core::mem::{align_of, size_of}; +use core::ptr::{null, null_mut, NonNull}; + /// Convert a `&T` into a `*const T` without using an `as`. #[inline] -#[allow(dead_code)] pub(crate) const fn as_ptr(t: &T) -> *const T { t } /// Convert a `&mut T` into a `*mut T` without using an `as`. #[inline] -#[allow(dead_code)] pub(crate) fn as_mut_ptr(t: &mut T) -> *mut T { t } /// Convert an `Option<&T>` into a possibly-null `*const T`. #[inline] -#[allow(dead_code)] pub(crate) const fn optional_as_ptr(t: Option<&T>) -> *const T { match t { Some(t) => t, - None => core::ptr::null(), + None => null(), } } /// Convert an `Option<&mut T>` into a possibly-null `*mut T`. #[inline] -#[allow(dead_code)] pub(crate) fn optional_as_mut_ptr(t: Option<&mut T>) -> *mut T { match t { Some(t) => t, - None => core::ptr::null_mut(), + None => null_mut(), } } /// Convert a `*mut c_void` to a `*mut T`, checking that it is not null, /// misaligned, or pointing to a region of memory that wraps around the address /// space. -#[allow(dead_code)] -pub(crate) fn check_raw_pointer(value: *mut core::ffi::c_void) -> Option> { - if (value as usize) - .checked_add(core::mem::size_of::()) - .is_none() - || (value as usize) % core::mem::align_of::() != 0 +pub(crate) fn check_raw_pointer(value: *mut c_void) -> Option> { + if (value as usize).checked_add(size_of::()).is_none() + || (value as usize) % align_of::() != 0 { return None; } - core::ptr::NonNull::new(value.cast()) + NonNull::new(value.cast()) } diff --git a/vendor/rustix/src/weak.rs b/vendor/rustix/src/weak.rs index fae3ce058..b75b1f12a 100644 --- a/vendor/rustix/src/weak.rs +++ b/vendor/rustix/src/weak.rs @@ -1,6 +1,10 @@ // Implementation derived from `weak` in Rust's // library/std/src/sys/unix/weak.rs at revision // fd0cb0cdc21dd9c06025277d772108f8d42cb25f. +// +// Ideally we should update to a newer version which doesn't need `dlsym`, +// however that depends on the `extern_weak` feature which is currently +// unstable. #![cfg_attr(linux_raw, allow(unsafe_code))] @@ -108,15 +112,38 @@ impl Weak { } } +// To avoid having the `linux_raw` backend depend on the libc crate, just +// declare the few things we need in a module called `libc` so that `fetch` +// uses it. +#[cfg(linux_raw)] +mod libc { + use core::ptr; + use linux_raw_sys::ctypes::{c_char, c_void}; + + #[cfg(all(target_os = "android", target_pointer_width = "32"))] + pub(super) const RTLD_DEFAULT: *mut c_void = -1isize as *mut c_void; + #[cfg(not(all(target_os = "android", target_pointer_width = "32")))] + pub(super) const RTLD_DEFAULT: *mut c_void = ptr::null_mut(); + + extern "C" { + pub(super) fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void; + } + + #[test] + fn test_abi() { + assert_eq!(self::RTLD_DEFAULT, ::libc::RTLD_DEFAULT); + } +} + unsafe fn fetch(name: &str) -> *mut c_void { let name = match CStr::from_bytes_with_nul(name.as_bytes()) { Ok(c_str) => c_str, Err(..) => return null_mut(), }; - libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) + libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr().cast()) } -#[cfg(not(any(target_os = "android", target_os = "linux")))] +#[cfg(not(linux_kernel))] macro_rules! syscall { (fn $name:ident($($arg_name:ident: $t:ty),*) via $_sys_name:ident -> $ret:ty) => ( unsafe fn $name($($arg_name: $t),*) -> $ret { @@ -132,11 +159,11 @@ macro_rules! syscall { ) } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(linux_kernel)] macro_rules! syscall { (fn $name:ident($($arg_name:ident: $t:ty),*) via $sys_name:ident -> $ret:ty) => ( unsafe fn $name($($arg_name:$t),*) -> $ret { - // This looks like a hack, but concat_idents only accepts idents + // This looks like a hack, but `concat_idents` only accepts idents // (not paths). use libc::*; @@ -157,28 +184,59 @@ macro_rules! syscall { // Pass `BorrowedFd` values as the integer value. impl AsSyscallArg for $crate::fd::BorrowedFd<'_> { - type SyscallArgType = c::c_long; + type SyscallArgType = ::libc::c_long; fn into_syscall_arg(self) -> Self::SyscallArgType { $crate::fd::AsRawFd::as_raw_fd(&self) as _ } } // Coerce integer values into `c_long`. + impl AsSyscallArg for i8 { + type SyscallArgType = ::libc::c_long; + fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ } + } + impl AsSyscallArg for u8 { + type SyscallArgType = ::libc::c_long; + fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ } + } + impl AsSyscallArg for i16 { + type SyscallArgType = ::libc::c_long; + fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ } + } + impl AsSyscallArg for u16 { + type SyscallArgType = ::libc::c_long; + fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ } + } impl AsSyscallArg for i32 { - type SyscallArgType = c::c_long; + type SyscallArgType = ::libc::c_long; fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ } } impl AsSyscallArg for u32 { - type SyscallArgType = c::c_long; + type SyscallArgType = ::libc::c_long; fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ } } impl AsSyscallArg for usize { - type SyscallArgType = c::c_long; + type SyscallArgType = ::libc::c_long; + fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ } + } + + // On 64-bit platforms, also coerce `i64` and `u64` since `c_long` + // is 64-bit and can hold those values. + #[cfg(target_pointer_width = "64")] + impl AsSyscallArg for i64 { + type SyscallArgType = ::libc::c_long; + fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ } + } + #[cfg(target_pointer_width = "64")] + impl AsSyscallArg for u64 { + type SyscallArgType = ::libc::c_long; fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ } } - // `concat_idents is unstable, so we take an extra `sys_name` + // `concat_idents` is [unstable], so we take an extra `sys_name` // parameter and have our users do the concat for us for now. + // + // [unstable]: https://github.com/rust-lang/rust/issues/29599 /* syscall( concat_idents!(SYS_, $name), -- cgit v1.2.3