From d22f3e239c30154ac6c4abfecef9db946fc5e200 Mon Sep 17 00:00:00 2001 From: Roy Ivy III Date: Sat, 1 Jan 2022 18:41:37 -0600 Subject: [PATCH] change ~ remove (now unneeded) vendored nix-v0.23.1-patched --- vendor/nix-v0.23.1-patched/.cirrus.yml | 274 -- vendor/nix-v0.23.1-patched/.gitattributes | 1 - vendor/nix-v0.23.1-patched/.gitignore | 10 - vendor/nix-v0.23.1-patched/CHANGELOG.md | 1227 ------- vendor/nix-v0.23.1-patched/CONTRIBUTING.md | 114 - vendor/nix-v0.23.1-patched/CONVENTIONS.md | 86 - vendor/nix-v0.23.1-patched/Cargo.toml | 74 - vendor/nix-v0.23.1-patched/Cross.toml | 5 - vendor/nix-v0.23.1-patched/LICENSE | 21 - vendor/nix-v0.23.1-patched/README.md | 102 - .../nix-v0.23.1-patched/RELEASE_PROCEDURE.md | 18 - vendor/nix-v0.23.1-patched/bors.toml | 49 - vendor/nix-v0.23.1-patched/release.toml | 5 - vendor/nix-v0.23.1-patched/src/dir.rs | 246 -- vendor/nix-v0.23.1-patched/src/env.rs | 66 - vendor/nix-v0.23.1-patched/src/errno.rs | 2723 --------------- vendor/nix-v0.23.1-patched/src/fcntl.rs | 696 ---- vendor/nix-v0.23.1-patched/src/features.rs | 121 - vendor/nix-v0.23.1-patched/src/ifaddrs.rs | 147 - vendor/nix-v0.23.1-patched/src/kmod.rs | 122 - vendor/nix-v0.23.1-patched/src/lib.rs | 227 -- vendor/nix-v0.23.1-patched/src/macros.rs | 311 -- vendor/nix-v0.23.1-patched/src/mount/bsd.rs | 426 --- vendor/nix-v0.23.1-patched/src/mount/linux.rs | 111 - vendor/nix-v0.23.1-patched/src/mount/mod.rs | 21 - vendor/nix-v0.23.1-patched/src/mqueue.rs | 178 - vendor/nix-v0.23.1-patched/src/net/if_.rs | 411 --- vendor/nix-v0.23.1-patched/src/net/mod.rs | 4 - vendor/nix-v0.23.1-patched/src/poll.rs | 163 - vendor/nix-v0.23.1-patched/src/pty.rs | 348 -- vendor/nix-v0.23.1-patched/src/sched.rs | 282 -- vendor/nix-v0.23.1-patched/src/sys/aio.rs | 1122 ------ vendor/nix-v0.23.1-patched/src/sys/epoll.rs | 109 - vendor/nix-v0.23.1-patched/src/sys/event.rs | 348 -- vendor/nix-v0.23.1-patched/src/sys/eventfd.rs | 17 - vendor/nix-v0.23.1-patched/src/sys/inotify.rs | 233 -- .../nix-v0.23.1-patched/src/sys/ioctl/bsd.rs | 109 - .../src/sys/ioctl/linux.rs | 141 - .../nix-v0.23.1-patched/src/sys/ioctl/mod.rs | 778 ----- vendor/nix-v0.23.1-patched/src/sys/memfd.rs | 19 - vendor/nix-v0.23.1-patched/src/sys/mman.rs | 464 --- vendor/nix-v0.23.1-patched/src/sys/mod.rs | 131 - .../src/sys/personality.rs | 70 - vendor/nix-v0.23.1-patched/src/sys/pthread.rs | 38 - .../nix-v0.23.1-patched/src/sys/ptrace/bsd.rs | 176 - .../src/sys/ptrace/linux.rs | 479 --- .../nix-v0.23.1-patched/src/sys/ptrace/mod.rs | 22 - vendor/nix-v0.23.1-patched/src/sys/quota.rs | 277 -- vendor/nix-v0.23.1-patched/src/sys/reboot.rs | 45 - .../nix-v0.23.1-patched/src/sys/resource.rs | 233 -- vendor/nix-v0.23.1-patched/src/sys/select.rs | 430 --- .../nix-v0.23.1-patched/src/sys/sendfile.rs | 231 -- vendor/nix-v0.23.1-patched/src/sys/signal.rs | 1234 ------- .../nix-v0.23.1-patched/src/sys/signalfd.rs | 169 - .../src/sys/socket/addr.rs | 1447 -------- .../nix-v0.23.1-patched/src/sys/socket/mod.rs | 1916 ----------- .../src/sys/socket/sockopt.rs | 930 ----- vendor/nix-v0.23.1-patched/src/sys/stat.rs | 315 -- vendor/nix-v0.23.1-patched/src/sys/statfs.rs | 622 ---- vendor/nix-v0.23.1-patched/src/sys/statvfs.rs | 161 - vendor/nix-v0.23.1-patched/src/sys/sysinfo.rs | 79 - vendor/nix-v0.23.1-patched/src/sys/termios.rs | 1016 ------ vendor/nix-v0.23.1-patched/src/sys/time.rs | 609 ---- vendor/nix-v0.23.1-patched/src/sys/timerfd.rs | 281 -- vendor/nix-v0.23.1-patched/src/sys/uio.rs | 223 -- vendor/nix-v0.23.1-patched/src/sys/utsname.rs | 75 - vendor/nix-v0.23.1-patched/src/sys/wait.rs | 262 -- vendor/nix-v0.23.1-patched/src/time.rs | 260 -- vendor/nix-v0.23.1-patched/src/ucontext.rs | 43 - vendor/nix-v0.23.1-patched/src/unistd.rs | 2994 ----------------- vendor/nix-v0.23.1-patched/test/common/mod.rs | 141 - vendor/nix-v0.23.1-patched/test/sys/mod.rs | 47 - .../nix-v0.23.1-patched/test/sys/test_aio.rs | 620 ---- .../test/sys/test_aio_drop.rs | 29 - .../test/sys/test_epoll.rs | 23 - .../test/sys/test_inotify.rs | 63 - .../test/sys/test_ioctl.rs | 337 -- .../test/sys/test_lio_listio_resubmit.rs | 106 - .../nix-v0.23.1-patched/test/sys/test_mman.rs | 92 - .../test/sys/test_pthread.rs | 22 - .../test/sys/test_ptrace.rs | 219 -- .../test/sys/test_select.rs | 82 - .../test/sys/test_signal.rs | 121 - .../test/sys/test_signalfd.rs | 27 - .../test/sys/test_socket.rs | 1941 ----------- .../test/sys/test_sockopt.rs | 199 -- .../test/sys/test_sysinfo.rs | 18 - .../test/sys/test_termios.rs | 130 - .../test/sys/test_timerfd.rs | 61 - .../nix-v0.23.1-patched/test/sys/test_uio.rs | 255 -- .../nix-v0.23.1-patched/test/sys/test_wait.rs | 107 - vendor/nix-v0.23.1-patched/test/test.rs | 103 - .../nix-v0.23.1-patched/test/test_clearenv.rs | 9 - vendor/nix-v0.23.1-patched/test/test_dir.rs | 56 - vendor/nix-v0.23.1-patched/test/test_fcntl.rs | 540 --- .../test/test_kmod/hello_mod/Makefile | 7 - .../test/test_kmod/hello_mod/hello.c | 26 - .../nix-v0.23.1-patched/test/test_kmod/mod.rs | 166 - vendor/nix-v0.23.1-patched/test/test_mount.rs | 236 -- vendor/nix-v0.23.1-patched/test/test_mq.rs | 157 - vendor/nix-v0.23.1-patched/test/test_net.rs | 12 - .../nix-v0.23.1-patched/test/test_nix_path.rs | 0 .../nix-v0.23.1-patched/test/test_nmount.rs | 51 - vendor/nix-v0.23.1-patched/test/test_poll.rs | 82 - vendor/nix-v0.23.1-patched/test/test_pty.rs | 301 -- .../test/test_ptymaster_drop.rs | 20 - .../nix-v0.23.1-patched/test/test_resource.rs | 23 - vendor/nix-v0.23.1-patched/test/test_sched.rs | 32 - .../nix-v0.23.1-patched/test/test_sendfile.rs | 151 - vendor/nix-v0.23.1-patched/test/test_stat.rs | 358 -- vendor/nix-v0.23.1-patched/test/test_time.rs | 58 - .../nix-v0.23.1-patched/test/test_unistd.rs | 1150 ------- 112 files changed, 34875 deletions(-) delete mode 100644 vendor/nix-v0.23.1-patched/.cirrus.yml delete mode 100644 vendor/nix-v0.23.1-patched/.gitattributes delete mode 100644 vendor/nix-v0.23.1-patched/.gitignore delete mode 100644 vendor/nix-v0.23.1-patched/CHANGELOG.md delete mode 100644 vendor/nix-v0.23.1-patched/CONTRIBUTING.md delete mode 100644 vendor/nix-v0.23.1-patched/CONVENTIONS.md delete mode 100644 vendor/nix-v0.23.1-patched/Cargo.toml delete mode 100644 vendor/nix-v0.23.1-patched/Cross.toml delete mode 100644 vendor/nix-v0.23.1-patched/LICENSE delete mode 100644 vendor/nix-v0.23.1-patched/README.md delete mode 100644 vendor/nix-v0.23.1-patched/RELEASE_PROCEDURE.md delete mode 100644 vendor/nix-v0.23.1-patched/bors.toml delete mode 100644 vendor/nix-v0.23.1-patched/release.toml delete mode 100644 vendor/nix-v0.23.1-patched/src/dir.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/env.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/errno.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/fcntl.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/features.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/ifaddrs.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/kmod.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/lib.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/macros.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/mount/bsd.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/mount/linux.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/mount/mod.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/mqueue.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/net/if_.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/net/mod.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/poll.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/pty.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sched.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/aio.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/epoll.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/event.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/eventfd.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/inotify.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/ioctl/bsd.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/ioctl/linux.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/ioctl/mod.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/memfd.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/mman.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/mod.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/personality.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/pthread.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/ptrace/bsd.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/ptrace/linux.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/ptrace/mod.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/quota.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/reboot.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/resource.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/select.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/sendfile.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/signal.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/signalfd.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/socket/addr.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/socket/mod.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/socket/sockopt.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/stat.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/statfs.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/statvfs.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/sysinfo.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/termios.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/time.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/timerfd.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/uio.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/utsname.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/sys/wait.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/time.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/ucontext.rs delete mode 100644 vendor/nix-v0.23.1-patched/src/unistd.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/common/mod.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/mod.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_aio.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_aio_drop.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_epoll.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_inotify.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_ioctl.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_lio_listio_resubmit.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_mman.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_pthread.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_ptrace.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_select.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_signal.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_signalfd.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_socket.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_sockopt.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_sysinfo.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_termios.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_timerfd.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_uio.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/sys/test_wait.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_clearenv.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_dir.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_fcntl.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_kmod/hello_mod/Makefile delete mode 100644 vendor/nix-v0.23.1-patched/test/test_kmod/hello_mod/hello.c delete mode 100644 vendor/nix-v0.23.1-patched/test/test_kmod/mod.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_mount.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_mq.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_net.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_nix_path.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_nmount.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_poll.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_pty.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_ptymaster_drop.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_resource.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_sched.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_sendfile.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_stat.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_time.rs delete mode 100644 vendor/nix-v0.23.1-patched/test/test_unistd.rs diff --git a/vendor/nix-v0.23.1-patched/.cirrus.yml b/vendor/nix-v0.23.1-patched/.cirrus.yml deleted file mode 100644 index 3848f9206..000000000 --- a/vendor/nix-v0.23.1-patched/.cirrus.yml +++ /dev/null @@ -1,274 +0,0 @@ -cargo_cache: - folder: $CARGO_HOME/registry - fingerprint_script: cat Cargo.lock || echo "" - -env: - # Build by default; don't just check - BUILD: build - CLIPPYFLAGS: -D warnings - RUSTFLAGS: -D warnings - RUSTDOCFLAGS: -D warnings - TOOL: cargo - # The MSRV - TOOLCHAIN: 1.46.0 - ZFLAGS: - -# Tests that don't require executing the build binaries -build: &BUILD - build_script: - - . $HOME/.cargo/env || true - - $TOOL +$TOOLCHAIN $BUILD $ZFLAGS --target $TARGET --all-targets - - $TOOL +$TOOLCHAIN doc $ZFLAGS --no-deps --target $TARGET - - $TOOL +$TOOLCHAIN clippy $ZFLAGS --target $TARGET -- $CLIPPYFLAGS - -# Tests that do require executing the binaries -test: &TEST - << : *BUILD - test_script: - - . $HOME/.cargo/env || true - - $TOOL +$TOOLCHAIN test --target $TARGET - -# Test FreeBSD in a full VM. Test the i686 target too, in the -# same VM. The binary will be built in 32-bit mode, but will execute on a -# 64-bit kernel and in a 64-bit environment. Our tests don't execute any of -# the system's binaries, so the environment shouldn't matter. -task: - name: FreeBSD amd64 & i686 - env: - TARGET: x86_64-unknown-freebsd - freebsd_instance: - image: freebsd-12-2-release-amd64 - setup_script: - - fetch https://sh.rustup.rs -o rustup.sh - - sh rustup.sh -y --profile=minimal --default-toolchain $TOOLCHAIN - - . $HOME/.cargo/env - - rustup target add i686-unknown-freebsd - - rustup component add --toolchain $TOOLCHAIN clippy - << : *TEST - i386_test_script: - - . $HOME/.cargo/env - - cargo build --target i686-unknown-freebsd - - cargo doc --no-deps --target i686-unknown-freebsd - - cargo test --target i686-unknown-freebsd - before_cache_script: rm -rf $CARGO_HOME/registry/index - -# Test OSX in a full VM -task: - matrix: - - name: OSX x86_64 - env: - TARGET: x86_64-apple-darwin - osx_instance: - image: catalina-xcode - setup_script: - - curl --proto '=https' --tlsv1.2 -sSf -o rustup.sh https://sh.rustup.rs - - sh rustup.sh -y --profile=minimal --default-toolchain $TOOLCHAIN - - . $HOME/.cargo/env - - rustup component add --toolchain $TOOLCHAIN clippy - << : *TEST - before_cache_script: rm -rf $CARGO_HOME/registry/index - -# Use cross for QEMU-based testing -# cross needs to execute Docker, so we must use Cirrus's Docker Builder task. -task: - env: - RUST_TEST_THREADS: 1 # QEMU works best with 1 thread - HOME: /tmp/home - PATH: $HOME/.cargo/bin:$PATH - RUSTFLAGS: --cfg qemu -D warnings - TOOL: cross - matrix: - - name: Linux arm gnueabi - env: - TARGET: arm-unknown-linux-gnueabi - - name: Linux armv7 gnueabihf - env: - TARGET: armv7-unknown-linux-gnueabihf - - name: Linux i686 - env: - TARGET: i686-unknown-linux-gnu - - name: Linux i686 musl - env: - TARGET: i686-unknown-linux-musl - - name: Linux MIPS - env: - TARGET: mips-unknown-linux-gnu - - name: Linux MIPS64 - env: - TARGET: mips64-unknown-linux-gnuabi64 - - name: Linux MIPS64 el - env: - TARGET: mips64el-unknown-linux-gnuabi64 - - name: Linux mipsel - env: - TARGET: mipsel-unknown-linux-gnu - - name: Linux powerpc64le - env: - TARGET: powerpc64le-unknown-linux-gnu - compute_engine_instance: - image_project: cirrus-images - image: family/docker-builder - platform: linux - cpu: 1 # Since QEMU will only use 1 thread - memory: 4G - setup_script: - - mkdir /tmp/home - - curl --proto '=https' --tlsv1.2 -sSf -o rustup.sh https://sh.rustup.rs - - sh rustup.sh -y --profile=minimal --default-toolchain $TOOLCHAIN - - . $HOME/.cargo/env - - cargo install cross - << : *TEST - before_cache_script: rm -rf $CARGO_HOME/registry/index - -# Tasks for Linux native builds -task: - matrix: - - name: Rust Stable - container: - image: rust:latest - env: - TARGET: x86_64-unknown-linux-gnu - TOOLCHAIN: - - name: Linux aarch64 - arm_container: - image: rust:1.46 - env: - RUSTFLAGS: --cfg graviton -D warnings - TARGET: aarch64-unknown-linux-gnu - - name: Linux x86_64 - container: - image: rust:1.46 - env: - TARGET: x86_64-unknown-linux-gnu - - name: Linux x86_64 musl - container: - image: rust:1.46 - env: - TARGET: x86_64-unknown-linux-musl - setup_script: - - rustup target add $TARGET - - rustup component add clippy - << : *TEST - before_cache_script: rm -rf $CARGO_HOME/registry/index - -# Tasks for cross-compiling, but no testing -task: - container: - image: rust:1.46 - env: - BUILD: check - matrix: - # Cross claims to support Android, but when it tries to run Nix's tests it - # reports undefined symbol references. - - name: Android aarch64 - env: - TARGET: aarch64-linux-android - - name: Android arm - env: - TARGET: arm-linux-androideabi - - name: Android armv7 - env: - TARGET: armv7-linux-androideabi - - name: Android i686 - env: - TARGET: i686-linux-android - - name: Android x86_64 - env: - TARGET: x86_64-linux-android - - name: Linux arm-musleabi - env: - TARGET: arm-unknown-linux-musleabi - - name: Fuchsia x86_64 - env: - TARGET: x86_64-fuchsia - - name: Illumos - env: - TARGET: x86_64-unknown-illumos - # illumos toolchain isn't available via rustup until 1.50 - TOOLCHAIN: 1.50.0 - container: - image: rust:1.50 - # Cross claims to support running tests on iOS, but it actually doesn't. - # https://github.com/rust-embedded/cross/issues/535 - - name: iOS aarch64 - env: - TARGET: aarch64-apple-ios - # Rustup only supports cross-building from arbitrary hosts for iOS at - # 1.49.0 and above. Below that it's possible to cross-build from an OSX - # host, but OSX VMs are more expensive than Linux VMs. - TOOLCHAIN: 1.49.0 - - name: iOS x86_64 - env: - TARGET: x86_64-apple-ios - TOOLCHAIN: 1.49.0 - # Cross testing on powerpc fails with "undefined reference to renameat2". - # Perhaps cross is using too-old a version? - - name: Linux powerpc - env: - TARGET: powerpc-unknown-linux-gnu - # Cross claims to support Linux powerpc64, but it really doesn't. - # https://github.com/rust-embedded/cross/issues/441 - - name: Linux powerpc64 - env: - TARGET: powerpc64-unknown-linux-gnu - - name: Linux s390x - env: - TARGET: s390x-unknown-linux-gnu - - name: Linux x32 - env: - TARGET: x86_64-unknown-linux-gnux32 - - name: NetBSD x86_64 - env: - TARGET: x86_64-unknown-netbsd - - name: Redox x86_64 - env: - TARGET: x86_64-unknown-redox - # Redox requires a nightly compiler. - # If stuff breaks, change nightly to the date in the toolchain_* - # directory at https://static.redox-os.org - TOOLCHAIN: nightly-2020-08-04 - setup_script: - - rustup target add $TARGET - - rustup toolchain install $TOOLCHAIN --profile minimal --target $TARGET - - rustup component add --toolchain $TOOLCHAIN clippy - << : *BUILD - before_cache_script: rm -rf $CARGO_HOME/registry/index - -# Rust Tier 3 targets can't use Rustup -task: - container: - image: rustlang/rust:nightly - env: - BUILD: check - # Must allow here rather than in lib.rs because this lint doesn't exist - # prior to Rust 1.57.0 - # https://github.com/rust-lang/rust-clippy/issues/7718 - CLIPPYFLAGS: -D warnings -A clippy::if_then_panic - TOOLCHAIN: nightly - ZFLAGS: -Zbuild-std - matrix: - - name: DragonFly BSD x86_64 - env: - TARGET: x86_64-unknown-dragonfly - - name: OpenBSD x86_64 - env: - TARGET: x86_64-unknown-openbsd - setup_script: - - rustup component add rust-src - << : *BUILD - before_cache_script: rm -rf $CARGO_HOME/registry/index - -# Test that we can build with the lowest version of all dependencies. -# "cargo test" doesn't work because some of our dev-dependencies, like -# rand, can't build with their own minimal dependencies. -task: - name: Minver - env: - TOOLCHAIN: nightly - container: - image: rustlang/rust:nightly - setup_script: - - cargo update -Zminimal-versions - script: - - cargo check - before_cache_script: rm -rf $CARGO_HOME/registry/index diff --git a/vendor/nix-v0.23.1-patched/.gitattributes b/vendor/nix-v0.23.1-patched/.gitattributes deleted file mode 100644 index 3d432e03f..000000000 --- a/vendor/nix-v0.23.1-patched/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -/CHANGELOG.md merge=union diff --git a/vendor/nix-v0.23.1-patched/.gitignore b/vendor/nix-v0.23.1-patched/.gitignore deleted file mode 100644 index 87f1a1476..000000000 --- a/vendor/nix-v0.23.1-patched/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -syntax: glob -Cargo.lock -target -*.diff -*.rej -*.orig -.*.swn -.*.swo -.*.swp -*.a diff --git a/vendor/nix-v0.23.1-patched/CHANGELOG.md b/vendor/nix-v0.23.1-patched/CHANGELOG.md deleted file mode 100644 index d2db7d2d6..000000000 --- a/vendor/nix-v0.23.1-patched/CHANGELOG.md +++ /dev/null @@ -1,1227 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -This project adheres to [Semantic Versioning](https://semver.org/). - -## [Unreleased] - ReleaseDate - -### Added -### Changed -### Fixed - -- Fixed soundness issues in `FdSet::insert`, `FdSet::remove`, and - `FdSet::contains` involving file descriptors outside of the range - `0..FD_SETSIZE`. - (#[1575](https://github.com/nix-rust/nix/pull/1575)) - -### Removed - -## [0.23.0] - 2021-09-28 -### Added - -- Added the `LocalPeerCred` sockopt. - (#[1482](https://github.com/nix-rust/nix/pull/1482)) -- Added `TimeSpec::from_duration` and `TimeSpec::from_timespec` - (#[1465](https://github.com/nix-rust/nix/pull/1465)) -- Added `IPV6_V6ONLY` sockopt. - (#[1470](https://github.com/nix-rust/nix/pull/1470)) -- Added `impl From for libc::passwd` trait implementation to convert a `User` - into a `libc::passwd`. Consumes the `User` struct to give ownership over - the member pointers. - (#[1471](https://github.com/nix-rust/nix/pull/1471)) -- Added `pthread_kill`. - (#[1472](https://github.com/nix-rust/nix/pull/1472)) -- Added `mknodat`. - (#[1473](https://github.com/nix-rust/nix/pull/1473)) -- Added `setrlimit` and `getrlimit`. - (#[1302](https://github.com/nix-rust/nix/pull/1302)) -- Added `ptrace::interrupt` method for platforms that support `PTRACE_INTERRUPT` - (#[1422](https://github.com/nix-rust/nix/pull/1422)) -- Added `IP6T_SO_ORIGINAL_DST` sockopt. - (#[1490](https://github.com/nix-rust/nix/pull/1490)) -- Added the `PTRACE_EVENT_STOP` variant to the `sys::ptrace::Event` enum - (#[1335](https://github.com/nix-rust/nix/pull/1335)) -- Exposed `SockAddr::from_raw_sockaddr` - (#[1447](https://github.com/nix-rust/nix/pull/1447)) -- Added `TcpRepair` - (#[1503](https://github.com/nix-rust/nix/pull/1503)) -- Enabled `pwritev` and `preadv` for more operating systems. - (#[1511](https://github.com/nix-rust/nix/pull/1511)) -- Added support for `TCP_MAXSEG` TCP Maximum Segment Size socket options - (#[1292](https://github.com/nix-rust/nix/pull/1292)) -- Added `Ipv4RecvErr` and `Ipv6RecvErr` sockopts and associated control messages. - (#[1514](https://github.com/nix-rust/nix/pull/1514)) -- Added `AsRawFd` implementation on `PollFd`. - (#[1516](https://github.com/nix-rust/nix/pull/1516)) -- Added `Ipv4Ttl` and `Ipv6Ttl` sockopts. - (#[1515](https://github.com/nix-rust/nix/pull/1515)) -- Added `MAP_EXCL`, `MAP_ALIGNED_SUPER`, and `MAP_CONCEAL` mmap flags, and - exposed `MAP_ANONYMOUS` for all operating systems. - (#[1522](https://github.com/nix-rust/nix/pull/1522)) - (#[1525](https://github.com/nix-rust/nix/pull/1525)) - (#[1531](https://github.com/nix-rust/nix/pull/1531)) - (#[1534](https://github.com/nix-rust/nix/pull/1534)) -- Added read/write accessors for 'events' on `PollFd`. - (#[1517](https://github.com/nix-rust/nix/pull/1517)) - -### Changed - -- `FdSet::{contains, highest, fds}` no longer require a mutable reference. - (#[1464](https://github.com/nix-rust/nix/pull/1464)) -- `User::gecos` and corresponding `libc::passwd::pw_gecos` are supported on - 64-bit Android, change conditional compilation to include the field in - 64-bit Android builds - (#[1471](https://github.com/nix-rust/nix/pull/1471)) -- `eventfd`s are supported on Android, change conditional compilation to - include `sys::eventfd::eventfd` and `sys::eventfd::EfdFlags`for Android - builds. - (#[1481](https://github.com/nix-rust/nix/pull/1481)) -- Most enums that come from C, for example `Errno`, are now marked as - `#[non_exhaustive]`. - (#[1474](https://github.com/nix-rust/nix/pull/1474)) -- Many more functions, mostly contructors, are now `const`. - (#[1476](https://github.com/nix-rust/nix/pull/1476)) - (#[1492](https://github.com/nix-rust/nix/pull/1492)) -- `sys::event::KEvent::filter` now returns a `Result` instead of being - infalliable. The only cases where it will now return an error are cases - where it previously would've had undefined behavior. - (#[1484](https://github.com/nix-rust/nix/pull/1484)) -- Minimum supported Rust version is now 1.46.0. - ([#1492](https://github.com/nix-rust/nix/pull/1492)) -- Rework `UnixAddr` to encapsulate internals better in order to fix soundness - issues. No longer allows creating a `UnixAddr` from a raw `sockaddr_un`. - ([#1496](https://github.com/nix-rust/nix/pull/1496)) -- Raised bitflags to 1.3.0 and the MSRV to 1.46.0. - ([#1492](https://github.com/nix-rust/nix/pull/1492)) - -### Fixed - -- `posix_fadvise` now returns errors in the conventional way, rather than as a - non-zero value in `Ok()`. - (#[1538](https://github.com/nix-rust/nix/pull/1538)) -- Added more errno definitions for better backwards compatibility with - Nix 0.21.0. - (#[1467](https://github.com/nix-rust/nix/pull/1467)) -- Fixed potential undefined behavior in `Signal::try_from` on some platforms. - (#[1484](https://github.com/nix-rust/nix/pull/1484)) -- Fixed buffer overflow in `unistd::getgrouplist`. - (#[1545](https://github.com/nix-rust/nix/pull/1545)) - - -### Removed - -- Removed a couple of termios constants on redox that were never actually - supported. - (#[1483](https://github.com/nix-rust/nix/pull/1483)) -- Removed `nix::sys::signal::NSIG`. It was of dubious utility, and not correct - for all platforms. - (#[1484](https://github.com/nix-rust/nix/pull/1484)) -- Removed support for 32-bit Apple targets, since they've been dropped by both - Rustc and Xcode. - (#[1492](https://github.com/nix-rust/nix/pull/1492)) -- Deprecated `SockAddr/InetAddr::to_str` in favor of `ToString::to_string` - (#[1495](https://github.com/nix-rust/nix/pull/1495)) -- Removed `SigevNotify` on OpenBSD and Redox. - (#[1511](https://github.com/nix-rust/nix/pull/1511)) - -## [0.22.0] - 9 July 2021 -### Added -- Added `if_nameindex` (#[1445](https://github.com/nix-rust/nix/pull/1445)) -- Added `nmount` for FreeBSD. - (#[1453](https://github.com/nix-rust/nix/pull/1453)) -- Added `IpFreebind` socket option (sockopt) on Linux, Fuchsia and Android. - (#[1456](https://github.com/nix-rust/nix/pull/1456)) -- Added `TcpUserTimeout` socket option (sockopt) on Linux and Fuchsia. - (#[1457](https://github.com/nix-rust/nix/pull/1457)) -- Added `renameat2` for Linux - (#[1458](https://github.com/nix-rust/nix/pull/1458)) -- Added `RxqOvfl` support on Linux, Fuchsia and Android. - (#[1455](https://github.com/nix-rust/nix/pull/1455)) - -### Changed -- `ptsname_r` now returns a lossily-converted string in the event of bad UTF, - just like `ptsname`. - ([#1446](https://github.com/nix-rust/nix/pull/1446)) -- Nix's error type is now a simple wrapper around the platform's Errno. This - means it is now `Into`. It's also `Clone`, `Copy`, `Eq`, and - has a small fixed size. It also requires less typing. For example, the old - enum variant `nix::Error::Sys(nix::errno::Errno::EINVAL)` is now simply - `nix::Error::EINVAL`. - ([#1446](https://github.com/nix-rust/nix/pull/1446)) - -### Fixed -### Removed - -## [0.21.0] - 31 May 2021 -### Added -- Added `getresuid` and `getresgid` - (#[1430](https://github.com/nix-rust/nix/pull/1430)) -- Added TIMESTAMPNS support for linux - (#[1402](https://github.com/nix-rust/nix/pull/1402)) -- Added `sendfile64` (#[1439](https://github.com/nix-rust/nix/pull/1439)) -- Added `MS_LAZYTIME` to `MsFlags` - (#[1437](https://github.com/nix-rust/nix/pull/1437)) - -### Changed -- Made `forkpty` unsafe, like `fork` - (#[1390](https://github.com/nix-rust/nix/pull/1390)) -- Made `Uid`, `Gid` and `Pid` methods `from_raw` and `as_raw` a `const fn` - (#[1429](https://github.com/nix-rust/nix/pull/1429)) -- Made `Uid::is_root` a `const fn` - (#[1429](https://github.com/nix-rust/nix/pull/1429)) -- `AioCb` is now always pinned. Once a `libc::aiocb` gets sent to the kernel, - its address in memory must not change. Nix now enforces that by using - `std::pin`. Most users won't need to change anything, except when using - `aio_suspend`. See that method's documentation for the new usage. - (#[1440](https://github.com/nix-rust/nix/pull/1440)) -- `LioCb` is now constructed using a distinct `LioCbBuilder` struct. This - avoids a soundness issue with the old `LioCb`. Usage is similar but - construction now uses the builder pattern. See the documentation for - details. - (#[1440](https://github.com/nix-rust/nix/pull/1440)) -- Minimum supported Rust version is now 1.41.0. - ([#1440](https://github.com/nix-rust/nix/pull/1440)) -- Errno aliases are now associated consts on `Errno`, instead of consts in the - `errno` module. - (#[1452](https://github.com/nix-rust/nix/pull/1452)) - -### Fixed -- Allow `sockaddr_ll` size, as reported by the Linux kernel, to be smaller then it's definition - (#[1395](https://github.com/nix-rust/nix/pull/1395)) -- Fix spurious errors using `sendmmsg` with multiple cmsgs - (#[1414](https://github.com/nix-rust/nix/pull/1414)) -- Added `Errno::EOPNOTSUPP` to FreeBSD, where it was missing. - (#[1452](https://github.com/nix-rust/nix/pull/1452)) - -### Removed - -- Removed `sys::socket::accept4` from Android arm because libc removed it in - version 0.2.87. - ([#1399](https://github.com/nix-rust/nix/pull/1399)) -- `AioCb::from_boxed_slice` and `AioCb::from_boxed_mut_slice` have been - removed. They were useful with earlier versions of Rust, but should no - longer be needed now that async/await are available. `AioCb`s now work - exclusively with borrowed buffers, not owned ones. - (#[1440](https://github.com/nix-rust/nix/pull/1440)) -- Removed some Errno values from platforms where they aren't actually defined. - (#[1452](https://github.com/nix-rust/nix/pull/1452)) - -## [0.20.0] - 20 February 2021 -### Added - -- Added a `passwd` field to `Group` (#[1338](https://github.com/nix-rust/nix/pull/1338)) -- Added `mremap` (#[1306](https://github.com/nix-rust/nix/pull/1306)) -- Added `personality` (#[1331](https://github.com/nix-rust/nix/pull/1331)) -- Added limited Fuchsia support (#[1285](https://github.com/nix-rust/nix/pull/1285)) -- Added `getpeereid` (#[1342](https://github.com/nix-rust/nix/pull/1342)) -- Implemented `IntoIterator` for `Dir` - (#[1333](https://github.com/nix-rust/nix/pull/1333)). - -### Changed - -- Minimum supported Rust version is now 1.40.0. - ([#1356](https://github.com/nix-rust/nix/pull/1356)) -- i686-apple-darwin has been demoted to Tier 2 support, because it's deprecated - by Xcode. - (#[1350](https://github.com/nix-rust/nix/pull/1350)) -- Fixed calling `recvfrom` on an `AddrFamily::Packet` socket - (#[1344](https://github.com/nix-rust/nix/pull/1344)) - -### Fixed -- `TimerFd` now closes the underlying fd on drop. - ([#1381](https://github.com/nix-rust/nix/pull/1381)) -- Define `*_MAGIC` filesystem constants on Linux s390x - (#[1372](https://github.com/nix-rust/nix/pull/1372)) -- mqueue, sysinfo, timespec, statfs, test_ptrace_syscall() on x32 - (#[1366](https://github.com/nix-rust/nix/pull/1366)) - -### Removed - -- `Dir`, `SignalFd`, and `PtyMaster` are no longer `Clone`. - (#[1382](https://github.com/nix-rust/nix/pull/1382)) -- Removed `SockLevel`, which hasn't been used for a few years - (#[1362](https://github.com/nix-rust/nix/pull/1362)) -- Removed both `Copy` and `Clone` from `TimerFd`. - ([#1381](https://github.com/nix-rust/nix/pull/1381)) - -## [0.19.1] - 28 November 2020 -### Fixed -- Fixed bugs in `recvmmsg`. - (#[1341](https://github.com/nix-rust/nix/pull/1341)) - -## [0.19.0] - 6 October 2020 -### Added -- Added Netlink protocol families to the `SockProtocol` enum - (#[1289](https://github.com/nix-rust/nix/pull/1289)) -- Added `clock_gettime`, `clock_settime`, `clock_getres`, - `clock_getcpuclockid` functions and `ClockId` struct. - (#[1281](https://github.com/nix-rust/nix/pull/1281)) -- Added wrapper functions for `PTRACE_SYSEMU` and `PTRACE_SYSEMU_SINGLESTEP`. - (#[1300](https://github.com/nix-rust/nix/pull/1300)) -- Add support for Vsock on Android rather than just Linux. - (#[1301](https://github.com/nix-rust/nix/pull/1301)) -- Added `TCP_KEEPCNT` and `TCP_KEEPINTVL` TCP keepalive options. - (#[1283](https://github.com/nix-rust/nix/pull/1283)) -### Changed -- Expose `SeekData` and `SeekHole` on all Linux targets - (#[1284](https://github.com/nix-rust/nix/pull/1284)) -- Changed unistd::{execv,execve,execvp,execvpe,fexecve,execveat} to take both `&[&CStr]` and `&[CString]` as its list argument(s). - (#[1278](https://github.com/nix-rust/nix/pull/1278)) -- Made `unistd::fork` an unsafe funtion, bringing it in line with [libstd's decision](https://github.com/rust-lang/rust/pull/58059). - (#[1293](https://github.com/nix-rust/nix/pull/1293)) -### Fixed -### Removed - -## [0.18.0] - 26 July 2020 -### Added -- Added `fchown(2)` wrapper. - (#[1257](https://github.com/nix-rust/nix/pull/1257)) -- Added support on linux systems for `MAP_HUGE_`_`SIZE`_ family of flags. - (#[1211](https://github.com/nix-rust/nix/pull/1211)) -- Added support for `F_OFD_*` `fcntl` commands on Linux and Android. - (#[1195](https://github.com/nix-rust/nix/pull/1195)) -- Added `env::clearenv()`: calls `libc::clearenv` on platforms - where it's available, and clears the environment of all variables - via `std::env::vars` and `std::env::remove_var` on others. - (#[1185](https://github.com/nix-rust/nix/pull/1185)) -- `FsType` inner value made public. - (#[1187](https://github.com/nix-rust/nix/pull/1187)) -- Added `unistd::setfsuid` and `unistd::setfsgid` to set the user or group - identity for filesystem checks per-thread. - (#[1163](https://github.com/nix-rust/nix/pull/1163)) -- Derived `Ord`, `PartialOrd` for `unistd::Pid` (#[1189](https://github.com/nix-rust/nix/pull/1189)) -- Added `select::FdSet::fds` method to iterate over file descriptors in a set. - ([#1207](https://github.com/nix-rust/nix/pull/1207)) -- Added support for UDP generic segmentation offload (GSO) and generic - receive offload (GRO) ([#1209](https://github.com/nix-rust/nix/pull/1209)) -- Added support for `sendmmsg` and `recvmmsg` calls - (#[1208](https://github.com/nix-rust/nix/pull/1208)) -- Added support for `SCM_CREDS` messages (`UnixCredentials`) on FreeBSD/DragonFly - (#[1216](https://github.com/nix-rust/nix/pull/1216)) -- Added `BindToDevice` socket option (sockopt) on Linux - (#[1233](https://github.com/nix-rust/nix/pull/1233)) -- Added `EventFilter` bitflags for `EV_DISPATCH` and `EV_RECEIPT` on OpenBSD. - (#[1252](https://github.com/nix-rust/nix/pull/1252)) -- Added support for `Ipv4PacketInfo` and `Ipv6PacketInfo` to `ControlMessage`. - (#[1222](https://github.com/nix-rust/nix/pull/1222)) -- `CpuSet` and `UnixCredentials` now implement `Default`. - (#[1244](https://github.com/nix-rust/nix/pull/1244)) -- Added `unistd::ttyname` - (#[1259](https://github.com/nix-rust/nix/pull/1259)) -- Added support for `Ipv4PacketInfo` and `Ipv6PacketInfo` to `ControlMessage` for iOS and Android. - (#[1265](https://github.com/nix-rust/nix/pull/1265)) -- Added support for `TimerFd`. - (#[1261](https://github.com/nix-rust/nix/pull/1261)) - -### Changed -- Changed `fallocate` return type from `c_int` to `()` (#[1201](https://github.com/nix-rust/nix/pull/1201)) -- Enabled `sys::ptrace::setregs` and `sys::ptrace::getregs` on x86_64-unknown-linux-musl target - (#[1198](https://github.com/nix-rust/nix/pull/1198)) -- On Linux, `ptrace::write` is now an `unsafe` function. Caveat programmer. - (#[1245](https://github.com/nix-rust/nix/pull/1245)) -- `execv`, `execve`, `execvp` and `execveat` in `::nix::unistd` and `reboot` in - `::nix::sys::reboot` now return `Result` instead of `Result` (#[1239](https://github.com/nix-rust/nix/pull/1239)) -- `sys::socket::sockaddr_storage_to_addr` is no longer `unsafe`. So is - `offset_of!`. -- `sys::socket::sockaddr_storage_to_addr`, `offset_of!`, and `Errno::clear` are - no longer `unsafe`. -- `SockAddr::as_ffi_pair`,`sys::socket::sockaddr_storage_to_addr`, `offset_of!`, - and `Errno::clear` are no longer `unsafe`. - (#[1244](https://github.com/nix-rust/nix/pull/1244)) -- Several `Inotify` methods now take `self` by value instead of by reference - (#[1244](https://github.com/nix-rust/nix/pull/1244)) -- `nix::poll::ppoll`: `timeout` parameter is now optional, None is equivalent for infinite timeout. - -### Fixed - -- Fixed `getsockopt`. The old code produced UB which triggers a panic with - Rust 1.44.0. - (#[1214](https://github.com/nix-rust/nix/pull/1214)) - -- Fixed a bug in nix::unistd that would result in an infinite loop - when a group or user lookup required a buffer larger than - 16KB. (#[1198](https://github.com/nix-rust/nix/pull/1198)) -- Fixed unaligned casting of `cmsg_data` to `af_alg_iv` (#[1206](https://github.com/nix-rust/nix/pull/1206)) -- Fixed `readlink`/`readlinkat` when reading symlinks longer than `PATH_MAX` (#[1231](https://github.com/nix-rust/nix/pull/1231)) -- `PollFd`, `EpollEvent`, `IpMembershipRequest`, `Ipv6MembershipRequest`, - `TimeVal`, and `IoVec` are now `repr(transparent)`. This is required for - correctness's sake across all architectures and compilers, though now bugs - have been reported so far. - (#[1243](https://github.com/nix-rust/nix/pull/1243)) -- Fixed unaligned pointer read in `Inotify::read_events`. - (#[1244](https://github.com/nix-rust/nix/pull/1244)) - -### Removed - -- Removed `sys::socket::addr::from_libc_sockaddr` from the public API. - (#[1215](https://github.com/nix-rust/nix/pull/1215)) -- Removed `sys::termios::{get_libc_termios, get_libc_termios_mut, update_wrapper` - from the public API. These were previously hidden in the docs but still usable - by downstream. - (#[1235](https://github.com/nix-rust/nix/pull/1235)) - -- Nix no longer implements `NixPath` for `Option

where P: NixPath`. Most - Nix functions that accept `NixPath` arguments can't do anything useful with - `None`. The exceptions (`mount` and `quotactl_sync`) already take explicitly - optional arguments. - (#[1242](https://github.com/nix-rust/nix/pull/1242)) - -- Removed `unistd::daemon` and `unistd::pipe2` on OSX and ios - (#[1255](https://github.com/nix-rust/nix/pull/1255)) - -- Removed `sys::event::FilterFlag::NOTE_EXIT_REPARENTED` and - `sys::event::FilterFlag::NOTE_REAP` on OSX and ios. - (#[1255](https://github.com/nix-rust/nix/pull/1255)) - -- Removed `sys::ptrace::ptrace` on Android and Linux. - (#[1255](https://github.com/nix-rust/nix/pull/1255)) - -- Dropped support for powerpc64-unknown-linux-gnu - (#[1266](https://github.com/nix-rust/nix/pull/1268)) - -## [0.17.0] - 3 February 2020 -### Added -- Add `CLK_TCK` to `SysconfVar` - (#[1177](https://github.com/nix-rust/nix/pull/1177)) -### Changed -### Fixed -### Removed -- Removed deprecated Error::description from error types - (#[1175](https://github.com/nix-rust/nix/pull/1175)) - -## [0.16.1] - 23 December 2019 -### Added -### Changed -### Fixed - -- Fixed the build for OpenBSD - (#[1168](https://github.com/nix-rust/nix/pull/1168)) - -### Removed - -## [0.16.0] - 1 December 2019 -### Added -- Added `ptrace::seize()`: similar to `attach()` on Linux - but with better-defined semantics. - (#[1154](https://github.com/nix-rust/nix/pull/1154)) - -- Added `Signal::as_str()`: returns signal name as `&'static str` - (#[1138](https://github.com/nix-rust/nix/pull/1138)) - -- Added `posix_fallocate`. - ([#1105](https://github.com/nix-rust/nix/pull/1105)) - -- Implemented `Default` for `FdSet` - ([#1107](https://github.com/nix-rust/nix/pull/1107)) - -- Added `NixPath::is_empty`. - ([#1107](https://github.com/nix-rust/nix/pull/1107)) - -- Added `mkfifoat` - ([#1133](https://github.com/nix-rust/nix/pull/1133)) - -- Added `User::from_uid`, `User::from_name`, `User::from_gid` and - `Group::from_name`, - ([#1139](https://github.com/nix-rust/nix/pull/1139)) - -- Added `linkat` - ([#1101](https://github.com/nix-rust/nix/pull/1101)) - -- Added `sched_getaffinity`. - ([#1148](https://github.com/nix-rust/nix/pull/1148)) - -- Added optional `Signal` argument to `ptrace::{detach, syscall}` for signal - injection. ([#1083](https://github.com/nix-rust/nix/pull/1083)) - -### Changed -- `sys::termios::BaudRate` now implements `TryFrom` instead of - `From`. The old `From` implementation would panic on failure. - ([#1159](https://github.com/nix-rust/nix/pull/1159)) - -- `sys::socket::ControlMessage::ScmCredentials` and - `sys::socket::ControlMessageOwned::ScmCredentials` now wrap `UnixCredentials` - rather than `libc::ucred`. - ([#1160](https://github.com/nix-rust/nix/pull/1160)) - -- `sys::socket::recvmsg` now takes a plain `Vec` instead of a `CmsgBuffer` - implementor. If you were already using `cmsg_space!`, then you needn't worry. - ([#1156](https://github.com/nix-rust/nix/pull/1156)) - -- `sys::socket::recvfrom` now returns - `Result<(usize, Option)>` instead of `Result<(usize, SockAddr)>`. - ([#1145](https://github.com/nix-rust/nix/pull/1145)) - -- `Signal::from_c_int` has been replaced by `Signal::try_from` - ([#1113](https://github.com/nix-rust/nix/pull/1113)) - -- Changed `readlink` and `readlinkat` to return `OsString` - ([#1109](https://github.com/nix-rust/nix/pull/1109)) - - ```rust - # use nix::fcntl::{readlink, readlinkat}; - // the buffer argument of `readlink` and `readlinkat` has been removed, - // and the return value is now an owned type (`OsString`). - // Existing code can be updated by removing the buffer argument - // and removing any clone or similar operation on the output - - // old code `readlink(&path, &mut buf)` can be replaced with the following - let _: OsString = readlink(&path); - - // old code `readlinkat(dirfd, &path, &mut buf)` can be replaced with the following - let _: OsString = readlinkat(dirfd, &path); - ``` - -- Minimum supported Rust version is now 1.36.0. - ([#1108](https://github.com/nix-rust/nix/pull/1108)) - -- `Ipv4Addr::octets`, `Ipv4Addr::to_std`, `Error::as_errno`, - `ForkResult::is_child`, `ForkResult::is_parent`, `Gid::as_raw`, - `Uid::is_root`, `Uid::as_raw`, `Pid::as_raw`, and `PollFd::revents` now take - `self` by value. - ([#1107](https://github.com/nix-rust/nix/pull/1107)) - -- Type `&CString` for parameters of `exec(v|ve|vp|vpe|veat)` are changed to `&CStr`. - ([#1121](https://github.com/nix-rust/nix/pull/1121)) - -### Fixed -- Fix length of abstract socket addresses - ([#1120](https://github.com/nix-rust/nix/pull/1120)) - -- Fix initialization of msghdr in recvmsg/sendmsg when built with musl - ([#1136](https://github.com/nix-rust/nix/pull/1136)) - -### Removed -- Remove the deprecated `CmsgSpace`. - ([#1156](https://github.com/nix-rust/nix/pull/1156)) - -## [0.15.0] - 10 August 2019 -### Added -- Added `MSG_WAITALL` to `MsgFlags` in `sys::socket`. - ([#1079](https://github.com/nix-rust/nix/pull/1079)) -- Implemented `Clone`, `Copy`, `Debug`, `Eq`, `Hash`, and `PartialEq` for most - types that support them. ([#1035](https://github.com/nix-rust/nix/pull/1035)) -- Added `copy_file_range` wrapper - ([#1069](https://github.com/nix-rust/nix/pull/1069)) -- Add `mkdirat`. - ([#1084](https://github.com/nix-rust/nix/pull/1084)) -- Add `posix_fadvise`. - ([#1089](https://github.com/nix-rust/nix/pull/1089)) -- Added `AF_VSOCK` to `AddressFamily`. - ([#1091](https://github.com/nix-rust/nix/pull/1091)) -- Add `unlinkat` - ([#1058](https://github.com/nix-rust/nix/pull/1058)) -- Add `renameat`. - ([#1097](https://github.com/nix-rust/nix/pull/1097)) - -### Changed -- Support for `ifaddrs` now present when building for Android. - ([#1077](https://github.com/nix-rust/nix/pull/1077)) -- Minimum supported Rust version is now 1.31.0 - ([#1035](https://github.com/nix-rust/nix/pull/1035)) - ([#1095](https://github.com/nix-rust/nix/pull/1095)) -- Now functions `statfs()` and `fstatfs()` return result with `Statfs` wrapper - ([#928](https://github.com/nix-rust/nix/pull/928)) - -### Fixed -- Enabled `sched_yield` for all nix hosts. - ([#1090](https://github.com/nix-rust/nix/pull/1090)) - -### Removed - -## [0.14.1] - 2019-06-06 -### Added -- Macros exported by `nix` may now be imported via `use` on the Rust 2018 - edition without importing helper macros on Linux targets. - ([#1066](https://github.com/nix-rust/nix/pull/1066)) - - For example, in Rust 2018, the `ioctl_read_bad!` macro can now be imported - without importing the `convert_ioctl_res!` macro. - - ```rust - use nix::ioctl_read_bad; - - ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios); - ``` - -### Changed -- Changed some public types from reexports of libc types like `uint32_t` to the - native equivalents like `u32.` - ([#1072](https://github.com/nix-rust/nix/pull/1072/commits)) - -### Fixed -- Fix the build on Android and Linux/mips with recent versions of libc. - ([#1072](https://github.com/nix-rust/nix/pull/1072/commits)) - -### Removed - -## [0.14.0] - 2019-05-21 -### Added -- Add IP_RECVIF & IP_RECVDSTADDR. Enable IP_PKTINFO and IP6_PKTINFO on netbsd/openbsd. - ([#1002](https://github.com/nix-rust/nix/pull/1002)) -- Added `inotify_init1`, `inotify_add_watch` and `inotify_rm_watch` wrappers for - Android and Linux. ([#1016](https://github.com/nix-rust/nix/pull/1016)) -- Add `ALG_SET_IV`, `ALG_SET_OP` and `ALG_SET_AEAD_ASSOCLEN` control messages and `AF_ALG` - socket types on Linux and Android ([#1031](https://github.com/nix-rust/nix/pull/1031)) -- Add killpg - ([#1034](https://github.com/nix-rust/nix/pull/1034)) -- Added ENOTSUP errno support for Linux and Android. - ([#969](https://github.com/nix-rust/nix/pull/969)) -- Add several errno constants from OpenBSD 6.2 - ([#1036](https://github.com/nix-rust/nix/pull/1036)) -- Added `from_std` and `to_std` methods for `sys::socket::IpAddr` - ([#1043](https://github.com/nix-rust/nix/pull/1043)) -- Added `nix::unistd:seteuid` and `nix::unistd::setegid` for those platforms that do - not support `setresuid` nor `setresgid` respectively. - ([#1044](https://github.com/nix-rust/nix/pull/1044)) -- Added a `access` wrapper - ([#1045](https://github.com/nix-rust/nix/pull/1045)) -- Add `forkpty` - ([#1042](https://github.com/nix-rust/nix/pull/1042)) -- Add `sched_yield` - ([#1050](https://github.com/nix-rust/nix/pull/1050)) - -### Changed -- `PollFd` event flags renamed to `PollFlags` ([#1024](https://github.com/nix-rust/nix/pull/1024/)) -- `recvmsg` now returns an Iterator over `ControlMessageOwned` objects rather - than `ControlMessage` objects. This is sadly not backwards-compatible. Fix - code like this: - ```rust - if let ControlMessage::ScmRights(&fds) = cmsg { - ``` - - By replacing it with code like this: - ```rust - if let ControlMessageOwned::ScmRights(fds) = cmsg { - ``` - ([#1020](https://github.com/nix-rust/nix/pull/1020)) -- Replaced `CmsgSpace` with the `cmsg_space` macro. - ([#1020](https://github.com/nix-rust/nix/pull/1020)) - -### Fixed -- Fixed multiple bugs when using `sendmsg` and `recvmsg` with ancillary control messages - ([#1020](https://github.com/nix-rust/nix/pull/1020)) -- Macros exported by `nix` may now be imported via `use` on the Rust 2018 - edition without importing helper macros for BSD targets. - ([#1041](https://github.com/nix-rust/nix/pull/1041)) - - For example, in Rust 2018, the `ioctl_read_bad!` macro can now be imported - without importing the `convert_ioctl_res!` macro. - - ```rust - use nix::ioctl_read_bad; - - ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios); - ``` - -### Removed -- `Daemon`, `NOTE_REAP`, and `NOTE_EXIT_REPARENTED` are now deprecated on OSX - and iOS. - ([#1033](https://github.com/nix-rust/nix/pull/1033)) -- `PTRACE_GETREGS`, `PTRACE_SETREGS`, `PTRACE_GETFPREGS`, and - `PTRACE_SETFPREGS` have been removed from some platforms where they never - should've been defined in the first place. - ([#1055](https://github.com/nix-rust/nix/pull/1055)) - -## [0.13.0] - 2019-01-15 -### Added -- Added PKTINFO(V4) & V6PKTINFO cmsg support - Android/FreeBSD/iOS/Linux/MacOS. - ([#990](https://github.com/nix-rust/nix/pull/990)) -- Added support of CString type in `setsockopt`. - ([#972](https://github.com/nix-rust/nix/pull/972)) -- Added option `TCP_CONGESTION` in `setsockopt`. - ([#972](https://github.com/nix-rust/nix/pull/972)) -- Added `symlinkat` wrapper. - ([#997](https://github.com/nix-rust/nix/pull/997)) -- Added `ptrace::{getregs, setregs}`. - ([#1010](https://github.com/nix-rust/nix/pull/1010)) -- Added `nix::sys::signal::signal`. - ([#817](https://github.com/nix-rust/nix/pull/817)) -- Added an `mprotect` wrapper. - ([#991](https://github.com/nix-rust/nix/pull/991)) - -### Changed -### Fixed -- `lutimes` never worked on OpenBSD as it is not implemented on OpenBSD. It has - been removed. ([#1000](https://github.com/nix-rust/nix/pull/1000)) -- `fexecve` never worked on NetBSD or on OpenBSD as it is not implemented on - either OS. It has been removed. ([#1000](https://github.com/nix-rust/nix/pull/1000)) - -### Removed - -## [0.12.0] 2018-11-28 - -### Added -- Added `FromStr` and `Display` impls for `nix::sys::Signal` - ([#884](https://github.com/nix-rust/nix/pull/884)) -- Added a `sync` wrapper. - ([#961](https://github.com/nix-rust/nix/pull/961)) -- Added a `sysinfo` wrapper. - ([#922](https://github.com/nix-rust/nix/pull/922)) -- Support the `SO_PEERCRED` socket option and the `UnixCredentials` type on all Linux and Android targets. - ([#921](https://github.com/nix-rust/nix/pull/921)) -- Added support for `SCM_CREDENTIALS`, allowing to send process credentials over Unix sockets. - ([#923](https://github.com/nix-rust/nix/pull/923)) -- Added a `dir` module for reading directories (wraps `fdopendir`, `readdir`, and `rewinddir`). - ([#916](https://github.com/nix-rust/nix/pull/916)) -- Added `kmod` module that allows loading and unloading kernel modules on Linux. - ([#930](https://github.com/nix-rust/nix/pull/930)) -- Added `futimens` and `utimesat` wrappers ([#944](https://github.com/nix-rust/nix/pull/944)), - an `lutimes` wrapper ([#967](https://github.com/nix-rust/nix/pull/967)), - and a `utimes` wrapper ([#946](https://github.com/nix-rust/nix/pull/946)). -- Added `AF_UNSPEC` wrapper to `AddressFamily` ([#948](https://github.com/nix-rust/nix/pull/948)) -- Added the `mode_t` public alias within `sys::stat`. - ([#954](https://github.com/nix-rust/nix/pull/954)) -- Added a `truncate` wrapper. - ([#956](https://github.com/nix-rust/nix/pull/956)) -- Added a `fchownat` wrapper. - ([#955](https://github.com/nix-rust/nix/pull/955)) -- Added support for `ptrace` on BSD operating systems ([#949](https://github.com/nix-rust/nix/pull/949)) -- Added `ptrace` functions for reads and writes to tracee memory and ptrace kill - ([#949](https://github.com/nix-rust/nix/pull/949)) ([#958](https://github.com/nix-rust/nix/pull/958)) -- Added a `acct` wrapper module for enabling and disabling process accounting - ([#952](https://github.com/nix-rust/nix/pull/952)) -- Added the `time_t` and `suseconds_t` public aliases within `sys::time`. - ([#968](https://github.com/nix-rust/nix/pull/968)) -- Added `unistd::execvpe` for Haiku, Linux and OpenBSD - ([#975](https://github.com/nix-rust/nix/pull/975)) -- Added `Error::as_errno`. - ([#977](https://github.com/nix-rust/nix/pull/977)) - -### Changed -- Increased required Rust version to 1.24.1 - ([#900](https://github.com/nix-rust/nix/pull/900)) - ([#966](https://github.com/nix-rust/nix/pull/966)) - -### Fixed -- Made `preadv` take immutable slice of IoVec. - ([#914](https://github.com/nix-rust/nix/pull/914)) -- Fixed passing multiple file descriptors over Unix Sockets. - ([#918](https://github.com/nix-rust/nix/pull/918)) - -### Removed - -## [0.11.0] 2018-06-01 - -### Added -- Added `sendfile` on FreeBSD and Darwin. - ([#901](https://github.com/nix-rust/nix/pull/901)) -- Added `pselect` - ([#894](https://github.com/nix-rust/nix/pull/894)) -- Exposed `preadv` and `pwritev` on the BSDs. - ([#883](https://github.com/nix-rust/nix/pull/883)) -- Added `mlockall` and `munlockall` - ([#876](https://github.com/nix-rust/nix/pull/876)) -- Added `SO_MARK` on Linux. - ([#873](https://github.com/nix-rust/nix/pull/873)) -- Added safe support for nearly any buffer type in the `sys::aio` module. - ([#872](https://github.com/nix-rust/nix/pull/872)) -- Added `sys::aio::LioCb` as a wrapper for `libc::lio_listio`. - ([#872](https://github.com/nix-rust/nix/pull/872)) -- Added `unistd::getsid` - ([#850](https://github.com/nix-rust/nix/pull/850)) -- Added `alarm`. ([#830](https://github.com/nix-rust/nix/pull/830)) -- Added interface flags `IFF_NO_PI, IFF_TUN, IFF_TAP` on linux-like systems. - ([#853](https://github.com/nix-rust/nix/pull/853)) -- Added `statvfs` module to all MacOS and Linux architectures. - ([#832](https://github.com/nix-rust/nix/pull/832)) -- Added `EVFILT_EMPTY`, `EVFILT_PROCDESC`, and `EVFILT_SENDFILE` on FreeBSD. - ([#825](https://github.com/nix-rust/nix/pull/825)) -- Exposed `termios::cfmakesane` on FreeBSD. - ([#825](https://github.com/nix-rust/nix/pull/825)) -- Exposed `MSG_CMSG_CLOEXEC` on *BSD. - ([#825](https://github.com/nix-rust/nix/pull/825)) -- Added `fchmod`, `fchmodat`. - ([#857](https://github.com/nix-rust/nix/pull/857)) -- Added `request_code_write_int!` on FreeBSD/DragonFlyBSD - ([#833](https://github.com/nix-rust/nix/pull/833)) - -### Changed -- `Display` and `Debug` for `SysControlAddr` now includes all fields. - ([#837](https://github.com/nix-rust/nix/pull/837)) -- `ioctl!` has been replaced with a family of `ioctl_*!` macros. - ([#833](https://github.com/nix-rust/nix/pull/833)) -- `io!`, `ior!`, `iow!`, and `iorw!` has been renamed to `request_code_none!`, `request_code_read!`, - `request_code_write!`, and `request_code_readwrite!` respectively. These have also now been exposed - in the documentation. - ([#833](https://github.com/nix-rust/nix/pull/833)) -- Enabled more `ptrace::Request` definitions for uncommon Linux platforms - ([#892](https://github.com/nix-rust/nix/pull/892)) -- Emulation of `FD_CLOEXEC` and `O_NONBLOCK` was removed from `socket()`, `accept4()`, and - `socketpair()`. - ([#907](https://github.com/nix-rust/nix/pull/907)) - -### Fixed -- Fixed possible panics when using `SigAction::flags` on Linux - ([#869](https://github.com/nix-rust/nix/pull/869)) -- Properly exposed 460800 and 921600 baud rates on NetBSD - ([#837](https://github.com/nix-rust/nix/pull/837)) -- Fixed `ioctl_write_int!` on FreeBSD/DragonFlyBSD - ([#833](https://github.com/nix-rust/nix/pull/833)) -- `ioctl_write_int!` now properly supports passing a `c_ulong` as the parameter on Linux non-musl targets - ([#833](https://github.com/nix-rust/nix/pull/833)) - -### Removed -- Removed explicit support for the `bytes` crate from the `sys::aio` module. - See `sys::aio::AioCb::from_boxed_slice` examples for alternatives. - ([#872](https://github.com/nix-rust/nix/pull/872)) -- Removed `sys::aio::lio_listio`. Use `sys::aio::LioCb::listio` instead. - ([#872](https://github.com/nix-rust/nix/pull/872)) -- Removed emulated `accept4()` from macos, ios, and netbsd targets - ([#907](https://github.com/nix-rust/nix/pull/907)) -- Removed `IFF_NOTRAILERS` on OpenBSD, as it has been removed in OpenBSD 6.3 - ([#893](https://github.com/nix-rust/nix/pull/893)) - -## [0.10.0] 2018-01-26 - -### Added -- Added specialized wrapper: `sys::ptrace::step` - ([#852](https://github.com/nix-rust/nix/pull/852)) -- Added `AioCb::from_ptr` and `AioCb::from_mut_ptr` - ([#820](https://github.com/nix-rust/nix/pull/820)) -- Added specialized wrappers: `sys::ptrace::{traceme, syscall, cont, attach}`. Using the matching routines - with `sys::ptrace::ptrace` is now deprecated. -- Added `nix::poll` module for all platforms - ([#672](https://github.com/nix-rust/nix/pull/672)) -- Added `nix::ppoll` function for FreeBSD and DragonFly - ([#672](https://github.com/nix-rust/nix/pull/672)) -- Added protocol families in `AddressFamily` enum. - ([#647](https://github.com/nix-rust/nix/pull/647)) -- Added the `pid()` method to `WaitStatus` for extracting the PID. - ([#722](https://github.com/nix-rust/nix/pull/722)) -- Added `nix::unistd:fexecve`. - ([#727](https://github.com/nix-rust/nix/pull/727)) -- Expose `uname()` on all platforms. - ([#739](https://github.com/nix-rust/nix/pull/739)) -- Expose `signalfd` module on Android as well. - ([#739](https://github.com/nix-rust/nix/pull/739)) -- Added `nix::sys::ptrace::detach`. - ([#749](https://github.com/nix-rust/nix/pull/749)) -- Added timestamp socket control message variant: - `nix::sys::socket::ControlMessage::ScmTimestamp` - ([#663](https://github.com/nix-rust/nix/pull/663)) -- Added socket option variant that enables the timestamp socket - control message: `nix::sys::socket::sockopt::ReceiveTimestamp` - ([#663](https://github.com/nix-rust/nix/pull/663)) -- Added more accessor methods for `AioCb` - ([#773](https://github.com/nix-rust/nix/pull/773)) -- Add `nix::sys::fallocate` - ([#768](https:://github.com/nix-rust/nix/pull/768)) -- Added `nix::unistd::mkfifo`. - ([#602](https://github.com/nix-rust/nix/pull/774)) -- Added `ptrace::Options::PTRACE_O_EXITKILL` on Linux and Android. - ([#771](https://github.com/nix-rust/nix/pull/771)) -- Added `nix::sys::uio::{process_vm_readv, process_vm_writev}` on Linux - ([#568](https://github.com/nix-rust/nix/pull/568)) -- Added `nix::unistd::{getgroups, setgroups, getgrouplist, initgroups}`. ([#733](https://github.com/nix-rust/nix/pull/733)) -- Added `nix::sys::socket::UnixAddr::as_abstract` on Linux and Android. - ([#785](https://github.com/nix-rust/nix/pull/785)) -- Added `nix::unistd::execveat` on Linux and Android. - ([#800](https://github.com/nix-rust/nix/pull/800)) -- Added the `from_raw()` method to `WaitStatus` for converting raw status values - to `WaitStatus` independent of syscalls. - ([#741](https://github.com/nix-rust/nix/pull/741)) -- Added more standard trait implementations for various types. - ([#814](https://github.com/nix-rust/nix/pull/814)) -- Added `sigprocmask` to the signal module. - ([#826](https://github.com/nix-rust/nix/pull/826)) -- Added `nix::sys::socket::LinkAddr` on Linux and all bsdlike system. - ([#813](https://github.com/nix-rust/nix/pull/813)) -- Add socket options for `IP_TRANSPARENT` / `BIND_ANY`. - ([#835](https://github.com/nix-rust/nix/pull/835)) - -### Changed -- Exposed the `mqueue` module for all supported operating systems. - ([#834](https://github.com/nix-rust/nix/pull/834)) -- Use native `pipe2` on all BSD targets. Users should notice no difference. - ([#777](https://github.com/nix-rust/nix/pull/777)) -- Renamed existing `ptrace` wrappers to encourage namespacing ([#692](https://github.com/nix-rust/nix/pull/692)) -- Marked `sys::ptrace::ptrace` as `unsafe`. -- Changed function signature of `socket()` and `socketpair()`. The `protocol` argument - has changed type from `c_int` to `SockProtocol`. - It accepts a `None` value for default protocol that was specified with zero using `c_int`. - ([#647](https://github.com/nix-rust/nix/pull/647)) -- Made `select` easier to use, adding the ability to automatically calculate the `nfds` parameter using the new - `FdSet::highest` ([#701](https://github.com/nix-rust/nix/pull/701)) -- Exposed `unistd::setresuid` and `unistd::setresgid` on FreeBSD and OpenBSD - ([#721](https://github.com/nix-rust/nix/pull/721)) -- Refactored the `statvfs` module removing extraneous API functions and the - `statvfs::vfs` module. Additionally `(f)statvfs()` now return the struct - directly. And the returned `Statvfs` struct now exposes its data through - accessor methods. ([#729](https://github.com/nix-rust/nix/pull/729)) -- The `addr` argument to `madvise` and `msync` is now `*mut` to better match the - libc API. ([#731](https://github.com/nix-rust/nix/pull/731)) -- `shm_open` and `shm_unlink` are no longer exposed on Android targets, where - they are not officially supported. ([#731](https://github.com/nix-rust/nix/pull/731)) -- `MapFlags`, `MmapAdvise`, and `MsFlags` expose some more variants and only - officially-supported variants are provided for each target. - ([#731](https://github.com/nix-rust/nix/pull/731)) -- Marked `pty::ptsname` function as `unsafe` - ([#744](https://github.com/nix-rust/nix/pull/744)) -- Moved constants ptrace request, event and options to enums and updated ptrace functions and argument types accordingly. - ([#749](https://github.com/nix-rust/nix/pull/749)) -- `AioCb::Drop` will now panic if the `AioCb` is still in-progress ([#715](https://github.com/nix-rust/nix/pull/715)) -- Restricted `nix::sys::socket::UnixAddr::new_abstract` to Linux and Android only. - ([#785](https://github.com/nix-rust/nix/pull/785)) -- The `ucred` struct has been removed in favor of a `UserCredentials` struct that - contains only getters for its fields. - ([#814](https://github.com/nix-rust/nix/pull/814)) -- Both `ip_mreq` and `ipv6_mreq` have been replaced with `IpMembershipRequest` and - `Ipv6MembershipRequest`. - ([#814](https://github.com/nix-rust/nix/pull/814)) -- Removed return type from `pause`. - ([#829](https://github.com/nix-rust/nix/pull/829)) -- Changed the termios APIs to allow for using a `u32` instead of the `BaudRate` - enum on BSD platforms to support arbitrary baud rates. See the module docs for - `nix::sys::termios` for more details. - ([#843](https://github.com/nix-rust/nix/pull/843)) - -### Fixed -- Fix compilation and tests for OpenBSD targets - ([#688](https://github.com/nix-rust/nix/pull/688)) -- Fixed error handling in `AioCb::fsync`, `AioCb::read`, and `AioCb::write`. - It is no longer an error to drop an `AioCb` that failed to enqueue in the OS. - ([#715](https://github.com/nix-rust/nix/pull/715)) -- Fix potential memory corruption on non-Linux platforms when using - `sendmsg`/`recvmsg`, caused by mismatched `msghdr` definition. - ([#648](https://github.com/nix-rust/nix/pull/648)) - -### Removed -- `AioCb::from_boxed_slice` has been removed. It was never actually safe. Use - `from_bytes` or `from_bytes_mut` instead. - ([#820](https://github.com/nix-rust/nix/pull/820)) -- The syscall module has been removed. This only exposed enough functionality for - `memfd_create()` and `pivot_root()`, which are still exposed as separate functions. - ([#747](https://github.com/nix-rust/nix/pull/747)) -- The `Errno` variants are no longer reexported from the `errno` module. `Errno` itself is no longer reexported from the - crate root and instead must be accessed using the `errno` module. ([#696](https://github.com/nix-rust/nix/pull/696)) -- Removed `MS_VERBOSE`, `MS_NOSEC`, and `MS_BORN` from `MsFlags`. These - are internal kernel flags and should never have been exposed. - ([#814](https://github.com/nix-rust/nix/pull/814)) - - -## [0.9.0] 2017-07-23 - -### Added -- Added `sysconf`, `pathconf`, and `fpathconf` - ([#630](https://github.com/nix-rust/nix/pull/630) -- Added `sys::signal::SigAction::{ flags, mask, handler}` - ([#611](https://github.com/nix-rust/nix/pull/609) -- Added `nix::sys::pthread::pthread_self` - ([#591](https://github.com/nix-rust/nix/pull/591) -- Added `AioCb::from_boxed_slice` - ([#582](https://github.com/nix-rust/nix/pull/582) -- Added `nix::unistd::{openat, fstatat, readlink, readlinkat}` - ([#551](https://github.com/nix-rust/nix/pull/551)) -- Added `nix::pty::{grantpt, posix_openpt, ptsname/ptsname_r, unlockpt}` - ([#556](https://github.com/nix-rust/nix/pull/556) -- Added `nix::ptr::openpty` - ([#456](https://github.com/nix-rust/nix/pull/456)) -- Added `nix::ptrace::{ptrace_get_data, ptrace_getsiginfo, ptrace_setsiginfo - and nix::Error::UnsupportedOperation}` - ([#614](https://github.com/nix-rust/nix/pull/614)) -- Added `cfmakeraw`, `cfsetspeed`, and `tcgetsid`. ([#527](https://github.com/nix-rust/nix/pull/527)) -- Added "bad none", "bad write_ptr", "bad write_int", and "bad readwrite" variants to the `ioctl!` - macro. ([#670](https://github.com/nix-rust/nix/pull/670)) -- On Linux and Android, added support for receiving `PTRACE_O_TRACESYSGOOD` - events from `wait` and `waitpid` using `WaitStatus::PtraceSyscall` - ([#566](https://github.com/nix-rust/nix/pull/566)). - -### Changed -- The `ioctl!` macro and its variants now allow the generated functions to have - doccomments. ([#661](https://github.com/nix-rust/nix/pull/661)) -- Changed `ioctl!(write ...)` into `ioctl!(write_ptr ...)` and `ioctl!(write_int ..)` variants - to more clearly separate those use cases. ([#670](https://github.com/nix-rust/nix/pull/670)) -- Marked `sys::mman::{ mmap, munmap, madvise, munlock, msync }` as unsafe. - ([#559](https://github.com/nix-rust/nix/pull/559)) -- Minimum supported Rust version is now 1.13. -- Removed `revents` argument from `PollFd::new()` as it's an output argument and - will be overwritten regardless of value. - ([#542](https://github.com/nix-rust/nix/pull/542)) -- Changed type signature of `sys::select::FdSet::contains` to make `self` - immutable ([#564](https://github.com/nix-rust/nix/pull/564)) -- Introduced wrapper types for `gid_t`, `pid_t`, and `uid_t` as `Gid`, `Pid`, and `Uid` - respectively. Various functions have been changed to use these new types as - arguments. ([#629](https://github.com/nix-rust/nix/pull/629)) -- Fixed compilation on all Android and iOS targets ([#527](https://github.com/nix-rust/nix/pull/527)) - and promoted them to Tier 2 support. -- `nix::sys::statfs::{statfs,fstatfs}` uses statfs definition from `libc::statfs` instead of own linux specific type `nix::sys::Statfs`. - Also file system type constants like `nix::sys::statfs::ADFS_SUPER_MAGIC` were removed in favor of the libc equivalent. - ([#561](https://github.com/nix-rust/nix/pull/561)) -- Revised the termios API including additional tests and documentation and exposed it on iOS. ([#527](https://github.com/nix-rust/nix/pull/527)) -- `eventfd`, `signalfd`, and `pwritev`/`preadv` functionality is now included by default for all - supported platforms. ([#681](https://github.com/nix-rust/nix/pull/561)) -- The `ioctl!` macro's plain variants has been replaced with "bad read" to be consistent with - other variants. The generated functions also have more strict types for their arguments. The - "*_buf" variants also now calculate total array size and take slice references for improved type - safety. The documentation has also been dramatically improved. - ([#670](https://github.com/nix-rust/nix/pull/670)) - -### Removed -- Removed `io::Error` from `nix::Error` and the conversion from `nix::Error` to `Errno` - ([#614](https://github.com/nix-rust/nix/pull/614)) -- All feature flags have been removed in favor of conditional compilation on supported platforms. - `execvpe` is no longer supported, but this was already broken and will be added back in the next - release. ([#681](https://github.com/nix-rust/nix/pull/561)) -- Removed `ioc_*` functions and many helper constants and macros within the `ioctl` module. These - should always have been private and only the `ioctl!` should be used in public code. - ([#670](https://github.com/nix-rust/nix/pull/670)) - -### Fixed -- Fixed multiple issues compiling under different archetectures and OSes. - Now compiles on Linux/MIPS ([#538](https://github.com/nix-rust/nix/pull/538)), - `Linux/PPC` ([#553](https://github.com/nix-rust/nix/pull/553)), - `MacOS/x86_64,i686` ([#553](https://github.com/nix-rust/nix/pull/553)), - `NetBSD/x64_64` ([#538](https://github.com/nix-rust/nix/pull/538)), - `FreeBSD/x86_64,i686` ([#536](https://github.com/nix-rust/nix/pull/536)), and - `Android` ([#631](https://github.com/nix-rust/nix/pull/631)). -- `bind` and `errno_location` now work correctly on `Android` - ([#631](https://github.com/nix-rust/nix/pull/631)) -- Added `nix::ptrace` on all Linux-kernel-based platforms - [#624](https://github.com/nix-rust/nix/pull/624). Previously it was - only available on x86, x86-64, and ARM, and also not on Android. -- Fixed `sys::socket::sendmsg` with zero entry `cmsgs` parameter. - ([#623](https://github.com/nix-rust/nix/pull/623)) -- Multiple constants related to the termios API have now been properly defined for - all supported platforms. ([#527](https://github.com/nix-rust/nix/pull/527)) -- `ioctl!` macro now supports working with non-int datatypes and properly supports all platforms. - ([#670](https://github.com/nix-rust/nix/pull/670)) - -## [0.8.1] 2017-04-16 - -### Fixed -- Fixed build on FreeBSD. (Cherry-picked - [a859ee3c](https://github.com/nix-rust/nix/commit/a859ee3c9396dfdb118fcc2c8ecc697e2d303467)) - -## [0.8.0] 2017-03-02 - -### Added -- Added `::nix::sys::termios::BaudRate` enum to provide portable baudrate - values. ([#518](https://github.com/nix-rust/nix/pull/518)) -- Added a new `WaitStatus::PtraceEvent` to support ptrace events on Linux - and Android ([#438](https://github.com/nix-rust/nix/pull/438)) -- Added support for POSIX AIO - ([#483](https://github.com/nix-rust/nix/pull/483)) - ([#506](https://github.com/nix-rust/nix/pull/506)) -- Added support for XNU system control sockets - ([#478](https://github.com/nix-rust/nix/pull/478)) -- Added support for `ioctl` calls on BSD platforms - ([#478](https://github.com/nix-rust/nix/pull/478)) -- Added struct `TimeSpec` - ([#475](https://github.com/nix-rust/nix/pull/475)) - ([#483](https://github.com/nix-rust/nix/pull/483)) -- Added complete definitions for all kqueue-related constants on all supported - OSes - ([#415](https://github.com/nix-rust/nix/pull/415)) -- Added function `epoll_create1` and bitflags `EpollCreateFlags` in - `::nix::sys::epoll` in order to support `::libc::epoll_create1`. - ([#410](https://github.com/nix-rust/nix/pull/410)) -- Added `setresuid` and `setresgid` for Linux in `::nix::unistd` - ([#448](https://github.com/nix-rust/nix/pull/448)) -- Added `getpgid` in `::nix::unistd` - ([#433](https://github.com/nix-rust/nix/pull/433)) -- Added `tcgetpgrp` and `tcsetpgrp` in `::nix::unistd` - ([#451](https://github.com/nix-rust/nix/pull/451)) -- Added `CLONE_NEWCGROUP` in `::nix::sched` - ([#457](https://github.com/nix-rust/nix/pull/457)) -- Added `getpgrp` in `::nix::unistd` - ([#491](https://github.com/nix-rust/nix/pull/491)) -- Added `fchdir` in `::nix::unistd` - ([#497](https://github.com/nix-rust/nix/pull/497)) -- Added `major` and `minor` in `::nix::sys::stat` for decomposing `dev_t` - ([#508](https://github.com/nix-rust/nix/pull/508)) -- Fixed the style of many bitflags and use `libc` in more places. - ([#503](https://github.com/nix-rust/nix/pull/503)) -- Added `ppoll` in `::nix::poll` - ([#520](https://github.com/nix-rust/nix/pull/520)) -- Added support for getting and setting pipe size with fcntl(2) on Linux - ([#540](https://github.com/nix-rust/nix/pull/540)) - -### Changed -- `::nix::sys::termios::{cfgetispeed, cfsetispeed, cfgetospeed, cfsetospeed}` - switched to use `BaudRate` enum from `speed_t`. - ([#518](https://github.com/nix-rust/nix/pull/518)) -- `epoll_ctl` now could accept None as argument `event` - when op is `EpollOp::EpollCtlDel`. - ([#480](https://github.com/nix-rust/nix/pull/480)) -- Removed the `bad` keyword from the `ioctl!` macro - ([#478](https://github.com/nix-rust/nix/pull/478)) -- Changed `TimeVal` into an opaque Newtype - ([#475](https://github.com/nix-rust/nix/pull/475)) -- `kill`'s signature, defined in `::nix::sys::signal`, changed, so that the - signal parameter has type `T: Into>`. `None` as an argument - for that parameter will result in a 0 passed to libc's `kill`, while a - `Some`-argument will result in the previous behavior for the contained - `Signal`. - ([#445](https://github.com/nix-rust/nix/pull/445)) -- The minimum supported version of rustc is now 1.7.0. - ([#444](https://github.com/nix-rust/nix/pull/444)) -- Changed `KEvent` to an opaque structure that may only be modified by its - constructor and the `ev_set` method. - ([#415](https://github.com/nix-rust/nix/pull/415)) - ([#442](https://github.com/nix-rust/nix/pull/442)) - ([#463](https://github.com/nix-rust/nix/pull/463)) -- `pipe2` now calls `libc::pipe2` where available. Previously it was emulated - using `pipe`, which meant that setting `O_CLOEXEC` was not atomic. - ([#427](https://github.com/nix-rust/nix/pull/427)) -- Renamed `EpollEventKind` to `EpollFlags` in `::nix::sys::epoll` in order for - it to conform with our conventions. - ([#410](https://github.com/nix-rust/nix/pull/410)) -- `EpollEvent` in `::nix::sys::epoll` is now an opaque proxy for - `::libc::epoll_event`. The formerly public field `events` is now be read-only - accessible with the new method `events()` of `EpollEvent`. Instances of - `EpollEvent` can be constructed using the new method `new()` of EpollEvent. - ([#410](https://github.com/nix-rust/nix/pull/410)) -- `SigFlags` in `::nix::sys::signal` has be renamed to `SigmaskHow` and its type - has changed from `bitflags` to `enum` in order to conform to our conventions. - ([#460](https://github.com/nix-rust/nix/pull/460)) -- `sethostname` now takes a `&str` instead of a `&[u8]` as this provides an API - that makes more sense in normal, correct usage of the API. -- `gethostname` previously did not expose the actual length of the hostname - written from the underlying system call at all. This has been updated to - return a `&CStr` within the provided buffer that is always properly - NUL-terminated (this is not guaranteed by the call with all platforms/libc - implementations). -- Exposed all fcntl(2) operations at the module level, so they can be - imported direclty instead of via `FcntlArg` enum. - ([#541](https://github.com/nix-rust/nix/pull/541)) - -### Fixed -- Fixed multiple issues with Unix domain sockets on non-Linux OSes - ([#474](https://github.com/nix-rust/nix/pull/415)) -- Fixed using kqueue with `EVFILT_USER` on FreeBSD - ([#415](https://github.com/nix-rust/nix/pull/415)) -- Fixed the build on FreeBSD, and fixed the getsockopt, sendmsg, and recvmsg - functions on that same OS. - ([#397](https://github.com/nix-rust/nix/pull/397)) -- Fixed an off-by-one bug in `UnixAddr::new_abstract` in `::nix::sys::socket`. - ([#429](https://github.com/nix-rust/nix/pull/429)) -- Fixed clone passing a potentially unaligned stack. - ([#490](https://github.com/nix-rust/nix/pull/490)) -- Fixed mkdev not creating a `dev_t` the same way as libc. - ([#508](https://github.com/nix-rust/nix/pull/508)) - -## [0.7.0] 2016-09-09 - -### Added -- Added `lseek` and `lseek64` in `::nix::unistd` - ([#377](https://github.com/nix-rust/nix/pull/377)) -- Added `mkdir` and `getcwd` in `::nix::unistd` - ([#416](https://github.com/nix-rust/nix/pull/416)) -- Added accessors `sigmask_mut` and `sigmask` to `UContext` in - `::nix::ucontext`. - ([#370](https://github.com/nix-rust/nix/pull/370)) -- Added `WUNTRACED` to `WaitPidFlag` in `::nix::sys::wait` for non-_linux_ - targets. - ([#379](https://github.com/nix-rust/nix/pull/379)) -- Added new module `::nix::sys::reboot` with enumeration `RebootMode` and - functions `reboot` and `set_cad_enabled`. Currently for _linux_ only. - ([#386](https://github.com/nix-rust/nix/pull/386)) -- `FdSet` in `::nix::sys::select` now also implements `Clone`. - ([#405](https://github.com/nix-rust/nix/pull/405)) -- Added `F_FULLFSYNC` to `FcntlArg` in `::nix::fcntl` for _apple_ targets. - ([#407](https://github.com/nix-rust/nix/pull/407)) -- Added `CpuSet::unset` in `::nix::sched`. - ([#402](https://github.com/nix-rust/nix/pull/402)) -- Added constructor method `new()` to `PollFd` in `::nix::poll`, in order to - allow creation of objects, after removing public access to members. - ([#399](https://github.com/nix-rust/nix/pull/399)) -- Added method `revents()` to `PollFd` in `::nix::poll`, in order to provide - read access to formerly public member `revents`. - ([#399](https://github.com/nix-rust/nix/pull/399)) -- Added `MSG_CMSG_CLOEXEC` to `MsgFlags` in `::nix::sys::socket` for _linux_ only. - ([#422](https://github.com/nix-rust/nix/pull/422)) - -### Changed -- Replaced the reexported integer constants for signals by the enumeration - `Signal` in `::nix::sys::signal`. - ([#362](https://github.com/nix-rust/nix/pull/362)) -- Renamed `EventFdFlag` to `EfdFlags` in `::nix::sys::eventfd`. - ([#383](https://github.com/nix-rust/nix/pull/383)) -- Changed the result types of `CpuSet::is_set` and `CpuSet::set` in - `::nix::sched` to `Result` and `Result<()>`, respectively. They now - return `EINVAL`, if an invalid argument for the `field` parameter is passed. - ([#402](https://github.com/nix-rust/nix/pull/402)) -- `MqAttr` in `::nix::mqueue` is now an opaque proxy for `::libc::mq_attr`, - which has the same structure as the old `MqAttr`. The field `mq_flags` of - `::libc::mq_attr` is readable using the new method `flags()` of `MqAttr`. - `MqAttr` also no longer implements `Debug`. - ([#392](https://github.com/nix-rust/nix/pull/392)) -- The parameter `msq_prio` of `mq_receive` with type `u32` in `::nix::mqueue` - was replaced by a parameter named `msg_prio` with type `&mut u32`, so that - the message priority can be obtained by the caller. - ([#392](https://github.com/nix-rust/nix/pull/392)) -- The type alias `MQd` in `::nix::queue` was replaced by the type alias - `libc::mqd_t`, both of which are aliases for the same type. - ([#392](https://github.com/nix-rust/nix/pull/392)) - -### Removed -- Type alias `SigNum` from `::nix::sys::signal`. - ([#362](https://github.com/nix-rust/nix/pull/362)) -- Type alias `CpuMask` from `::nix::shed`. - ([#402](https://github.com/nix-rust/nix/pull/402)) -- Removed public fields from `PollFd` in `::nix::poll`. (See also added method - `revents()`. - ([#399](https://github.com/nix-rust/nix/pull/399)) - -### Fixed -- Fixed the build problem for NetBSD (Note, that we currently do not support - it, so it might already be broken again). - ([#389](https://github.com/nix-rust/nix/pull/389)) -- Fixed the build on FreeBSD, and fixed the getsockopt, sendmsg, and recvmsg - functions on that same OS. - ([#397](https://github.com/nix-rust/nix/pull/397)) - -## [0.6.0] 2016-06-10 - -### Added -- Added `gettid` in `::nix::unistd` for _linux_ and _android_. - ([#293](https://github.com/nix-rust/nix/pull/293)) -- Some _mips_ support in `::nix::sched` and `::nix::sys::syscall`. - ([#301](https://github.com/nix-rust/nix/pull/301)) -- Added `SIGNALFD_SIGINFO_SIZE` in `::nix::sys::signalfd`. - ([#309](https://github.com/nix-rust/nix/pull/309)) -- Added new module `::nix::ucontext` with struct `UContext`. Currently for - _linux_ only. - ([#311](https://github.com/nix-rust/nix/pull/311)) -- Added `EPOLLEXCLUSIVE` to `EpollEventKind` in `::nix::sys::epoll`. - ([#330](https://github.com/nix-rust/nix/pull/330)) -- Added `pause` to `::nix::unistd`. - ([#336](https://github.com/nix-rust/nix/pull/336)) -- Added `sleep` to `::nix::unistd`. - ([#351](https://github.com/nix-rust/nix/pull/351)) -- Added `S_IFDIR`, `S_IFLNK`, `S_IFMT` to `SFlag` in `::nix::sys::stat`. - ([#359](https://github.com/nix-rust/nix/pull/359)) -- Added `clear` and `extend` functions to `SigSet`'s implementation in - `::nix::sys::signal`. - ([#347](https://github.com/nix-rust/nix/pull/347)) -- `sockaddr_storage_to_addr` in `::nix::sys::socket` now supports `sockaddr_nl` - on _linux_ and _android_. - ([#366](https://github.com/nix-rust/nix/pull/366)) -- Added support for `SO_ORIGINAL_DST` in `::nix::sys::socket` on _linux_. - ([#367](https://github.com/nix-rust/nix/pull/367)) -- Added `SIGINFO` in `::nix::sys::signal` for the _macos_ target as well as - `SIGPWR` and `SIGSTKFLT` in `::nix::sys::signal` for non-_macos_ targets. - ([#361](https://github.com/nix-rust/nix/pull/361)) - -### Changed -- Changed the structure `IoVec` in `::nix::sys::uio`. - ([#304](https://github.com/nix-rust/nix/pull/304)) -- Replaced `CREATE_NEW_FD` by `SIGNALFD_NEW` in `::nix::sys::signalfd`. - ([#309](https://github.com/nix-rust/nix/pull/309)) -- Renamed `SaFlag` to `SaFlags` and `SigFlag` to `SigFlags` in - `::nix::sys::signal`. - ([#314](https://github.com/nix-rust/nix/pull/314)) -- Renamed `Fork` to `ForkResult` and changed its fields in `::nix::unistd`. - ([#332](https://github.com/nix-rust/nix/pull/332)) -- Added the `signal` parameter to `clone`'s signature in `::nix::sched`. - ([#344](https://github.com/nix-rust/nix/pull/344)) -- `execv`, `execve`, and `execvp` now return `Result` instead of - `Result<()>` in `::nix::unistd`. - ([#357](https://github.com/nix-rust/nix/pull/357)) - -### Fixed -- Improved the conversion from `std::net::SocketAddr` to `InetAddr` in - `::nix::sys::socket::addr`. - ([#335](https://github.com/nix-rust/nix/pull/335)) - -## [0.5.0] 2016-03-01 diff --git a/vendor/nix-v0.23.1-patched/CONTRIBUTING.md b/vendor/nix-v0.23.1-patched/CONTRIBUTING.md deleted file mode 100644 index 00221157b..000000000 --- a/vendor/nix-v0.23.1-patched/CONTRIBUTING.md +++ /dev/null @@ -1,114 +0,0 @@ -# Contributing to nix - -We're really glad you're interested in contributing to nix! This -document has a few pointers and guidelines to help get you started. - -To have a welcoming and inclusive project, nix uses the Rust project's -[Code of Conduct][conduct]. All contributors are expected to follow it. - -[conduct]: https://www.rust-lang.org/conduct.html - - -# Issues - -We use GitHub's [issue tracker][issues]. - -[issues]: https://github.com/nix-rust/nix/issues - - -## Bug reports - -Before submitting a new bug report, please [search existing -issues][issue-search] to see if there's something related. If not, just -[open a new issue][new-issue]! - -As a reminder, the more information you can give in your issue, the -easier it is to figure out how to fix it. For nix, this will likely -include the OS and version, and the architecture. - -[issue-search]: https://github.com/nix-rust/nix/search?utf8=%E2%9C%93&q=is%3Aissue&type=Issues -[new-issue]: https://github.com/nix-rust/nix/issues/new - - -## Feature / API requests - -If you'd like a new API or feature added, please [open a new -issue][new-issue] requesting it. As with reporting a bug, the more -information you can provide, the better. - - -## Labels - -We use labels to help manage issues. The structure is modeled after -[Rust's issue labeling scheme][rust-labels]: -- **A-** prefixed labels state which area of the project the issue - relates to -- **E-** prefixed labels explain the level of experience necessary to fix the - issue -- **O-** prefixed labels specify the OS for issues that are OS-specific -- **R-** prefixed labels specify the architecture for issues that are - architecture-specific - -[rust-labels]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#issue-triage - - -# Pull requests - -GitHub pull requests are the primary mechanism we use to change nix. GitHub itself has -some [great documentation][pr-docs] on using the Pull Request feature. We use the 'fork and -pull' model described there. - -Please make pull requests against the `master` branch. - -If you change the API by way of adding, removing or changing something or if -you fix a bug, please add an appropriate note to the [change log][cl]. We -follow the conventions of [Keep A CHANGELOG][kacl]. - -[cl]: https://github.com/nix-rust/nix/blob/master/CHANGELOG.md -[kacl]: https://github.com/olivierlacan/keep-a-changelog/tree/18adb5f5be7a898d046f6a4acb93e39dcf40c4ad -[pr-docs]: https://help.github.com/articles/using-pull-requests/ - -## Testing - -nix has a test suite that you can run with `cargo test`. Ideally, we'd like pull -requests to include tests where they make sense. For example, when fixing a bug, -add a test that would have failed without the fix. - -After you've made your change, make sure the tests pass in your development -environment. We also have [continuous integration set up on -Cirrus-CI][cirrus-ci], which might find some issues on other platforms. The CI -will run once you open a pull request. - -There is also infrastructure for running tests for other targets -locally. More information is available in the [CI Readme][ci-readme]. - -[cirrus-ci]: https://cirrus-ci.com/github/nix-rust/nix -[ci-readme]: ci/README.md - -### Disabling a test in the CI environment - -Sometimes there are features that cannot be tested in the CI environment. -To stop a test from running under CI, add `skip_if_cirrus!()` to it. Please -describe the reason it shouldn't run under CI, and a link to an issue if -possible! - -## bors, the bot who merges all the PRs - -All pull requests are merged via [bors], an integration bot. After the -pull request has been reviewed, the reviewer will leave a comment like - -> bors r+ - -to let bors know that it was approved. Then bors will check that it passes -tests when merged with the latest changes in the `master` branch, and -merge if the tests succeed. - -[bors]: https://bors-ng.github.io/ - - -## API conventions - -If you're adding a new API, we have a [document with -conventions][conventions] to use throughout the nix project. - -[conventions]: https://github.com/nix-rust/nix/blob/master/CONVENTIONS.md diff --git a/vendor/nix-v0.23.1-patched/CONVENTIONS.md b/vendor/nix-v0.23.1-patched/CONVENTIONS.md deleted file mode 100644 index 2461085eb..000000000 --- a/vendor/nix-v0.23.1-patched/CONVENTIONS.md +++ /dev/null @@ -1,86 +0,0 @@ -# Conventions - -In order to achieve our goal of wrapping [libc][libc] code in idiomatic rust -constructs with minimal performance overhead, we follow the following -conventions. - -Note that, thus far, not all the code follows these conventions and not all -conventions we try to follow have been documented here. If you find an instance -of either, feel free to remedy the flaw by opening a pull request with -appropriate changes or additions. - -## Change Log - -We follow the conventions laid out in [Keep A CHANGELOG][kacl]. - -[kacl]: https://github.com/olivierlacan/keep-a-changelog/tree/18adb5f5be7a898d046f6a4acb93e39dcf40c4ad - -## libc constants, functions and structs - -We do not define integer constants ourselves, but use or reexport them from the -[libc crate][libc]. - -We use the functions exported from [libc][libc] instead of writing our own -`extern` declarations. - -We use the `struct` definitions from [libc][libc] internally instead of writing -our own. If we want to add methods to a libc type, we use the newtype pattern. -For example, - -```rust -pub struct SigSet(libc::sigset_t); - -impl SigSet { - ... -} -``` - -When creating newtypes, we use Rust's `CamelCase` type naming convention. - -## Bitflags - -Many C functions have flags parameters that are combined from constants using -bitwise operations. We represent the types of these parameters by types defined -using our `libc_bitflags!` macro, which is a convenience wrapper around the -`bitflags!` macro from the [bitflags crate][bitflags] that brings in the -constant value from `libc`. - -We name the type for a set of constants whose element's names start with `FOO_` -`FooFlags`. - -For example, - -```rust -libc_bitflags!{ - pub struct ProtFlags: libc::c_int { - PROT_NONE; - PROT_READ; - PROT_WRITE; - PROT_EXEC; - #[cfg(any(target_os = "linux", target_os = "android"))] - PROT_GROWSDOWN; - #[cfg(any(target_os = "linux", target_os = "android"))] - PROT_GROWSUP; - } -} -``` - - -## Enumerations - -We represent sets of constants that are intended as mutually exclusive arguments -to parameters of functions by [enumerations][enum]. - - -## Structures Initialized by libc Functions - -Whenever we need to use a [libc][libc] function to properly initialize a -variable and said function allows us to use uninitialized memory, we use -[`std::mem::MaybeUninit`][std_MaybeUninit] when defining the variable. This -allows us to avoid the overhead incurred by zeroing or otherwise initializing -the variable. - -[bitflags]: https://crates.io/crates/bitflags/ -[enum]: https://doc.rust-lang.org/reference.html#enumerations -[libc]: https://crates.io/crates/libc/ -[std_MaybeUninit]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html diff --git a/vendor/nix-v0.23.1-patched/Cargo.toml b/vendor/nix-v0.23.1-patched/Cargo.toml deleted file mode 100644 index 6309c12cc..000000000 --- a/vendor/nix-v0.23.1-patched/Cargo.toml +++ /dev/null @@ -1,74 +0,0 @@ -[package] -name = "nix" -description = "Rust friendly bindings to *nix APIs" -edition = "2018" -version = "0.23.1" -authors = ["The nix-rust Project Developers"] -repository = "https://github.com/nix-rust/nix" -license = "MIT" -categories = ["os::unix-apis"] -include = ["src/**/*", "LICENSE", "README.md", "CHANGELOG.md"] - -[package.metadata.docs.rs] -targets = [ - "x86_64-unknown-linux-gnu", - "aarch64-linux-android", - "x86_64-apple-darwin", - "aarch64-apple-ios", - "x86_64-unknown-freebsd", - "x86_64-unknown-openbsd", - "x86_64-unknown-netbsd", - "x86_64-unknown-dragonfly", - "x86_64-fuchsia", - "x86_64-unknown-redox", - "x86_64-unknown-illumos" -] - -[dependencies] -libc = { version = "0.2.102", features = [ "extra_traits" ] } -bitflags = "1.3.1" -cfg-if = "1.0" - -[target.'cfg(not(target_os = "redox"))'.dependencies] -memoffset = "0.6.3" - -[target.'cfg(target_os = "dragonfly")'.build-dependencies] -cc = "1" - -[dev-dependencies] -assert-impl = "0.1" -lazy_static = "1.2" -rand = "0.8" -tempfile = "3.2.0" -semver = "1.0.0" - -[target.'cfg(any(target_os = "android", target_os = "linux"))'.dev-dependencies] -caps = "0.5.1" - -[target.'cfg(target_os = "freebsd")'.dev-dependencies] -sysctl = "0.1" - -[[test]] -name = "test" -path = "test/test.rs" - -[[test]] -name = "test-aio-drop" -path = "test/sys/test_aio_drop.rs" - -[[test]] -name = "test-clearenv" -path = "test/test_clearenv.rs" - -[[test]] -name = "test-lio-listio-resubmit" -path = "test/sys/test_lio_listio_resubmit.rs" - -[[test]] -name = "test-mount" -path = "test/test_mount.rs" -harness = false - -[[test]] -name = "test-ptymaster-drop" -path = "test/test_ptymaster_drop.rs" diff --git a/vendor/nix-v0.23.1-patched/Cross.toml b/vendor/nix-v0.23.1-patched/Cross.toml deleted file mode 100644 index acd94f308..000000000 --- a/vendor/nix-v0.23.1-patched/Cross.toml +++ /dev/null @@ -1,5 +0,0 @@ -[build.env] -passthrough = [ - "RUSTFLAGS", - "RUST_TEST_THREADS" -] diff --git a/vendor/nix-v0.23.1-patched/LICENSE b/vendor/nix-v0.23.1-patched/LICENSE deleted file mode 100644 index aff9096fd..000000000 --- a/vendor/nix-v0.23.1-patched/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Carl Lerche + nix-rust Authors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/nix-v0.23.1-patched/README.md b/vendor/nix-v0.23.1-patched/README.md deleted file mode 100644 index a8759f1ce..000000000 --- a/vendor/nix-v0.23.1-patched/README.md +++ /dev/null @@ -1,102 +0,0 @@ -# Rust bindings to *nix APIs - -[![Cirrus Build Status](https://api.cirrus-ci.com/github/nix-rust/nix.svg)](https://cirrus-ci.com/github/nix-rust/nix) -[![crates.io](https://img.shields.io/crates/v/nix.svg)](https://crates.io/crates/nix) - -[Documentation (Releases)](https://docs.rs/nix/) - -Nix seeks to provide friendly bindings to various *nix platform APIs (Linux, Darwin, -...). The goal is to not provide a 100% unified interface, but to unify -what can be while still providing platform specific APIs. - -For many system APIs, Nix provides a safe alternative to the unsafe APIs -exposed by the [libc crate](https://github.com/rust-lang/libc). This is done by -wrapping the libc functionality with types/abstractions that enforce legal/safe -usage. - - -As an example of what Nix provides, examine the differences between what is -exposed by libc and nix for the -[gethostname](https://man7.org/linux/man-pages/man2/gethostname.2.html) system -call: - -```rust,ignore -// libc api (unsafe, requires handling return code/errno) -pub unsafe extern fn gethostname(name: *mut c_char, len: size_t) -> c_int; - -// nix api (returns a nix::Result) -pub fn gethostname<'a>(buffer: &'a mut [u8]) -> Result<&'a CStr>; -``` - -## Supported Platforms - -nix target support consists of two tiers. While nix attempts to support all -platforms supported by [libc](https://github.com/rust-lang/libc), only some -platforms are actively supported due to either technical or manpower -limitations. Support for platforms is split into three tiers: - - * Tier 1 - Builds and tests for this target are run in CI. Failures of either - block the inclusion of new code. - * Tier 2 - Builds for this target are run in CI. Failures during the build - blocks the inclusion of new code. Tests may be run, but failures - in tests don't block the inclusion of new code. - * Tier 3 - Builds for this target are run in CI. Failures during the build - *do not* block the inclusion of new code. Testing may be run, but - failures in tests don't block the inclusion of new code. - -The following targets are supported by `nix`: - -Tier 1: - * aarch64-unknown-linux-gnu - * arm-unknown-linux-gnueabi - * armv7-unknown-linux-gnueabihf - * i686-unknown-freebsd - * i686-unknown-linux-gnu - * i686-unknown-linux-musl - * mips-unknown-linux-gnu - * mips64-unknown-linux-gnuabi64 - * mips64el-unknown-linux-gnuabi64 - * mipsel-unknown-linux-gnu - * powerpc64le-unknown-linux-gnu - * x86_64-apple-darwin - * x86_64-unknown-freebsd - * x86_64-unknown-linux-gnu - * x86_64-unknown-linux-musl - -Tier 2: - * aarch64-apple-ios - * aarch64-linux-android - * arm-linux-androideabi - * arm-unknown-linux-musleabi - * armv7-linux-androideabi - * i686-linux-android - * powerpc-unknown-linux-gnu - * s390x-unknown-linux-gnu - * x86_64-apple-ios - * x86_64-linux-android - * x86_64-unknown-illumos - * x86_64-unknown-netbsd - -Tier 3: - * x86_64-fuchsia - * x86_64-unknown-dragonfly - * x86_64-unknown-linux-gnux32 - * x86_64-unknown-openbsd - * x86_64-unknown-redox - -## Minimum Supported Rust Version (MSRV) - -nix is supported on Rust 1.46.0 and higher. It's MSRV will not be -changed in the future without bumping the major or minor version. - -## Contributing - -Contributions are very welcome. Please See [CONTRIBUTING](CONTRIBUTING.md) for -additional details. - -Feel free to join us in [the nix-rust/nix](https://gitter.im/nix-rust/nix) channel on Gitter to -discuss `nix` development. - -## License - -Nix is licensed under the MIT license. See [LICENSE](LICENSE) for more details. diff --git a/vendor/nix-v0.23.1-patched/RELEASE_PROCEDURE.md b/vendor/nix-v0.23.1-patched/RELEASE_PROCEDURE.md deleted file mode 100644 index b8cfcd81d..000000000 --- a/vendor/nix-v0.23.1-patched/RELEASE_PROCEDURE.md +++ /dev/null @@ -1,18 +0,0 @@ -This document lists the steps that lead to a successful release of the Nix -library. - -# Before Release - -Nix uses [cargo release](https://github.com/crate-ci/cargo-release) to automate -the release process. Based on changes since the last release, pick a new -version number following semver conventions. For nix, a change that drops -support for some Rust versions counts as a breaking change, and requires a -major bump. - -The release is prepared as follows: - -- Ask for a new libc version if, necessary. It usually is. Then update the - dependency in Cargo.toml accordingly. -- Confirm that everything's ready for a release by running - `cargo release --dry-run ` -- Create the release with `cargo release ` diff --git a/vendor/nix-v0.23.1-patched/bors.toml b/vendor/nix-v0.23.1-patched/bors.toml deleted file mode 100644 index 03810b7e8..000000000 --- a/vendor/nix-v0.23.1-patched/bors.toml +++ /dev/null @@ -1,49 +0,0 @@ -status = [ - "Android aarch64", - "Android arm", - "Android armv7", - "Android i686", - "Android x86_64", - "DragonFly BSD x86_64", - "FreeBSD amd64 & i686", - "Fuchsia x86_64", - "Linux MIPS", - "Linux MIPS64 el", - "Linux MIPS64", - "Linux aarch64", - "Linux arm gnueabi", - "Linux arm-musleabi", - "Linux armv7 gnueabihf", - "Linux i686 musl", - "Linux i686", - "Linux mipsel", - "Linux powerpc", - "Linux powerpc64", - "Linux powerpc64le", - "Linux s390x", - "Linux x32", - "Linux x86_64 musl", - "Linux x86_64", - "Minver", - "NetBSD x86_64", - "OpenBSD x86_64", - "OSX x86_64", - "Redox x86_64", - "Rust Stable", - "iOS aarch64", - "iOS x86_64", - "Illumos", -] - -# Set bors's timeout to 1 hour -# -# bors's timeout should always be at least twice as long as the test suite -# takes. This is to allow the CI provider to fast-fail a test; if one of the -# builders immediately reports a failure, then bors will move on to the next -# batch, leaving the slower builders to work through the already-doomed run and -# the next one. -# -# At the time this was written, nix's test suite took about twenty minutes to -# run. The timeout was raised to one hour to give nix room to grow and time -# for delays on Cirrus's end. -timeout_sec = 3600 diff --git a/vendor/nix-v0.23.1-patched/release.toml b/vendor/nix-v0.23.1-patched/release.toml deleted file mode 100644 index df2c9da45..000000000 --- a/vendor/nix-v0.23.1-patched/release.toml +++ /dev/null @@ -1,5 +0,0 @@ -no-dev-version = true -pre-release-replacements = [ - { file="CHANGELOG.md", search="Unreleased", replace="{{version}}" }, - { file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}" } -] diff --git a/vendor/nix-v0.23.1-patched/src/dir.rs b/vendor/nix-v0.23.1-patched/src/dir.rs deleted file mode 100644 index ed70a458a..000000000 --- a/vendor/nix-v0.23.1-patched/src/dir.rs +++ /dev/null @@ -1,246 +0,0 @@ -use crate::{Error, NixPath, Result}; -use crate::errno::Errno; -use crate::fcntl::{self, OFlag}; -use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd}; -use std::ptr; -use std::ffi; -use crate::sys; - -#[cfg(target_os = "linux")] -use libc::{dirent64 as dirent, readdir64_r as readdir_r}; - -#[cfg(not(target_os = "linux"))] -use libc::{dirent, readdir_r}; - -/// An open directory. -/// -/// This is a lower-level interface than `std::fs::ReadDir`. Notable differences: -/// * can be opened from a file descriptor (as returned by `openat`, perhaps before knowing -/// if the path represents a file or directory). -/// * implements `AsRawFd`, so it can be passed to `fstat`, `openat`, etc. -/// The file descriptor continues to be owned by the `Dir`, so callers must not keep a `RawFd` -/// after the `Dir` is dropped. -/// * can be iterated through multiple times without closing and reopening the file -/// descriptor. Each iteration rewinds when finished. -/// * returns entries for `.` (current directory) and `..` (parent directory). -/// * returns entries' names as a `CStr` (no allocation or conversion beyond whatever libc -/// does). -#[derive(Debug, Eq, Hash, PartialEq)] -pub struct Dir( - ptr::NonNull -); - -impl Dir { - /// Opens the given path as with `fcntl::open`. - pub fn open(path: &P, oflag: OFlag, - mode: sys::stat::Mode) -> Result { - let fd = fcntl::open(path, oflag, mode)?; - Dir::from_fd(fd) - } - - /// Opens the given path as with `fcntl::openat`. - pub fn openat(dirfd: RawFd, path: &P, oflag: OFlag, - mode: sys::stat::Mode) -> Result { - let fd = fcntl::openat(dirfd, path, oflag, mode)?; - Dir::from_fd(fd) - } - - /// Converts from a descriptor-based object, closing the descriptor on success or failure. - #[inline] - pub fn from(fd: F) -> Result { - Dir::from_fd(fd.into_raw_fd()) - } - - /// Converts from a file descriptor, closing it on success or failure. - pub fn from_fd(fd: RawFd) -> Result { - let d = ptr::NonNull::new(unsafe { libc::fdopendir(fd) }).ok_or_else(|| { - let e = Error::last(); - unsafe { libc::close(fd) }; - e - })?; - Ok(Dir(d)) - } - - /// Returns an iterator of `Result` which rewinds when finished. - pub fn iter(&mut self) -> Iter { - Iter(self) - } -} - -// `Dir` is not `Sync`. With the current implementation, it could be, but according to -// https://www.gnu.org/software/libc/manual/html_node/Reading_002fClosing-Directory.html, -// future versions of POSIX are likely to obsolete `readdir_r` and specify that it's unsafe to -// call `readdir` simultaneously from multiple threads. -// -// `Dir` is safe to pass from one thread to another, as it's not reference-counted. -unsafe impl Send for Dir {} - -impl AsRawFd for Dir { - fn as_raw_fd(&self) -> RawFd { - unsafe { libc::dirfd(self.0.as_ptr()) } - } -} - -impl Drop for Dir { - fn drop(&mut self) { - let e = Errno::result(unsafe { libc::closedir(self.0.as_ptr()) }); - if !std::thread::panicking() && e == Err(Errno::EBADF) { - panic!("Closing an invalid file descriptor!"); - }; - } -} - -fn next(dir: &mut Dir) -> Option> { - unsafe { - // Note: POSIX specifies that portable applications should dynamically allocate a - // buffer with room for a `d_name` field of size `pathconf(..., _PC_NAME_MAX)` plus 1 - // for the NUL byte. It doesn't look like the std library does this; it just uses - // fixed-sized buffers (and libc's dirent seems to be sized so this is appropriate). - // Probably fine here too then. - let mut ent = std::mem::MaybeUninit::::uninit(); - let mut result = ptr::null_mut(); - if let Err(e) = Errno::result( - readdir_r(dir.0.as_ptr(), ent.as_mut_ptr(), &mut result)) - { - return Some(Err(e)); - } - if result.is_null() { - return None; - } - assert_eq!(result, ent.as_mut_ptr()); - Some(Ok(Entry(ent.assume_init()))) - } -} - -#[derive(Debug, Eq, Hash, PartialEq)] -pub struct Iter<'d>(&'d mut Dir); - -impl<'d> Iterator for Iter<'d> { - type Item = Result; - - fn next(&mut self) -> Option { - next(self.0) - } -} - -impl<'d> Drop for Iter<'d> { - fn drop(&mut self) { - unsafe { libc::rewinddir((self.0).0.as_ptr()) } - } -} - -/// The return type of [Dir::into_iter] -#[derive(Debug, Eq, Hash, PartialEq)] -pub struct OwningIter(Dir); - -impl Iterator for OwningIter { - type Item = Result; - - fn next(&mut self) -> Option { - next(&mut self.0) - } -} - -impl IntoIterator for Dir { - type Item = Result; - type IntoIter = OwningIter; - - /// Creates a owning iterator, that is, one that takes ownership of the - /// `Dir`. The `Dir` cannot be used after calling this. This can be useful - /// when you have a function that both creates a `Dir` instance and returns - /// an `Iterator`. - /// - /// Example: - /// - /// ``` - /// use nix::{dir::Dir, fcntl::OFlag, sys::stat::Mode}; - /// use std::{iter::Iterator, string::String}; - /// - /// fn ls_upper(dirname: &str) -> impl Iterator { - /// let d = Dir::open(dirname, OFlag::O_DIRECTORY, Mode::S_IXUSR).unwrap(); - /// d.into_iter().map(|x| x.unwrap().file_name().as_ref().to_string_lossy().to_ascii_uppercase()) - /// } - /// ``` - fn into_iter(self) -> Self::IntoIter { - OwningIter(self) - } -} - -/// A directory entry, similar to `std::fs::DirEntry`. -/// -/// Note that unlike the std version, this may represent the `.` or `..` entries. -#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] -#[repr(transparent)] -pub struct Entry(dirent); - -#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] -pub enum Type { - Fifo, - CharacterDevice, - Directory, - BlockDevice, - File, - Symlink, - Socket, -} - -impl Entry { - /// Returns the inode number (`d_ino`) of the underlying `dirent`. - #[cfg(any(target_os = "android", - target_os = "emscripten", - target_os = "fuchsia", - target_os = "haiku", - target_os = "illumos", - target_os = "ios", - target_os = "l4re", - target_os = "linux", - target_os = "macos", - target_os = "solaris"))] - pub fn ino(&self) -> u64 { - self.0.d_ino as u64 - } - - /// Returns the inode number (`d_fileno`) of the underlying `dirent`. - #[cfg(not(any(target_os = "android", - target_os = "emscripten", - target_os = "fuchsia", - target_os = "haiku", - target_os = "illumos", - target_os = "ios", - target_os = "l4re", - target_os = "linux", - target_os = "macos", - target_os = "solaris")))] - #[allow(clippy::useless_conversion)] // Not useless on all OSes - pub fn ino(&self) -> u64 { - u64::from(self.0.d_fileno) - } - - /// Returns the bare file name of this directory entry without any other leading path component. - pub fn file_name(&self) -> &ffi::CStr { - unsafe { ::std::ffi::CStr::from_ptr(self.0.d_name.as_ptr()) } - } - - /// Returns the type of this directory entry, if known. - /// - /// See platform `readdir(3)` or `dirent(5)` manpage for when the file type is known; - /// notably, some Linux filesystems don't implement this. The caller should use `stat` or - /// `fstat` if this returns `None`. - pub fn file_type(&self) -> Option { - #[cfg(not(any(target_os = "illumos", target_os = "solaris")))] - match self.0.d_type { - libc::DT_FIFO => Some(Type::Fifo), - libc::DT_CHR => Some(Type::CharacterDevice), - libc::DT_DIR => Some(Type::Directory), - libc::DT_BLK => Some(Type::BlockDevice), - libc::DT_REG => Some(Type::File), - libc::DT_LNK => Some(Type::Symlink), - libc::DT_SOCK => Some(Type::Socket), - /* libc::DT_UNKNOWN | */ _ => None, - } - - // illumos and Solaris systems do not have the d_type member at all: - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - None - } -} diff --git a/vendor/nix-v0.23.1-patched/src/env.rs b/vendor/nix-v0.23.1-patched/src/env.rs deleted file mode 100644 index 54d759596..000000000 --- a/vendor/nix-v0.23.1-patched/src/env.rs +++ /dev/null @@ -1,66 +0,0 @@ -//! Environment variables -use cfg_if::cfg_if; -use std::fmt; - -/// Indicates that [`clearenv`] failed for some unknown reason -#[derive(Clone, Copy, Debug)] -pub struct ClearEnvError; - -impl fmt::Display for ClearEnvError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "clearenv failed") - } -} - -impl std::error::Error for ClearEnvError {} - -/// Clear the environment of all name-value pairs. -/// -/// On platforms where libc provides `clearenv()`, it will be used. libc's -/// `clearenv()` is documented to return an error code but not set errno; if the -/// return value indicates a failure, this function will return -/// [`ClearEnvError`]. -/// -/// On platforms where libc does not provide `clearenv()`, a fallback -/// implementation will be used that iterates over all environment variables and -/// removes them one-by-one. -/// -/// # Safety -/// -/// This function is not threadsafe and can cause undefined behavior in -/// combination with `std::env` or other program components that access the -/// environment. See, for example, the discussion on `std::env::remove_var`; this -/// function is a case of an "inherently unsafe non-threadsafe API" dealing with -/// the environment. -/// -/// The caller must ensure no other threads access the process environment while -/// this function executes and that no raw pointers to an element of libc's -/// `environ` is currently held. The latter is not an issue if the only other -/// environment access in the program is via `std::env`, but the requirement on -/// thread safety must still be upheld. -pub unsafe fn clearenv() -> std::result::Result<(), ClearEnvError> { - let ret; - cfg_if! { - if #[cfg(any(target_os = "fuchsia", - target_os = "wasi", - target_env = "wasi", - target_env = "uclibc", - target_os = "linux", - target_os = "android", - target_os = "emscripten"))] { - ret = libc::clearenv(); - } else { - use std::env; - for (name, _) in env::vars_os() { - env::remove_var(name); - } - ret = 0; - } - } - - if ret == 0 { - Ok(()) - } else { - Err(ClearEnvError) - } -} diff --git a/vendor/nix-v0.23.1-patched/src/errno.rs b/vendor/nix-v0.23.1-patched/src/errno.rs deleted file mode 100644 index 3da246e82..000000000 --- a/vendor/nix-v0.23.1-patched/src/errno.rs +++ /dev/null @@ -1,2723 +0,0 @@ -use cfg_if::cfg_if; -use libc::{c_int, c_void}; -use std::convert::TryFrom; -use std::{fmt, io, error}; -use crate::{Error, Result}; - -pub use self::consts::*; - -cfg_if! { - if #[cfg(any(target_os = "freebsd", - target_os = "ios", - target_os = "macos"))] { - unsafe fn errno_location() -> *mut c_int { - libc::__error() - } - } else if #[cfg(any(target_os = "android", - target_os = "netbsd", - target_os = "openbsd"))] { - unsafe fn errno_location() -> *mut c_int { - libc::__errno() - } - } else if #[cfg(any(target_os = "linux", - target_os = "redox", - target_os = "dragonfly", - target_os = "fuchsia"))] { - unsafe fn errno_location() -> *mut c_int { - libc::__errno_location() - } - } else if #[cfg(any(target_os = "illumos", target_os = "solaris"))] { - unsafe fn errno_location() -> *mut c_int { - libc::___errno() - } - } -} - -/// Sets the platform-specific errno to no-error -fn clear() { - // Safe because errno is a thread-local variable - unsafe { - *errno_location() = 0; - } -} - -/// Returns the platform-specific value of errno -pub fn errno() -> i32 { - unsafe { - (*errno_location()) as i32 - } -} - -impl Errno { - /// Convert this `Error` to an [`Errno`](enum.Errno.html). - /// - /// # Example - /// - /// ``` - /// # use nix::Error; - /// # use nix::errno::Errno; - /// let e = Error::from(Errno::EPERM); - /// assert_eq!(Some(Errno::EPERM), e.as_errno()); - /// ``` - #[deprecated( - since = "0.22.0", - note = "It's a no-op now; just delete it." - )] - pub const fn as_errno(self) -> Option { - Some(self) - } - - /// Create a nix Error from a given errno - #[deprecated( - since = "0.22.0", - note = "It's a no-op now; just delete it." - )] - #[allow(clippy::wrong_self_convention)] // False positive - pub fn from_errno(errno: Errno) -> Error { - errno - } - - /// Create a new invalid argument error (`EINVAL`) - #[deprecated( - since = "0.22.0", - note = "Use Errno::EINVAL instead" - )] - pub const fn invalid_argument() -> Error { - Errno::EINVAL - } - - pub fn last() -> Self { - last() - } - - pub fn desc(self) -> &'static str { - desc(self) - } - - pub const fn from_i32(err: i32) -> Errno { - from_i32(err) - } - - pub fn clear() { - clear() - } - - /// Returns `Ok(value)` if it does not contain the sentinel value. This - /// should not be used when `-1` is not the errno sentinel value. - #[inline] - pub fn result>(value: S) -> Result { - if value == S::sentinel() { - Err(Self::last()) - } else { - Ok(value) - } - } - - /// Backwards compatibility hack for Nix <= 0.21.0 users - /// - /// In older versions of Nix, `Error::Sys` was an enum variant. Now it's a - /// function, which is compatible with most of the former use cases of the - /// enum variant. But you should use `Error(Errno::...)` instead. - #[deprecated( - since = "0.22.0", - note = "Use Errno::... instead" - )] - #[allow(non_snake_case)] - #[inline] - pub const fn Sys(errno: Errno) -> Error { - errno - } -} - -/// The sentinel value indicates that a function failed and more detailed -/// information about the error can be found in `errno` -pub trait ErrnoSentinel: Sized { - fn sentinel() -> Self; -} - -impl ErrnoSentinel for isize { - fn sentinel() -> Self { -1 } -} - -impl ErrnoSentinel for i32 { - fn sentinel() -> Self { -1 } -} - -impl ErrnoSentinel for i64 { - fn sentinel() -> Self { -1 } -} - -impl ErrnoSentinel for *mut c_void { - fn sentinel() -> Self { -1isize as *mut c_void } -} - -impl ErrnoSentinel for libc::sighandler_t { - fn sentinel() -> Self { libc::SIG_ERR } -} - -impl error::Error for Errno {} - -impl fmt::Display for Errno { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}: {}", self, self.desc()) - } -} - -impl From for io::Error { - fn from(err: Errno) -> Self { - io::Error::from_raw_os_error(err as i32) - } -} - -impl TryFrom for Errno { - type Error = io::Error; - - fn try_from(ioerror: io::Error) -> std::result::Result { - ioerror.raw_os_error() - .map(Errno::from_i32) - .ok_or(ioerror) - } -} - -fn last() -> Errno { - Errno::from_i32(errno()) -} - -fn desc(errno: Errno) -> &'static str { - use self::Errno::*; - match errno { - UnknownErrno => "Unknown errno", - EPERM => "Operation not permitted", - ENOENT => "No such file or directory", - ESRCH => "No such process", - EINTR => "Interrupted system call", - EIO => "I/O error", - ENXIO => "No such device or address", - E2BIG => "Argument list too long", - ENOEXEC => "Exec format error", - EBADF => "Bad file number", - ECHILD => "No child processes", - EAGAIN => "Try again", - ENOMEM => "Out of memory", - EACCES => "Permission denied", - EFAULT => "Bad address", - ENOTBLK => "Block device required", - EBUSY => "Device or resource busy", - EEXIST => "File exists", - EXDEV => "Cross-device link", - ENODEV => "No such device", - ENOTDIR => "Not a directory", - EISDIR => "Is a directory", - EINVAL => "Invalid argument", - ENFILE => "File table overflow", - EMFILE => "Too many open files", - ENOTTY => "Not a typewriter", - ETXTBSY => "Text file busy", - EFBIG => "File too large", - ENOSPC => "No space left on device", - ESPIPE => "Illegal seek", - EROFS => "Read-only file system", - EMLINK => "Too many links", - EPIPE => "Broken pipe", - EDOM => "Math argument out of domain of func", - ERANGE => "Math result not representable", - EDEADLK => "Resource deadlock would occur", - ENAMETOOLONG => "File name too long", - ENOLCK => "No record locks available", - ENOSYS => "Function not implemented", - ENOTEMPTY => "Directory not empty", - ELOOP => "Too many symbolic links encountered", - ENOMSG => "No message of desired type", - EIDRM => "Identifier removed", - EINPROGRESS => "Operation now in progress", - EALREADY => "Operation already in progress", - ENOTSOCK => "Socket operation on non-socket", - EDESTADDRREQ => "Destination address required", - EMSGSIZE => "Message too long", - EPROTOTYPE => "Protocol wrong type for socket", - ENOPROTOOPT => "Protocol not available", - EPROTONOSUPPORT => "Protocol not supported", - ESOCKTNOSUPPORT => "Socket type not supported", - EPFNOSUPPORT => "Protocol family not supported", - EAFNOSUPPORT => "Address family not supported by protocol", - EADDRINUSE => "Address already in use", - EADDRNOTAVAIL => "Cannot assign requested address", - ENETDOWN => "Network is down", - ENETUNREACH => "Network is unreachable", - ENETRESET => "Network dropped connection because of reset", - ECONNABORTED => "Software caused connection abort", - ECONNRESET => "Connection reset by peer", - ENOBUFS => "No buffer space available", - EISCONN => "Transport endpoint is already connected", - ENOTCONN => "Transport endpoint is not connected", - ESHUTDOWN => "Cannot send after transport endpoint shutdown", - ETOOMANYREFS => "Too many references: cannot splice", - ETIMEDOUT => "Connection timed out", - ECONNREFUSED => "Connection refused", - EHOSTDOWN => "Host is down", - EHOSTUNREACH => "No route to host", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ECHRNG => "Channel number out of range", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EL2NSYNC => "Level 2 not synchronized", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EL3HLT => "Level 3 halted", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EL3RST => "Level 3 reset", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ELNRNG => "Link number out of range", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EUNATCH => "Protocol driver not attached", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ENOCSI => "No CSI structure available", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EL2HLT => "Level 2 halted", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EBADE => "Invalid exchange", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EBADR => "Invalid request descriptor", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EXFULL => "Exchange full", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ENOANO => "No anode", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EBADRQC => "Invalid request code", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EBADSLT => "Invalid slot", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EBFONT => "Bad font file format", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ENOSTR => "Device not a stream", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ENODATA => "No data available", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ETIME => "Timer expired", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ENOSR => "Out of streams resources", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ENONET => "Machine is not on the network", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ENOPKG => "Package not installed", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EREMOTE => "Object is remote", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ENOLINK => "Link has been severed", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EADV => "Advertise error", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ESRMNT => "Srmount error", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ECOMM => "Communication error on send", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EPROTO => "Protocol error", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EMULTIHOP => "Multihop attempted", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] - EDOTDOT => "RFS specific error", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] - EBADMSG => "Not a data message", - - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - EBADMSG => "Trying to read unreadable message", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] - EOVERFLOW => "Value too large for defined data type", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ENOTUNIQ => "Name not unique on network", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EBADFD => "File descriptor in bad state", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EREMCHG => "Remote address changed", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ELIBACC => "Can not access a needed shared library", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ELIBBAD => "Accessing a corrupted shared library", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ELIBSCN => ".lib section in a.out corrupted", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ELIBMAX => "Attempting to link in too many shared libraries", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ELIBEXEC => "Cannot exec a shared library directly", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia", target_os = "openbsd"))] - EILSEQ => "Illegal byte sequence", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ERESTART => "Interrupted system call should be restarted", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ESTRPIPE => "Streams pipe error", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - EUSERS => "Too many users", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia", target_os = "netbsd", - target_os = "redox"))] - EOPNOTSUPP => "Operation not supported on transport endpoint", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] - ESTALE => "Stale file handle", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] - EUCLEAN => "Structure needs cleaning", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] - ENOTNAM => "Not a XENIX named type file", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] - ENAVAIL => "No XENIX semaphores available", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] - EISNAM => "Is a named type file", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] - EREMOTEIO => "Remote I/O error", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] - EDQUOT => "Quota exceeded", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia", target_os = "openbsd", - target_os = "dragonfly"))] - ENOMEDIUM => "No medium found", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia", target_os = "openbsd"))] - EMEDIUMTYPE => "Wrong medium type", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "illumos", target_os = "solaris", - target_os = "fuchsia"))] - ECANCELED => "Operation canceled", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] - ENOKEY => "Required key not available", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] - EKEYEXPIRED => "Key has expired", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] - EKEYREVOKED => "Key has been revoked", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] - EKEYREJECTED => "Key was rejected by service", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] - EOWNERDEAD => "Owner died", - - #[cfg(any( target_os = "illumos", target_os = "solaris"))] - EOWNERDEAD => "Process died with lock", - - #[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] - ENOTRECOVERABLE => "State not recoverable", - - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - ENOTRECOVERABLE => "Lock is not recoverable", - - #[cfg(any(all(target_os = "linux", not(target_arch="mips")), - target_os = "fuchsia"))] - ERFKILL => "Operation not possible due to RF-kill", - - #[cfg(any(all(target_os = "linux", not(target_arch="mips")), - target_os = "fuchsia"))] - EHWPOISON => "Memory page has hardware error", - - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - EDOOFUS => "Programming error", - - #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "redox"))] - EMULTIHOP => "Multihop attempted", - - #[cfg(any(target_os = "freebsd", target_os = "dragonfly", - target_os = "redox"))] - ENOLINK => "Link has been severed", - - #[cfg(target_os = "freebsd")] - ENOTCAPABLE => "Capabilities insufficient", - - #[cfg(target_os = "freebsd")] - ECAPMODE => "Not permitted in capability mode", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd"))] - ENEEDAUTH => "Need authenticator", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd", - target_os = "redox", target_os = "illumos", - target_os = "solaris"))] - EOVERFLOW => "Value too large to be stored in data type", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "netbsd", target_os = "redox"))] - EILSEQ => "Illegal byte sequence", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd"))] - ENOATTR => "Attribute not found", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd", - target_os = "redox"))] - EBADMSG => "Bad message", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd", - target_os = "redox"))] - EPROTO => "Protocol error", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "ios", target_os = "openbsd"))] - ENOTRECOVERABLE => "State not recoverable", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "ios", target_os = "openbsd"))] - EOWNERDEAD => "Previous owner died", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd", - target_os = "illumos", target_os = "solaris"))] - ENOTSUP => "Operation not supported", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd"))] - EPROCLIM => "Too many processes", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd", - target_os = "redox"))] - EUSERS => "Too many users", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd", - target_os = "redox", target_os = "illumos", - target_os = "solaris"))] - EDQUOT => "Disc quota exceeded", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd", - target_os = "redox", target_os = "illumos", - target_os = "solaris"))] - ESTALE => "Stale NFS file handle", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd", - target_os = "redox"))] - EREMOTE => "Too many levels of remote in path", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd"))] - EBADRPC => "RPC struct is bad", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd"))] - ERPCMISMATCH => "RPC version wrong", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd"))] - EPROGUNAVAIL => "RPC prog. not avail", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd"))] - EPROGMISMATCH => "Program version wrong", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd"))] - EPROCUNAVAIL => "Bad procedure for program", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd"))] - EFTYPE => "Inappropriate file type or format", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd"))] - EAUTH => "Authentication error", - - #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly", target_os = "ios", - target_os = "openbsd", target_os = "netbsd", - target_os = "redox"))] - ECANCELED => "Operation canceled", - - #[cfg(any(target_os = "macos", target_os = "ios"))] - EPWROFF => "Device power is off", - - #[cfg(any(target_os = "macos", target_os = "ios"))] - EDEVERR => "Device error, e.g. paper out", - - #[cfg(any(target_os = "macos", target_os = "ios"))] - EBADEXEC => "Bad executable", - - #[cfg(any(target_os = "macos", target_os = "ios"))] - EBADARCH => "Bad CPU type in executable", - - #[cfg(any(target_os = "macos", target_os = "ios"))] - ESHLIBVERS => "Shared library version mismatch", - - #[cfg(any(target_os = "macos", target_os = "ios"))] - EBADMACHO => "Malformed Macho file", - - #[cfg(any(target_os = "macos", target_os = "ios", - target_os = "netbsd"))] - EMULTIHOP => "Reserved", - - #[cfg(any(target_os = "macos", target_os = "ios", - target_os = "netbsd", target_os = "redox"))] - ENODATA => "No message available on STREAM", - - #[cfg(any(target_os = "macos", target_os = "ios", - target_os = "netbsd"))] - ENOLINK => "Reserved", - - #[cfg(any(target_os = "macos", target_os = "ios", - target_os = "netbsd", target_os = "redox"))] - ENOSR => "No STREAM resources", - - #[cfg(any(target_os = "macos", target_os = "ios", - target_os = "netbsd", target_os = "redox"))] - ENOSTR => "Not a STREAM", - - #[cfg(any(target_os = "macos", target_os = "ios", - target_os = "netbsd", target_os = "redox"))] - ETIME => "STREAM ioctl timeout", - - #[cfg(any(target_os = "macos", target_os = "ios", - target_os = "illumos", target_os = "solaris"))] - EOPNOTSUPP => "Operation not supported on socket", - - #[cfg(any(target_os = "macos", target_os = "ios"))] - ENOPOLICY => "No such policy registered", - - #[cfg(any(target_os = "macos", target_os = "ios"))] - EQFULL => "Interface output queue is full", - - #[cfg(target_os = "openbsd")] - EOPNOTSUPP => "Operation not supported", - - #[cfg(target_os = "openbsd")] - EIPSEC => "IPsec processing failure", - - #[cfg(target_os = "dragonfly")] - EASYNC => "Async", - - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - EDEADLOCK => "Resource deadlock would occur", - - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - ELOCKUNMAPPED => "Locked lock was unmapped", - - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - ENOTACTIVE => "Facility is not active", - } -} - -#[cfg(any(target_os = "linux", target_os = "android", - target_os = "fuchsia"))] -mod consts { - #[derive(Clone, Copy, Debug, Eq, PartialEq)] - #[repr(i32)] - #[non_exhaustive] - pub enum Errno { - UnknownErrno = 0, - EPERM = libc::EPERM, - ENOENT = libc::ENOENT, - ESRCH = libc::ESRCH, - EINTR = libc::EINTR, - EIO = libc::EIO, - ENXIO = libc::ENXIO, - E2BIG = libc::E2BIG, - ENOEXEC = libc::ENOEXEC, - EBADF = libc::EBADF, - ECHILD = libc::ECHILD, - EAGAIN = libc::EAGAIN, - ENOMEM = libc::ENOMEM, - EACCES = libc::EACCES, - EFAULT = libc::EFAULT, - ENOTBLK = libc::ENOTBLK, - EBUSY = libc::EBUSY, - EEXIST = libc::EEXIST, - EXDEV = libc::EXDEV, - ENODEV = libc::ENODEV, - ENOTDIR = libc::ENOTDIR, - EISDIR = libc::EISDIR, - EINVAL = libc::EINVAL, - ENFILE = libc::ENFILE, - EMFILE = libc::EMFILE, - ENOTTY = libc::ENOTTY, - ETXTBSY = libc::ETXTBSY, - EFBIG = libc::EFBIG, - ENOSPC = libc::ENOSPC, - ESPIPE = libc::ESPIPE, - EROFS = libc::EROFS, - EMLINK = libc::EMLINK, - EPIPE = libc::EPIPE, - EDOM = libc::EDOM, - ERANGE = libc::ERANGE, - EDEADLK = libc::EDEADLK, - ENAMETOOLONG = libc::ENAMETOOLONG, - ENOLCK = libc::ENOLCK, - ENOSYS = libc::ENOSYS, - ENOTEMPTY = libc::ENOTEMPTY, - ELOOP = libc::ELOOP, - ENOMSG = libc::ENOMSG, - EIDRM = libc::EIDRM, - ECHRNG = libc::ECHRNG, - EL2NSYNC = libc::EL2NSYNC, - EL3HLT = libc::EL3HLT, - EL3RST = libc::EL3RST, - ELNRNG = libc::ELNRNG, - EUNATCH = libc::EUNATCH, - ENOCSI = libc::ENOCSI, - EL2HLT = libc::EL2HLT, - EBADE = libc::EBADE, - EBADR = libc::EBADR, - EXFULL = libc::EXFULL, - ENOANO = libc::ENOANO, - EBADRQC = libc::EBADRQC, - EBADSLT = libc::EBADSLT, - EBFONT = libc::EBFONT, - ENOSTR = libc::ENOSTR, - ENODATA = libc::ENODATA, - ETIME = libc::ETIME, - ENOSR = libc::ENOSR, - ENONET = libc::ENONET, - ENOPKG = libc::ENOPKG, - EREMOTE = libc::EREMOTE, - ENOLINK = libc::ENOLINK, - EADV = libc::EADV, - ESRMNT = libc::ESRMNT, - ECOMM = libc::ECOMM, - EPROTO = libc::EPROTO, - EMULTIHOP = libc::EMULTIHOP, - EDOTDOT = libc::EDOTDOT, - EBADMSG = libc::EBADMSG, - EOVERFLOW = libc::EOVERFLOW, - ENOTUNIQ = libc::ENOTUNIQ, - EBADFD = libc::EBADFD, - EREMCHG = libc::EREMCHG, - ELIBACC = libc::ELIBACC, - ELIBBAD = libc::ELIBBAD, - ELIBSCN = libc::ELIBSCN, - ELIBMAX = libc::ELIBMAX, - ELIBEXEC = libc::ELIBEXEC, - EILSEQ = libc::EILSEQ, - ERESTART = libc::ERESTART, - ESTRPIPE = libc::ESTRPIPE, - EUSERS = libc::EUSERS, - ENOTSOCK = libc::ENOTSOCK, - EDESTADDRREQ = libc::EDESTADDRREQ, - EMSGSIZE = libc::EMSGSIZE, - EPROTOTYPE = libc::EPROTOTYPE, - ENOPROTOOPT = libc::ENOPROTOOPT, - EPROTONOSUPPORT = libc::EPROTONOSUPPORT, - ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT, - EOPNOTSUPP = libc::EOPNOTSUPP, - EPFNOSUPPORT = libc::EPFNOSUPPORT, - EAFNOSUPPORT = libc::EAFNOSUPPORT, - EADDRINUSE = libc::EADDRINUSE, - EADDRNOTAVAIL = libc::EADDRNOTAVAIL, - ENETDOWN = libc::ENETDOWN, - ENETUNREACH = libc::ENETUNREACH, - ENETRESET = libc::ENETRESET, - ECONNABORTED = libc::ECONNABORTED, - ECONNRESET = libc::ECONNRESET, - ENOBUFS = libc::ENOBUFS, - EISCONN = libc::EISCONN, - ENOTCONN = libc::ENOTCONN, - ESHUTDOWN = libc::ESHUTDOWN, - ETOOMANYREFS = libc::ETOOMANYREFS, - ETIMEDOUT = libc::ETIMEDOUT, - ECONNREFUSED = libc::ECONNREFUSED, - EHOSTDOWN = libc::EHOSTDOWN, - EHOSTUNREACH = libc::EHOSTUNREACH, - EALREADY = libc::EALREADY, - EINPROGRESS = libc::EINPROGRESS, - ESTALE = libc::ESTALE, - EUCLEAN = libc::EUCLEAN, - ENOTNAM = libc::ENOTNAM, - ENAVAIL = libc::ENAVAIL, - EISNAM = libc::EISNAM, - EREMOTEIO = libc::EREMOTEIO, - EDQUOT = libc::EDQUOT, - ENOMEDIUM = libc::ENOMEDIUM, - EMEDIUMTYPE = libc::EMEDIUMTYPE, - ECANCELED = libc::ECANCELED, - ENOKEY = libc::ENOKEY, - EKEYEXPIRED = libc::EKEYEXPIRED, - EKEYREVOKED = libc::EKEYREVOKED, - EKEYREJECTED = libc::EKEYREJECTED, - EOWNERDEAD = libc::EOWNERDEAD, - ENOTRECOVERABLE = libc::ENOTRECOVERABLE, - #[cfg(not(any(target_os = "android", target_arch="mips")))] - ERFKILL = libc::ERFKILL, - #[cfg(not(any(target_os = "android", target_arch="mips")))] - EHWPOISON = libc::EHWPOISON, - } - - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::EWOULDBLOCK instead" - )] - pub const EWOULDBLOCK: Errno = Errno::EAGAIN; - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::EDEADLOCK instead" - )] - pub const EDEADLOCK: Errno = Errno::EDEADLK; - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::ENOTSUP instead" - )] - pub const ENOTSUP: Errno = Errno::EOPNOTSUPP; - - impl Errno { - pub const EWOULDBLOCK: Errno = Errno::EAGAIN; - pub const EDEADLOCK: Errno = Errno::EDEADLK; - pub const ENOTSUP: Errno = Errno::EOPNOTSUPP; - } - - pub const fn from_i32(e: i32) -> Errno { - use self::Errno::*; - - match e { - libc::EPERM => EPERM, - libc::ENOENT => ENOENT, - libc::ESRCH => ESRCH, - libc::EINTR => EINTR, - libc::EIO => EIO, - libc::ENXIO => ENXIO, - libc::E2BIG => E2BIG, - libc::ENOEXEC => ENOEXEC, - libc::EBADF => EBADF, - libc::ECHILD => ECHILD, - libc::EAGAIN => EAGAIN, - libc::ENOMEM => ENOMEM, - libc::EACCES => EACCES, - libc::EFAULT => EFAULT, - libc::ENOTBLK => ENOTBLK, - libc::EBUSY => EBUSY, - libc::EEXIST => EEXIST, - libc::EXDEV => EXDEV, - libc::ENODEV => ENODEV, - libc::ENOTDIR => ENOTDIR, - libc::EISDIR => EISDIR, - libc::EINVAL => EINVAL, - libc::ENFILE => ENFILE, - libc::EMFILE => EMFILE, - libc::ENOTTY => ENOTTY, - libc::ETXTBSY => ETXTBSY, - libc::EFBIG => EFBIG, - libc::ENOSPC => ENOSPC, - libc::ESPIPE => ESPIPE, - libc::EROFS => EROFS, - libc::EMLINK => EMLINK, - libc::EPIPE => EPIPE, - libc::EDOM => EDOM, - libc::ERANGE => ERANGE, - libc::EDEADLK => EDEADLK, - libc::ENAMETOOLONG => ENAMETOOLONG, - libc::ENOLCK => ENOLCK, - libc::ENOSYS => ENOSYS, - libc::ENOTEMPTY => ENOTEMPTY, - libc::ELOOP => ELOOP, - libc::ENOMSG => ENOMSG, - libc::EIDRM => EIDRM, - libc::ECHRNG => ECHRNG, - libc::EL2NSYNC => EL2NSYNC, - libc::EL3HLT => EL3HLT, - libc::EL3RST => EL3RST, - libc::ELNRNG => ELNRNG, - libc::EUNATCH => EUNATCH, - libc::ENOCSI => ENOCSI, - libc::EL2HLT => EL2HLT, - libc::EBADE => EBADE, - libc::EBADR => EBADR, - libc::EXFULL => EXFULL, - libc::ENOANO => ENOANO, - libc::EBADRQC => EBADRQC, - libc::EBADSLT => EBADSLT, - libc::EBFONT => EBFONT, - libc::ENOSTR => ENOSTR, - libc::ENODATA => ENODATA, - libc::ETIME => ETIME, - libc::ENOSR => ENOSR, - libc::ENONET => ENONET, - libc::ENOPKG => ENOPKG, - libc::EREMOTE => EREMOTE, - libc::ENOLINK => ENOLINK, - libc::EADV => EADV, - libc::ESRMNT => ESRMNT, - libc::ECOMM => ECOMM, - libc::EPROTO => EPROTO, - libc::EMULTIHOP => EMULTIHOP, - libc::EDOTDOT => EDOTDOT, - libc::EBADMSG => EBADMSG, - libc::EOVERFLOW => EOVERFLOW, - libc::ENOTUNIQ => ENOTUNIQ, - libc::EBADFD => EBADFD, - libc::EREMCHG => EREMCHG, - libc::ELIBACC => ELIBACC, - libc::ELIBBAD => ELIBBAD, - libc::ELIBSCN => ELIBSCN, - libc::ELIBMAX => ELIBMAX, - libc::ELIBEXEC => ELIBEXEC, - libc::EILSEQ => EILSEQ, - libc::ERESTART => ERESTART, - libc::ESTRPIPE => ESTRPIPE, - libc::EUSERS => EUSERS, - libc::ENOTSOCK => ENOTSOCK, - libc::EDESTADDRREQ => EDESTADDRREQ, - libc::EMSGSIZE => EMSGSIZE, - libc::EPROTOTYPE => EPROTOTYPE, - libc::ENOPROTOOPT => ENOPROTOOPT, - libc::EPROTONOSUPPORT => EPROTONOSUPPORT, - libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT, - libc::EOPNOTSUPP => EOPNOTSUPP, - libc::EPFNOSUPPORT => EPFNOSUPPORT, - libc::EAFNOSUPPORT => EAFNOSUPPORT, - libc::EADDRINUSE => EADDRINUSE, - libc::EADDRNOTAVAIL => EADDRNOTAVAIL, - libc::ENETDOWN => ENETDOWN, - libc::ENETUNREACH => ENETUNREACH, - libc::ENETRESET => ENETRESET, - libc::ECONNABORTED => ECONNABORTED, - libc::ECONNRESET => ECONNRESET, - libc::ENOBUFS => ENOBUFS, - libc::EISCONN => EISCONN, - libc::ENOTCONN => ENOTCONN, - libc::ESHUTDOWN => ESHUTDOWN, - libc::ETOOMANYREFS => ETOOMANYREFS, - libc::ETIMEDOUT => ETIMEDOUT, - libc::ECONNREFUSED => ECONNREFUSED, - libc::EHOSTDOWN => EHOSTDOWN, - libc::EHOSTUNREACH => EHOSTUNREACH, - libc::EALREADY => EALREADY, - libc::EINPROGRESS => EINPROGRESS, - libc::ESTALE => ESTALE, - libc::EUCLEAN => EUCLEAN, - libc::ENOTNAM => ENOTNAM, - libc::ENAVAIL => ENAVAIL, - libc::EISNAM => EISNAM, - libc::EREMOTEIO => EREMOTEIO, - libc::EDQUOT => EDQUOT, - libc::ENOMEDIUM => ENOMEDIUM, - libc::EMEDIUMTYPE => EMEDIUMTYPE, - libc::ECANCELED => ECANCELED, - libc::ENOKEY => ENOKEY, - libc::EKEYEXPIRED => EKEYEXPIRED, - libc::EKEYREVOKED => EKEYREVOKED, - libc::EKEYREJECTED => EKEYREJECTED, - libc::EOWNERDEAD => EOWNERDEAD, - libc::ENOTRECOVERABLE => ENOTRECOVERABLE, - #[cfg(not(any(target_os = "android", target_arch="mips")))] - libc::ERFKILL => ERFKILL, - #[cfg(not(any(target_os = "android", target_arch="mips")))] - libc::EHWPOISON => EHWPOISON, - _ => UnknownErrno, - } - } -} - -#[cfg(any(target_os = "macos", target_os = "ios"))] -mod consts { - #[derive(Clone, Copy, Debug, Eq, PartialEq)] - #[repr(i32)] - #[non_exhaustive] - pub enum Errno { - UnknownErrno = 0, - EPERM = libc::EPERM, - ENOENT = libc::ENOENT, - ESRCH = libc::ESRCH, - EINTR = libc::EINTR, - EIO = libc::EIO, - ENXIO = libc::ENXIO, - E2BIG = libc::E2BIG, - ENOEXEC = libc::ENOEXEC, - EBADF = libc::EBADF, - ECHILD = libc::ECHILD, - EDEADLK = libc::EDEADLK, - ENOMEM = libc::ENOMEM, - EACCES = libc::EACCES, - EFAULT = libc::EFAULT, - ENOTBLK = libc::ENOTBLK, - EBUSY = libc::EBUSY, - EEXIST = libc::EEXIST, - EXDEV = libc::EXDEV, - ENODEV = libc::ENODEV, - ENOTDIR = libc::ENOTDIR, - EISDIR = libc::EISDIR, - EINVAL = libc::EINVAL, - ENFILE = libc::ENFILE, - EMFILE = libc::EMFILE, - ENOTTY = libc::ENOTTY, - ETXTBSY = libc::ETXTBSY, - EFBIG = libc::EFBIG, - ENOSPC = libc::ENOSPC, - ESPIPE = libc::ESPIPE, - EROFS = libc::EROFS, - EMLINK = libc::EMLINK, - EPIPE = libc::EPIPE, - EDOM = libc::EDOM, - ERANGE = libc::ERANGE, - EAGAIN = libc::EAGAIN, - EINPROGRESS = libc::EINPROGRESS, - EALREADY = libc::EALREADY, - ENOTSOCK = libc::ENOTSOCK, - EDESTADDRREQ = libc::EDESTADDRREQ, - EMSGSIZE = libc::EMSGSIZE, - EPROTOTYPE = libc::EPROTOTYPE, - ENOPROTOOPT = libc::ENOPROTOOPT, - EPROTONOSUPPORT = libc::EPROTONOSUPPORT, - ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT, - ENOTSUP = libc::ENOTSUP, - EPFNOSUPPORT = libc::EPFNOSUPPORT, - EAFNOSUPPORT = libc::EAFNOSUPPORT, - EADDRINUSE = libc::EADDRINUSE, - EADDRNOTAVAIL = libc::EADDRNOTAVAIL, - ENETDOWN = libc::ENETDOWN, - ENETUNREACH = libc::ENETUNREACH, - ENETRESET = libc::ENETRESET, - ECONNABORTED = libc::ECONNABORTED, - ECONNRESET = libc::ECONNRESET, - ENOBUFS = libc::ENOBUFS, - EISCONN = libc::EISCONN, - ENOTCONN = libc::ENOTCONN, - ESHUTDOWN = libc::ESHUTDOWN, - ETOOMANYREFS = libc::ETOOMANYREFS, - ETIMEDOUT = libc::ETIMEDOUT, - ECONNREFUSED = libc::ECONNREFUSED, - ELOOP = libc::ELOOP, - ENAMETOOLONG = libc::ENAMETOOLONG, - EHOSTDOWN = libc::EHOSTDOWN, - EHOSTUNREACH = libc::EHOSTUNREACH, - ENOTEMPTY = libc::ENOTEMPTY, - EPROCLIM = libc::EPROCLIM, - EUSERS = libc::EUSERS, - EDQUOT = libc::EDQUOT, - ESTALE = libc::ESTALE, - EREMOTE = libc::EREMOTE, - EBADRPC = libc::EBADRPC, - ERPCMISMATCH = libc::ERPCMISMATCH, - EPROGUNAVAIL = libc::EPROGUNAVAIL, - EPROGMISMATCH = libc::EPROGMISMATCH, - EPROCUNAVAIL = libc::EPROCUNAVAIL, - ENOLCK = libc::ENOLCK, - ENOSYS = libc::ENOSYS, - EFTYPE = libc::EFTYPE, - EAUTH = libc::EAUTH, - ENEEDAUTH = libc::ENEEDAUTH, - EPWROFF = libc::EPWROFF, - EDEVERR = libc::EDEVERR, - EOVERFLOW = libc::EOVERFLOW, - EBADEXEC = libc::EBADEXEC, - EBADARCH = libc::EBADARCH, - ESHLIBVERS = libc::ESHLIBVERS, - EBADMACHO = libc::EBADMACHO, - ECANCELED = libc::ECANCELED, - EIDRM = libc::EIDRM, - ENOMSG = libc::ENOMSG, - EILSEQ = libc::EILSEQ, - ENOATTR = libc::ENOATTR, - EBADMSG = libc::EBADMSG, - EMULTIHOP = libc::EMULTIHOP, - ENODATA = libc::ENODATA, - ENOLINK = libc::ENOLINK, - ENOSR = libc::ENOSR, - ENOSTR = libc::ENOSTR, - EPROTO = libc::EPROTO, - ETIME = libc::ETIME, - EOPNOTSUPP = libc::EOPNOTSUPP, - ENOPOLICY = libc::ENOPOLICY, - ENOTRECOVERABLE = libc::ENOTRECOVERABLE, - EOWNERDEAD = libc::EOWNERDEAD, - EQFULL = libc::EQFULL, - } - - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::ELAST instead" - )] - pub const ELAST: Errno = Errno::EQFULL; - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::EWOULDBLOCK instead" - )] - pub const EWOULDBLOCK: Errno = Errno::EAGAIN; - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::EDEADLOCK instead" - )] - pub const EDEADLOCK: Errno = Errno::EDEADLK; - - impl Errno { - pub const ELAST: Errno = Errno::EQFULL; - pub const EWOULDBLOCK: Errno = Errno::EAGAIN; - pub const EDEADLOCK: Errno = Errno::EDEADLK; - } - - pub const fn from_i32(e: i32) -> Errno { - use self::Errno::*; - - match e { - libc::EPERM => EPERM, - libc::ENOENT => ENOENT, - libc::ESRCH => ESRCH, - libc::EINTR => EINTR, - libc::EIO => EIO, - libc::ENXIO => ENXIO, - libc::E2BIG => E2BIG, - libc::ENOEXEC => ENOEXEC, - libc::EBADF => EBADF, - libc::ECHILD => ECHILD, - libc::EDEADLK => EDEADLK, - libc::ENOMEM => ENOMEM, - libc::EACCES => EACCES, - libc::EFAULT => EFAULT, - libc::ENOTBLK => ENOTBLK, - libc::EBUSY => EBUSY, - libc::EEXIST => EEXIST, - libc::EXDEV => EXDEV, - libc::ENODEV => ENODEV, - libc::ENOTDIR => ENOTDIR, - libc::EISDIR => EISDIR, - libc::EINVAL => EINVAL, - libc::ENFILE => ENFILE, - libc::EMFILE => EMFILE, - libc::ENOTTY => ENOTTY, - libc::ETXTBSY => ETXTBSY, - libc::EFBIG => EFBIG, - libc::ENOSPC => ENOSPC, - libc::ESPIPE => ESPIPE, - libc::EROFS => EROFS, - libc::EMLINK => EMLINK, - libc::EPIPE => EPIPE, - libc::EDOM => EDOM, - libc::ERANGE => ERANGE, - libc::EAGAIN => EAGAIN, - libc::EINPROGRESS => EINPROGRESS, - libc::EALREADY => EALREADY, - libc::ENOTSOCK => ENOTSOCK, - libc::EDESTADDRREQ => EDESTADDRREQ, - libc::EMSGSIZE => EMSGSIZE, - libc::EPROTOTYPE => EPROTOTYPE, - libc::ENOPROTOOPT => ENOPROTOOPT, - libc::EPROTONOSUPPORT => EPROTONOSUPPORT, - libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT, - libc::ENOTSUP => ENOTSUP, - libc::EPFNOSUPPORT => EPFNOSUPPORT, - libc::EAFNOSUPPORT => EAFNOSUPPORT, - libc::EADDRINUSE => EADDRINUSE, - libc::EADDRNOTAVAIL => EADDRNOTAVAIL, - libc::ENETDOWN => ENETDOWN, - libc::ENETUNREACH => ENETUNREACH, - libc::ENETRESET => ENETRESET, - libc::ECONNABORTED => ECONNABORTED, - libc::ECONNRESET => ECONNRESET, - libc::ENOBUFS => ENOBUFS, - libc::EISCONN => EISCONN, - libc::ENOTCONN => ENOTCONN, - libc::ESHUTDOWN => ESHUTDOWN, - libc::ETOOMANYREFS => ETOOMANYREFS, - libc::ETIMEDOUT => ETIMEDOUT, - libc::ECONNREFUSED => ECONNREFUSED, - libc::ELOOP => ELOOP, - libc::ENAMETOOLONG => ENAMETOOLONG, - libc::EHOSTDOWN => EHOSTDOWN, - libc::EHOSTUNREACH => EHOSTUNREACH, - libc::ENOTEMPTY => ENOTEMPTY, - libc::EPROCLIM => EPROCLIM, - libc::EUSERS => EUSERS, - libc::EDQUOT => EDQUOT, - libc::ESTALE => ESTALE, - libc::EREMOTE => EREMOTE, - libc::EBADRPC => EBADRPC, - libc::ERPCMISMATCH => ERPCMISMATCH, - libc::EPROGUNAVAIL => EPROGUNAVAIL, - libc::EPROGMISMATCH => EPROGMISMATCH, - libc::EPROCUNAVAIL => EPROCUNAVAIL, - libc::ENOLCK => ENOLCK, - libc::ENOSYS => ENOSYS, - libc::EFTYPE => EFTYPE, - libc::EAUTH => EAUTH, - libc::ENEEDAUTH => ENEEDAUTH, - libc::EPWROFF => EPWROFF, - libc::EDEVERR => EDEVERR, - libc::EOVERFLOW => EOVERFLOW, - libc::EBADEXEC => EBADEXEC, - libc::EBADARCH => EBADARCH, - libc::ESHLIBVERS => ESHLIBVERS, - libc::EBADMACHO => EBADMACHO, - libc::ECANCELED => ECANCELED, - libc::EIDRM => EIDRM, - libc::ENOMSG => ENOMSG, - libc::EILSEQ => EILSEQ, - libc::ENOATTR => ENOATTR, - libc::EBADMSG => EBADMSG, - libc::EMULTIHOP => EMULTIHOP, - libc::ENODATA => ENODATA, - libc::ENOLINK => ENOLINK, - libc::ENOSR => ENOSR, - libc::ENOSTR => ENOSTR, - libc::EPROTO => EPROTO, - libc::ETIME => ETIME, - libc::EOPNOTSUPP => EOPNOTSUPP, - libc::ENOPOLICY => ENOPOLICY, - libc::ENOTRECOVERABLE => ENOTRECOVERABLE, - libc::EOWNERDEAD => EOWNERDEAD, - libc::EQFULL => EQFULL, - _ => UnknownErrno, - } - } -} - -#[cfg(target_os = "freebsd")] -mod consts { - #[derive(Clone, Copy, Debug, Eq, PartialEq)] - #[repr(i32)] - #[non_exhaustive] - pub enum Errno { - UnknownErrno = 0, - EPERM = libc::EPERM, - ENOENT = libc::ENOENT, - ESRCH = libc::ESRCH, - EINTR = libc::EINTR, - EIO = libc::EIO, - ENXIO = libc::ENXIO, - E2BIG = libc::E2BIG, - ENOEXEC = libc::ENOEXEC, - EBADF = libc::EBADF, - ECHILD = libc::ECHILD, - EDEADLK = libc::EDEADLK, - ENOMEM = libc::ENOMEM, - EACCES = libc::EACCES, - EFAULT = libc::EFAULT, - ENOTBLK = libc::ENOTBLK, - EBUSY = libc::EBUSY, - EEXIST = libc::EEXIST, - EXDEV = libc::EXDEV, - ENODEV = libc::ENODEV, - ENOTDIR = libc::ENOTDIR, - EISDIR = libc::EISDIR, - EINVAL = libc::EINVAL, - ENFILE = libc::ENFILE, - EMFILE = libc::EMFILE, - ENOTTY = libc::ENOTTY, - ETXTBSY = libc::ETXTBSY, - EFBIG = libc::EFBIG, - ENOSPC = libc::ENOSPC, - ESPIPE = libc::ESPIPE, - EROFS = libc::EROFS, - EMLINK = libc::EMLINK, - EPIPE = libc::EPIPE, - EDOM = libc::EDOM, - ERANGE = libc::ERANGE, - EAGAIN = libc::EAGAIN, - EINPROGRESS = libc::EINPROGRESS, - EALREADY = libc::EALREADY, - ENOTSOCK = libc::ENOTSOCK, - EDESTADDRREQ = libc::EDESTADDRREQ, - EMSGSIZE = libc::EMSGSIZE, - EPROTOTYPE = libc::EPROTOTYPE, - ENOPROTOOPT = libc::ENOPROTOOPT, - EPROTONOSUPPORT = libc::EPROTONOSUPPORT, - ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT, - ENOTSUP = libc::ENOTSUP, - EPFNOSUPPORT = libc::EPFNOSUPPORT, - EAFNOSUPPORT = libc::EAFNOSUPPORT, - EADDRINUSE = libc::EADDRINUSE, - EADDRNOTAVAIL = libc::EADDRNOTAVAIL, - ENETDOWN = libc::ENETDOWN, - ENETUNREACH = libc::ENETUNREACH, - ENETRESET = libc::ENETRESET, - ECONNABORTED = libc::ECONNABORTED, - ECONNRESET = libc::ECONNRESET, - ENOBUFS = libc::ENOBUFS, - EISCONN = libc::EISCONN, - ENOTCONN = libc::ENOTCONN, - ESHUTDOWN = libc::ESHUTDOWN, - ETOOMANYREFS = libc::ETOOMANYREFS, - ETIMEDOUT = libc::ETIMEDOUT, - ECONNREFUSED = libc::ECONNREFUSED, - ELOOP = libc::ELOOP, - ENAMETOOLONG = libc::ENAMETOOLONG, - EHOSTDOWN = libc::EHOSTDOWN, - EHOSTUNREACH = libc::EHOSTUNREACH, - ENOTEMPTY = libc::ENOTEMPTY, - EPROCLIM = libc::EPROCLIM, - EUSERS = libc::EUSERS, - EDQUOT = libc::EDQUOT, - ESTALE = libc::ESTALE, - EREMOTE = libc::EREMOTE, - EBADRPC = libc::EBADRPC, - ERPCMISMATCH = libc::ERPCMISMATCH, - EPROGUNAVAIL = libc::EPROGUNAVAIL, - EPROGMISMATCH = libc::EPROGMISMATCH, - EPROCUNAVAIL = libc::EPROCUNAVAIL, - ENOLCK = libc::ENOLCK, - ENOSYS = libc::ENOSYS, - EFTYPE = libc::EFTYPE, - EAUTH = libc::EAUTH, - ENEEDAUTH = libc::ENEEDAUTH, - EIDRM = libc::EIDRM, - ENOMSG = libc::ENOMSG, - EOVERFLOW = libc::EOVERFLOW, - ECANCELED = libc::ECANCELED, - EILSEQ = libc::EILSEQ, - ENOATTR = libc::ENOATTR, - EDOOFUS = libc::EDOOFUS, - EBADMSG = libc::EBADMSG, - EMULTIHOP = libc::EMULTIHOP, - ENOLINK = libc::ENOLINK, - EPROTO = libc::EPROTO, - ENOTCAPABLE = libc::ENOTCAPABLE, - ECAPMODE = libc::ECAPMODE, - ENOTRECOVERABLE = libc::ENOTRECOVERABLE, - EOWNERDEAD = libc::EOWNERDEAD, - } - - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::ELAST instead" - )] - pub const ELAST: Errno = Errno::EOWNERDEAD; - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::EWOULDBLOCK instead" - )] - pub const EWOULDBLOCK: Errno = Errno::EAGAIN; - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::EDEADLOCK instead" - )] - pub const EDEADLOCK: Errno = Errno::EDEADLK; - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::EOPNOTSUPP instead" - )] - pub const EOPNOTSUPP: Errno = Errno::ENOTSUP; - - impl Errno { - pub const ELAST: Errno = Errno::EOWNERDEAD; - pub const EWOULDBLOCK: Errno = Errno::EAGAIN; - pub const EDEADLOCK: Errno = Errno::EDEADLK; - pub const EOPNOTSUPP: Errno = Errno::ENOTSUP; - } - - pub const fn from_i32(e: i32) -> Errno { - use self::Errno::*; - - match e { - libc::EPERM => EPERM, - libc::ENOENT => ENOENT, - libc::ESRCH => ESRCH, - libc::EINTR => EINTR, - libc::EIO => EIO, - libc::ENXIO => ENXIO, - libc::E2BIG => E2BIG, - libc::ENOEXEC => ENOEXEC, - libc::EBADF => EBADF, - libc::ECHILD => ECHILD, - libc::EDEADLK => EDEADLK, - libc::ENOMEM => ENOMEM, - libc::EACCES => EACCES, - libc::EFAULT => EFAULT, - libc::ENOTBLK => ENOTBLK, - libc::EBUSY => EBUSY, - libc::EEXIST => EEXIST, - libc::EXDEV => EXDEV, - libc::ENODEV => ENODEV, - libc::ENOTDIR => ENOTDIR, - libc::EISDIR => EISDIR, - libc::EINVAL => EINVAL, - libc::ENFILE => ENFILE, - libc::EMFILE => EMFILE, - libc::ENOTTY => ENOTTY, - libc::ETXTBSY => ETXTBSY, - libc::EFBIG => EFBIG, - libc::ENOSPC => ENOSPC, - libc::ESPIPE => ESPIPE, - libc::EROFS => EROFS, - libc::EMLINK => EMLINK, - libc::EPIPE => EPIPE, - libc::EDOM => EDOM, - libc::ERANGE => ERANGE, - libc::EAGAIN => EAGAIN, - libc::EINPROGRESS => EINPROGRESS, - libc::EALREADY => EALREADY, - libc::ENOTSOCK => ENOTSOCK, - libc::EDESTADDRREQ => EDESTADDRREQ, - libc::EMSGSIZE => EMSGSIZE, - libc::EPROTOTYPE => EPROTOTYPE, - libc::ENOPROTOOPT => ENOPROTOOPT, - libc::EPROTONOSUPPORT => EPROTONOSUPPORT, - libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT, - libc::ENOTSUP => ENOTSUP, - libc::EPFNOSUPPORT => EPFNOSUPPORT, - libc::EAFNOSUPPORT => EAFNOSUPPORT, - libc::EADDRINUSE => EADDRINUSE, - libc::EADDRNOTAVAIL => EADDRNOTAVAIL, - libc::ENETDOWN => ENETDOWN, - libc::ENETUNREACH => ENETUNREACH, - libc::ENETRESET => ENETRESET, - libc::ECONNABORTED => ECONNABORTED, - libc::ECONNRESET => ECONNRESET, - libc::ENOBUFS => ENOBUFS, - libc::EISCONN => EISCONN, - libc::ENOTCONN => ENOTCONN, - libc::ESHUTDOWN => ESHUTDOWN, - libc::ETOOMANYREFS => ETOOMANYREFS, - libc::ETIMEDOUT => ETIMEDOUT, - libc::ECONNREFUSED => ECONNREFUSED, - libc::ELOOP => ELOOP, - libc::ENAMETOOLONG => ENAMETOOLONG, - libc::EHOSTDOWN => EHOSTDOWN, - libc::EHOSTUNREACH => EHOSTUNREACH, - libc::ENOTEMPTY => ENOTEMPTY, - libc::EPROCLIM => EPROCLIM, - libc::EUSERS => EUSERS, - libc::EDQUOT => EDQUOT, - libc::ESTALE => ESTALE, - libc::EREMOTE => EREMOTE, - libc::EBADRPC => EBADRPC, - libc::ERPCMISMATCH => ERPCMISMATCH, - libc::EPROGUNAVAIL => EPROGUNAVAIL, - libc::EPROGMISMATCH => EPROGMISMATCH, - libc::EPROCUNAVAIL => EPROCUNAVAIL, - libc::ENOLCK => ENOLCK, - libc::ENOSYS => ENOSYS, - libc::EFTYPE => EFTYPE, - libc::EAUTH => EAUTH, - libc::ENEEDAUTH => ENEEDAUTH, - libc::EIDRM => EIDRM, - libc::ENOMSG => ENOMSG, - libc::EOVERFLOW => EOVERFLOW, - libc::ECANCELED => ECANCELED, - libc::EILSEQ => EILSEQ, - libc::ENOATTR => ENOATTR, - libc::EDOOFUS => EDOOFUS, - libc::EBADMSG => EBADMSG, - libc::EMULTIHOP => EMULTIHOP, - libc::ENOLINK => ENOLINK, - libc::EPROTO => EPROTO, - libc::ENOTCAPABLE => ENOTCAPABLE, - libc::ECAPMODE => ECAPMODE, - libc::ENOTRECOVERABLE => ENOTRECOVERABLE, - libc::EOWNERDEAD => EOWNERDEAD, - _ => UnknownErrno, - } - } -} - - -#[cfg(target_os = "dragonfly")] -mod consts { - #[derive(Clone, Copy, Debug, Eq, PartialEq)] - #[repr(i32)] - #[non_exhaustive] - pub enum Errno { - UnknownErrno = 0, - EPERM = libc::EPERM, - ENOENT = libc::ENOENT, - ESRCH = libc::ESRCH, - EINTR = libc::EINTR, - EIO = libc::EIO, - ENXIO = libc::ENXIO, - E2BIG = libc::E2BIG, - ENOEXEC = libc::ENOEXEC, - EBADF = libc::EBADF, - ECHILD = libc::ECHILD, - EDEADLK = libc::EDEADLK, - ENOMEM = libc::ENOMEM, - EACCES = libc::EACCES, - EFAULT = libc::EFAULT, - ENOTBLK = libc::ENOTBLK, - EBUSY = libc::EBUSY, - EEXIST = libc::EEXIST, - EXDEV = libc::EXDEV, - ENODEV = libc::ENODEV, - ENOTDIR = libc::ENOTDIR, - EISDIR = libc::EISDIR, - EINVAL = libc::EINVAL, - ENFILE = libc::ENFILE, - EMFILE = libc::EMFILE, - ENOTTY = libc::ENOTTY, - ETXTBSY = libc::ETXTBSY, - EFBIG = libc::EFBIG, - ENOSPC = libc::ENOSPC, - ESPIPE = libc::ESPIPE, - EROFS = libc::EROFS, - EMLINK = libc::EMLINK, - EPIPE = libc::EPIPE, - EDOM = libc::EDOM, - ERANGE = libc::ERANGE, - EAGAIN = libc::EAGAIN, - EINPROGRESS = libc::EINPROGRESS, - EALREADY = libc::EALREADY, - ENOTSOCK = libc::ENOTSOCK, - EDESTADDRREQ = libc::EDESTADDRREQ, - EMSGSIZE = libc::EMSGSIZE, - EPROTOTYPE = libc::EPROTOTYPE, - ENOPROTOOPT = libc::ENOPROTOOPT, - EPROTONOSUPPORT = libc::EPROTONOSUPPORT, - ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT, - ENOTSUP = libc::ENOTSUP, - EPFNOSUPPORT = libc::EPFNOSUPPORT, - EAFNOSUPPORT = libc::EAFNOSUPPORT, - EADDRINUSE = libc::EADDRINUSE, - EADDRNOTAVAIL = libc::EADDRNOTAVAIL, - ENETDOWN = libc::ENETDOWN, - ENETUNREACH = libc::ENETUNREACH, - ENETRESET = libc::ENETRESET, - ECONNABORTED = libc::ECONNABORTED, - ECONNRESET = libc::ECONNRESET, - ENOBUFS = libc::ENOBUFS, - EISCONN = libc::EISCONN, - ENOTCONN = libc::ENOTCONN, - ESHUTDOWN = libc::ESHUTDOWN, - ETOOMANYREFS = libc::ETOOMANYREFS, - ETIMEDOUT = libc::ETIMEDOUT, - ECONNREFUSED = libc::ECONNREFUSED, - ELOOP = libc::ELOOP, - ENAMETOOLONG = libc::ENAMETOOLONG, - EHOSTDOWN = libc::EHOSTDOWN, - EHOSTUNREACH = libc::EHOSTUNREACH, - ENOTEMPTY = libc::ENOTEMPTY, - EPROCLIM = libc::EPROCLIM, - EUSERS = libc::EUSERS, - EDQUOT = libc::EDQUOT, - ESTALE = libc::ESTALE, - EREMOTE = libc::EREMOTE, - EBADRPC = libc::EBADRPC, - ERPCMISMATCH = libc::ERPCMISMATCH, - EPROGUNAVAIL = libc::EPROGUNAVAIL, - EPROGMISMATCH = libc::EPROGMISMATCH, - EPROCUNAVAIL = libc::EPROCUNAVAIL, - ENOLCK = libc::ENOLCK, - ENOSYS = libc::ENOSYS, - EFTYPE = libc::EFTYPE, - EAUTH = libc::EAUTH, - ENEEDAUTH = libc::ENEEDAUTH, - EIDRM = libc::EIDRM, - ENOMSG = libc::ENOMSG, - EOVERFLOW = libc::EOVERFLOW, - ECANCELED = libc::ECANCELED, - EILSEQ = libc::EILSEQ, - ENOATTR = libc::ENOATTR, - EDOOFUS = libc::EDOOFUS, - EBADMSG = libc::EBADMSG, - EMULTIHOP = libc::EMULTIHOP, - ENOLINK = libc::ENOLINK, - EPROTO = libc::EPROTO, - ENOMEDIUM = libc::ENOMEDIUM, - EASYNC = libc::EASYNC, - } - - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::ELAST instead" - )] - pub const ELAST: Errno = Errno::EASYNC; - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::EWOULDBLOCK instead" - )] - pub const EWOULDBLOCK: Errno = Errno::EAGAIN; - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::EDEADLOCK instead" - )] - pub const EDEADLOCK: Errno = Errno::EDEADLK; - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::EOPNOTSUPP instead" - )] - pub const EOPNOTSUPP: Errno = Errno::ENOTSUP; - - impl Errno { - pub const ELAST: Errno = Errno::EASYNC; - pub const EWOULDBLOCK: Errno = Errno::EAGAIN; - pub const EDEADLOCK: Errno = Errno::EDEADLK; - pub const EOPNOTSUPP: Errno = Errno::ENOTSUP; - } - - pub const fn from_i32(e: i32) -> Errno { - use self::Errno::*; - - match e { - libc::EPERM => EPERM, - libc::ENOENT => ENOENT, - libc::ESRCH => ESRCH, - libc::EINTR => EINTR, - libc::EIO => EIO, - libc::ENXIO => ENXIO, - libc::E2BIG => E2BIG, - libc::ENOEXEC => ENOEXEC, - libc::EBADF => EBADF, - libc::ECHILD => ECHILD, - libc::EDEADLK => EDEADLK, - libc::ENOMEM => ENOMEM, - libc::EACCES => EACCES, - libc::EFAULT => EFAULT, - libc::ENOTBLK => ENOTBLK, - libc::EBUSY => EBUSY, - libc::EEXIST => EEXIST, - libc::EXDEV => EXDEV, - libc::ENODEV => ENODEV, - libc::ENOTDIR => ENOTDIR, - libc::EISDIR=> EISDIR, - libc::EINVAL => EINVAL, - libc::ENFILE => ENFILE, - libc::EMFILE => EMFILE, - libc::ENOTTY => ENOTTY, - libc::ETXTBSY => ETXTBSY, - libc::EFBIG => EFBIG, - libc::ENOSPC => ENOSPC, - libc::ESPIPE => ESPIPE, - libc::EROFS => EROFS, - libc::EMLINK => EMLINK, - libc::EPIPE => EPIPE, - libc::EDOM => EDOM, - libc::ERANGE => ERANGE, - libc::EAGAIN => EAGAIN, - libc::EINPROGRESS => EINPROGRESS, - libc::EALREADY => EALREADY, - libc::ENOTSOCK => ENOTSOCK, - libc::EDESTADDRREQ => EDESTADDRREQ, - libc::EMSGSIZE => EMSGSIZE, - libc::EPROTOTYPE => EPROTOTYPE, - libc::ENOPROTOOPT => ENOPROTOOPT, - libc::EPROTONOSUPPORT => EPROTONOSUPPORT, - libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT, - libc::ENOTSUP => ENOTSUP, - libc::EPFNOSUPPORT => EPFNOSUPPORT, - libc::EAFNOSUPPORT => EAFNOSUPPORT, - libc::EADDRINUSE => EADDRINUSE, - libc::EADDRNOTAVAIL => EADDRNOTAVAIL, - libc::ENETDOWN => ENETDOWN, - libc::ENETUNREACH => ENETUNREACH, - libc::ENETRESET => ENETRESET, - libc::ECONNABORTED => ECONNABORTED, - libc::ECONNRESET => ECONNRESET, - libc::ENOBUFS => ENOBUFS, - libc::EISCONN => EISCONN, - libc::ENOTCONN => ENOTCONN, - libc::ESHUTDOWN => ESHUTDOWN, - libc::ETOOMANYREFS => ETOOMANYREFS, - libc::ETIMEDOUT => ETIMEDOUT, - libc::ECONNREFUSED => ECONNREFUSED, - libc::ELOOP => ELOOP, - libc::ENAMETOOLONG => ENAMETOOLONG, - libc::EHOSTDOWN => EHOSTDOWN, - libc::EHOSTUNREACH => EHOSTUNREACH, - libc::ENOTEMPTY => ENOTEMPTY, - libc::EPROCLIM => EPROCLIM, - libc::EUSERS => EUSERS, - libc::EDQUOT => EDQUOT, - libc::ESTALE => ESTALE, - libc::EREMOTE => EREMOTE, - libc::EBADRPC => EBADRPC, - libc::ERPCMISMATCH => ERPCMISMATCH, - libc::EPROGUNAVAIL => EPROGUNAVAIL, - libc::EPROGMISMATCH => EPROGMISMATCH, - libc::EPROCUNAVAIL => EPROCUNAVAIL, - libc::ENOLCK => ENOLCK, - libc::ENOSYS => ENOSYS, - libc::EFTYPE => EFTYPE, - libc::EAUTH => EAUTH, - libc::ENEEDAUTH => ENEEDAUTH, - libc::EIDRM => EIDRM, - libc::ENOMSG => ENOMSG, - libc::EOVERFLOW => EOVERFLOW, - libc::ECANCELED => ECANCELED, - libc::EILSEQ => EILSEQ, - libc::ENOATTR => ENOATTR, - libc::EDOOFUS => EDOOFUS, - libc::EBADMSG => EBADMSG, - libc::EMULTIHOP => EMULTIHOP, - libc::ENOLINK => ENOLINK, - libc::EPROTO => EPROTO, - libc::ENOMEDIUM => ENOMEDIUM, - libc::EASYNC => EASYNC, - _ => UnknownErrno, - } - } -} - - -#[cfg(target_os = "openbsd")] -mod consts { - #[derive(Clone, Copy, Debug, Eq, PartialEq)] - #[repr(i32)] - #[non_exhaustive] - pub enum Errno { - UnknownErrno = 0, - EPERM = libc::EPERM, - ENOENT = libc::ENOENT, - ESRCH = libc::ESRCH, - EINTR = libc::EINTR, - EIO = libc::EIO, - ENXIO = libc::ENXIO, - E2BIG = libc::E2BIG, - ENOEXEC = libc::ENOEXEC, - EBADF = libc::EBADF, - ECHILD = libc::ECHILD, - EDEADLK = libc::EDEADLK, - ENOMEM = libc::ENOMEM, - EACCES = libc::EACCES, - EFAULT = libc::EFAULT, - ENOTBLK = libc::ENOTBLK, - EBUSY = libc::EBUSY, - EEXIST = libc::EEXIST, - EXDEV = libc::EXDEV, - ENODEV = libc::ENODEV, - ENOTDIR = libc::ENOTDIR, - EISDIR = libc::EISDIR, - EINVAL = libc::EINVAL, - ENFILE = libc::ENFILE, - EMFILE = libc::EMFILE, - ENOTTY = libc::ENOTTY, - ETXTBSY = libc::ETXTBSY, - EFBIG = libc::EFBIG, - ENOSPC = libc::ENOSPC, - ESPIPE = libc::ESPIPE, - EROFS = libc::EROFS, - EMLINK = libc::EMLINK, - EPIPE = libc::EPIPE, - EDOM = libc::EDOM, - ERANGE = libc::ERANGE, - EAGAIN = libc::EAGAIN, - EINPROGRESS = libc::EINPROGRESS, - EALREADY = libc::EALREADY, - ENOTSOCK = libc::ENOTSOCK, - EDESTADDRREQ = libc::EDESTADDRREQ, - EMSGSIZE = libc::EMSGSIZE, - EPROTOTYPE = libc::EPROTOTYPE, - ENOPROTOOPT = libc::ENOPROTOOPT, - EPROTONOSUPPORT = libc::EPROTONOSUPPORT, - ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT, - EOPNOTSUPP = libc::EOPNOTSUPP, - EPFNOSUPPORT = libc::EPFNOSUPPORT, - EAFNOSUPPORT = libc::EAFNOSUPPORT, - EADDRINUSE = libc::EADDRINUSE, - EADDRNOTAVAIL = libc::EADDRNOTAVAIL, - ENETDOWN = libc::ENETDOWN, - ENETUNREACH = libc::ENETUNREACH, - ENETRESET = libc::ENETRESET, - ECONNABORTED = libc::ECONNABORTED, - ECONNRESET = libc::ECONNRESET, - ENOBUFS = libc::ENOBUFS, - EISCONN = libc::EISCONN, - ENOTCONN = libc::ENOTCONN, - ESHUTDOWN = libc::ESHUTDOWN, - ETOOMANYREFS = libc::ETOOMANYREFS, - ETIMEDOUT = libc::ETIMEDOUT, - ECONNREFUSED = libc::ECONNREFUSED, - ELOOP = libc::ELOOP, - ENAMETOOLONG = libc::ENAMETOOLONG, - EHOSTDOWN = libc::EHOSTDOWN, - EHOSTUNREACH = libc::EHOSTUNREACH, - ENOTEMPTY = libc::ENOTEMPTY, - EPROCLIM = libc::EPROCLIM, - EUSERS = libc::EUSERS, - EDQUOT = libc::EDQUOT, - ESTALE = libc::ESTALE, - EREMOTE = libc::EREMOTE, - EBADRPC = libc::EBADRPC, - ERPCMISMATCH = libc::ERPCMISMATCH, - EPROGUNAVAIL = libc::EPROGUNAVAIL, - EPROGMISMATCH = libc::EPROGMISMATCH, - EPROCUNAVAIL = libc::EPROCUNAVAIL, - ENOLCK = libc::ENOLCK, - ENOSYS = libc::ENOSYS, - EFTYPE = libc::EFTYPE, - EAUTH = libc::EAUTH, - ENEEDAUTH = libc::ENEEDAUTH, - EIPSEC = libc::EIPSEC, - ENOATTR = libc::ENOATTR, - EILSEQ = libc::EILSEQ, - ENOMEDIUM = libc::ENOMEDIUM, - EMEDIUMTYPE = libc::EMEDIUMTYPE, - EOVERFLOW = libc::EOVERFLOW, - ECANCELED = libc::ECANCELED, - EIDRM = libc::EIDRM, - ENOMSG = libc::ENOMSG, - ENOTSUP = libc::ENOTSUP, - EBADMSG = libc::EBADMSG, - ENOTRECOVERABLE = libc::ENOTRECOVERABLE, - EOWNERDEAD = libc::EOWNERDEAD, - EPROTO = libc::EPROTO, - } - - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::ELAST instead" - )] - pub const ELAST: Errno = Errno::ENOTSUP; - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::EWOULDBLOCK instead" - )] - pub const EWOULDBLOCK: Errno = Errno::EAGAIN; - - impl Errno { - pub const ELAST: Errno = Errno::ENOTSUP; - pub const EWOULDBLOCK: Errno = Errno::EAGAIN; - } - - pub const fn from_i32(e: i32) -> Errno { - use self::Errno::*; - - match e { - libc::EPERM => EPERM, - libc::ENOENT => ENOENT, - libc::ESRCH => ESRCH, - libc::EINTR => EINTR, - libc::EIO => EIO, - libc::ENXIO => ENXIO, - libc::E2BIG => E2BIG, - libc::ENOEXEC => ENOEXEC, - libc::EBADF => EBADF, - libc::ECHILD => ECHILD, - libc::EDEADLK => EDEADLK, - libc::ENOMEM => ENOMEM, - libc::EACCES => EACCES, - libc::EFAULT => EFAULT, - libc::ENOTBLK => ENOTBLK, - libc::EBUSY => EBUSY, - libc::EEXIST => EEXIST, - libc::EXDEV => EXDEV, - libc::ENODEV => ENODEV, - libc::ENOTDIR => ENOTDIR, - libc::EISDIR => EISDIR, - libc::EINVAL => EINVAL, - libc::ENFILE => ENFILE, - libc::EMFILE => EMFILE, - libc::ENOTTY => ENOTTY, - libc::ETXTBSY => ETXTBSY, - libc::EFBIG => EFBIG, - libc::ENOSPC => ENOSPC, - libc::ESPIPE => ESPIPE, - libc::EROFS => EROFS, - libc::EMLINK => EMLINK, - libc::EPIPE => EPIPE, - libc::EDOM => EDOM, - libc::ERANGE => ERANGE, - libc::EAGAIN => EAGAIN, - libc::EINPROGRESS => EINPROGRESS, - libc::EALREADY => EALREADY, - libc::ENOTSOCK => ENOTSOCK, - libc::EDESTADDRREQ => EDESTADDRREQ, - libc::EMSGSIZE => EMSGSIZE, - libc::EPROTOTYPE => EPROTOTYPE, - libc::ENOPROTOOPT => ENOPROTOOPT, - libc::EPROTONOSUPPORT => EPROTONOSUPPORT, - libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT, - libc::EOPNOTSUPP => EOPNOTSUPP, - libc::EPFNOSUPPORT => EPFNOSUPPORT, - libc::EAFNOSUPPORT => EAFNOSUPPORT, - libc::EADDRINUSE => EADDRINUSE, - libc::EADDRNOTAVAIL => EADDRNOTAVAIL, - libc::ENETDOWN => ENETDOWN, - libc::ENETUNREACH => ENETUNREACH, - libc::ENETRESET => ENETRESET, - libc::ECONNABORTED => ECONNABORTED, - libc::ECONNRESET => ECONNRESET, - libc::ENOBUFS => ENOBUFS, - libc::EISCONN => EISCONN, - libc::ENOTCONN => ENOTCONN, - libc::ESHUTDOWN => ESHUTDOWN, - libc::ETOOMANYREFS => ETOOMANYREFS, - libc::ETIMEDOUT => ETIMEDOUT, - libc::ECONNREFUSED => ECONNREFUSED, - libc::ELOOP => ELOOP, - libc::ENAMETOOLONG => ENAMETOOLONG, - libc::EHOSTDOWN => EHOSTDOWN, - libc::EHOSTUNREACH => EHOSTUNREACH, - libc::ENOTEMPTY => ENOTEMPTY, - libc::EPROCLIM => EPROCLIM, - libc::EUSERS => EUSERS, - libc::EDQUOT => EDQUOT, - libc::ESTALE => ESTALE, - libc::EREMOTE => EREMOTE, - libc::EBADRPC => EBADRPC, - libc::ERPCMISMATCH => ERPCMISMATCH, - libc::EPROGUNAVAIL => EPROGUNAVAIL, - libc::EPROGMISMATCH => EPROGMISMATCH, - libc::EPROCUNAVAIL => EPROCUNAVAIL, - libc::ENOLCK => ENOLCK, - libc::ENOSYS => ENOSYS, - libc::EFTYPE => EFTYPE, - libc::EAUTH => EAUTH, - libc::ENEEDAUTH => ENEEDAUTH, - libc::EIPSEC => EIPSEC, - libc::ENOATTR => ENOATTR, - libc::EILSEQ => EILSEQ, - libc::ENOMEDIUM => ENOMEDIUM, - libc::EMEDIUMTYPE => EMEDIUMTYPE, - libc::EOVERFLOW => EOVERFLOW, - libc::ECANCELED => ECANCELED, - libc::EIDRM => EIDRM, - libc::ENOMSG => ENOMSG, - libc::ENOTSUP => ENOTSUP, - libc::EBADMSG => EBADMSG, - libc::ENOTRECOVERABLE => ENOTRECOVERABLE, - libc::EOWNERDEAD => EOWNERDEAD, - libc::EPROTO => EPROTO, - _ => UnknownErrno, - } - } -} - -#[cfg(target_os = "netbsd")] -mod consts { - #[derive(Clone, Copy, Debug, Eq, PartialEq)] - #[repr(i32)] - #[non_exhaustive] - pub enum Errno { - UnknownErrno = 0, - EPERM = libc::EPERM, - ENOENT = libc::ENOENT, - ESRCH = libc::ESRCH, - EINTR = libc::EINTR, - EIO = libc::EIO, - ENXIO = libc::ENXIO, - E2BIG = libc::E2BIG, - ENOEXEC = libc::ENOEXEC, - EBADF = libc::EBADF, - ECHILD = libc::ECHILD, - EDEADLK = libc::EDEADLK, - ENOMEM = libc::ENOMEM, - EACCES = libc::EACCES, - EFAULT = libc::EFAULT, - ENOTBLK = libc::ENOTBLK, - EBUSY = libc::EBUSY, - EEXIST = libc::EEXIST, - EXDEV = libc::EXDEV, - ENODEV = libc::ENODEV, - ENOTDIR = libc::ENOTDIR, - EISDIR = libc::EISDIR, - EINVAL = libc::EINVAL, - ENFILE = libc::ENFILE, - EMFILE = libc::EMFILE, - ENOTTY = libc::ENOTTY, - ETXTBSY = libc::ETXTBSY, - EFBIG = libc::EFBIG, - ENOSPC = libc::ENOSPC, - ESPIPE = libc::ESPIPE, - EROFS = libc::EROFS, - EMLINK = libc::EMLINK, - EPIPE = libc::EPIPE, - EDOM = libc::EDOM, - ERANGE = libc::ERANGE, - EAGAIN = libc::EAGAIN, - EINPROGRESS = libc::EINPROGRESS, - EALREADY = libc::EALREADY, - ENOTSOCK = libc::ENOTSOCK, - EDESTADDRREQ = libc::EDESTADDRREQ, - EMSGSIZE = libc::EMSGSIZE, - EPROTOTYPE = libc::EPROTOTYPE, - ENOPROTOOPT = libc::ENOPROTOOPT, - EPROTONOSUPPORT = libc::EPROTONOSUPPORT, - ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT, - EOPNOTSUPP = libc::EOPNOTSUPP, - EPFNOSUPPORT = libc::EPFNOSUPPORT, - EAFNOSUPPORT = libc::EAFNOSUPPORT, - EADDRINUSE = libc::EADDRINUSE, - EADDRNOTAVAIL = libc::EADDRNOTAVAIL, - ENETDOWN = libc::ENETDOWN, - ENETUNREACH = libc::ENETUNREACH, - ENETRESET = libc::ENETRESET, - ECONNABORTED = libc::ECONNABORTED, - ECONNRESET = libc::ECONNRESET, - ENOBUFS = libc::ENOBUFS, - EISCONN = libc::EISCONN, - ENOTCONN = libc::ENOTCONN, - ESHUTDOWN = libc::ESHUTDOWN, - ETOOMANYREFS = libc::ETOOMANYREFS, - ETIMEDOUT = libc::ETIMEDOUT, - ECONNREFUSED = libc::ECONNREFUSED, - ELOOP = libc::ELOOP, - ENAMETOOLONG = libc::ENAMETOOLONG, - EHOSTDOWN = libc::EHOSTDOWN, - EHOSTUNREACH = libc::EHOSTUNREACH, - ENOTEMPTY = libc::ENOTEMPTY, - EPROCLIM = libc::EPROCLIM, - EUSERS = libc::EUSERS, - EDQUOT = libc::EDQUOT, - ESTALE = libc::ESTALE, - EREMOTE = libc::EREMOTE, - EBADRPC = libc::EBADRPC, - ERPCMISMATCH = libc::ERPCMISMATCH, - EPROGUNAVAIL = libc::EPROGUNAVAIL, - EPROGMISMATCH = libc::EPROGMISMATCH, - EPROCUNAVAIL = libc::EPROCUNAVAIL, - ENOLCK = libc::ENOLCK, - ENOSYS = libc::ENOSYS, - EFTYPE = libc::EFTYPE, - EAUTH = libc::EAUTH, - ENEEDAUTH = libc::ENEEDAUTH, - EIDRM = libc::EIDRM, - ENOMSG = libc::ENOMSG, - EOVERFLOW = libc::EOVERFLOW, - EILSEQ = libc::EILSEQ, - ENOTSUP = libc::ENOTSUP, - ECANCELED = libc::ECANCELED, - EBADMSG = libc::EBADMSG, - ENODATA = libc::ENODATA, - ENOSR = libc::ENOSR, - ENOSTR = libc::ENOSTR, - ETIME = libc::ETIME, - ENOATTR = libc::ENOATTR, - EMULTIHOP = libc::EMULTIHOP, - ENOLINK = libc::ENOLINK, - EPROTO = libc::EPROTO, - } - - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::ELAST instead" - )] - pub const ELAST: Errno = Errno::ENOTSUP; - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::EWOULDBLOCK instead" - )] - pub const EWOULDBLOCK: Errno = Errno::EAGAIN; - - impl Errno { - pub const ELAST: Errno = Errno::ENOTSUP; - pub const EWOULDBLOCK: Errno = Errno::EAGAIN; - } - - pub const fn from_i32(e: i32) -> Errno { - use self::Errno::*; - - match e { - libc::EPERM => EPERM, - libc::ENOENT => ENOENT, - libc::ESRCH => ESRCH, - libc::EINTR => EINTR, - libc::EIO => EIO, - libc::ENXIO => ENXIO, - libc::E2BIG => E2BIG, - libc::ENOEXEC => ENOEXEC, - libc::EBADF => EBADF, - libc::ECHILD => ECHILD, - libc::EDEADLK => EDEADLK, - libc::ENOMEM => ENOMEM, - libc::EACCES => EACCES, - libc::EFAULT => EFAULT, - libc::ENOTBLK => ENOTBLK, - libc::EBUSY => EBUSY, - libc::EEXIST => EEXIST, - libc::EXDEV => EXDEV, - libc::ENODEV => ENODEV, - libc::ENOTDIR => ENOTDIR, - libc::EISDIR => EISDIR, - libc::EINVAL => EINVAL, - libc::ENFILE => ENFILE, - libc::EMFILE => EMFILE, - libc::ENOTTY => ENOTTY, - libc::ETXTBSY => ETXTBSY, - libc::EFBIG => EFBIG, - libc::ENOSPC => ENOSPC, - libc::ESPIPE => ESPIPE, - libc::EROFS => EROFS, - libc::EMLINK => EMLINK, - libc::EPIPE => EPIPE, - libc::EDOM => EDOM, - libc::ERANGE => ERANGE, - libc::EAGAIN => EAGAIN, - libc::EINPROGRESS => EINPROGRESS, - libc::EALREADY => EALREADY, - libc::ENOTSOCK => ENOTSOCK, - libc::EDESTADDRREQ => EDESTADDRREQ, - libc::EMSGSIZE => EMSGSIZE, - libc::EPROTOTYPE => EPROTOTYPE, - libc::ENOPROTOOPT => ENOPROTOOPT, - libc::EPROTONOSUPPORT => EPROTONOSUPPORT, - libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT, - libc::EOPNOTSUPP => EOPNOTSUPP, - libc::EPFNOSUPPORT => EPFNOSUPPORT, - libc::EAFNOSUPPORT => EAFNOSUPPORT, - libc::EADDRINUSE => EADDRINUSE, - libc::EADDRNOTAVAIL => EADDRNOTAVAIL, - libc::ENETDOWN => ENETDOWN, - libc::ENETUNREACH => ENETUNREACH, - libc::ENETRESET => ENETRESET, - libc::ECONNABORTED => ECONNABORTED, - libc::ECONNRESET => ECONNRESET, - libc::ENOBUFS => ENOBUFS, - libc::EISCONN => EISCONN, - libc::ENOTCONN => ENOTCONN, - libc::ESHUTDOWN => ESHUTDOWN, - libc::ETOOMANYREFS => ETOOMANYREFS, - libc::ETIMEDOUT => ETIMEDOUT, - libc::ECONNREFUSED => ECONNREFUSED, - libc::ELOOP => ELOOP, - libc::ENAMETOOLONG => ENAMETOOLONG, - libc::EHOSTDOWN => EHOSTDOWN, - libc::EHOSTUNREACH => EHOSTUNREACH, - libc::ENOTEMPTY => ENOTEMPTY, - libc::EPROCLIM => EPROCLIM, - libc::EUSERS => EUSERS, - libc::EDQUOT => EDQUOT, - libc::ESTALE => ESTALE, - libc::EREMOTE => EREMOTE, - libc::EBADRPC => EBADRPC, - libc::ERPCMISMATCH => ERPCMISMATCH, - libc::EPROGUNAVAIL => EPROGUNAVAIL, - libc::EPROGMISMATCH => EPROGMISMATCH, - libc::EPROCUNAVAIL => EPROCUNAVAIL, - libc::ENOLCK => ENOLCK, - libc::ENOSYS => ENOSYS, - libc::EFTYPE => EFTYPE, - libc::EAUTH => EAUTH, - libc::ENEEDAUTH => ENEEDAUTH, - libc::EIDRM => EIDRM, - libc::ENOMSG => ENOMSG, - libc::EOVERFLOW => EOVERFLOW, - libc::EILSEQ => EILSEQ, - libc::ENOTSUP => ENOTSUP, - libc::ECANCELED => ECANCELED, - libc::EBADMSG => EBADMSG, - libc::ENODATA => ENODATA, - libc::ENOSR => ENOSR, - libc::ENOSTR => ENOSTR, - libc::ETIME => ETIME, - libc::ENOATTR => ENOATTR, - libc::EMULTIHOP => EMULTIHOP, - libc::ENOLINK => ENOLINK, - libc::EPROTO => EPROTO, - _ => UnknownErrno, - } - } -} - -#[cfg(target_os = "redox")] -mod consts { - #[derive(Clone, Copy, Debug, Eq, PartialEq)] - #[repr(i32)] - #[non_exhaustive] - pub enum Errno { - UnknownErrno = 0, - EPERM = libc::EPERM, - ENOENT = libc::ENOENT, - ESRCH = libc::ESRCH, - EINTR = libc::EINTR, - EIO = libc::EIO, - ENXIO = libc::ENXIO, - E2BIG = libc::E2BIG, - ENOEXEC = libc::ENOEXEC, - EBADF = libc::EBADF, - ECHILD = libc::ECHILD, - EDEADLK = libc::EDEADLK, - ENOMEM = libc::ENOMEM, - EACCES = libc::EACCES, - EFAULT = libc::EFAULT, - ENOTBLK = libc::ENOTBLK, - EBUSY = libc::EBUSY, - EEXIST = libc::EEXIST, - EXDEV = libc::EXDEV, - ENODEV = libc::ENODEV, - ENOTDIR = libc::ENOTDIR, - EISDIR = libc::EISDIR, - EINVAL = libc::EINVAL, - ENFILE = libc::ENFILE, - EMFILE = libc::EMFILE, - ENOTTY = libc::ENOTTY, - ETXTBSY = libc::ETXTBSY, - EFBIG = libc::EFBIG, - ENOSPC = libc::ENOSPC, - ESPIPE = libc::ESPIPE, - EROFS = libc::EROFS, - EMLINK = libc::EMLINK, - EPIPE = libc::EPIPE, - EDOM = libc::EDOM, - ERANGE = libc::ERANGE, - EAGAIN = libc::EAGAIN, - EINPROGRESS = libc::EINPROGRESS, - EALREADY = libc::EALREADY, - ENOTSOCK = libc::ENOTSOCK, - EDESTADDRREQ = libc::EDESTADDRREQ, - EMSGSIZE = libc::EMSGSIZE, - EPROTOTYPE = libc::EPROTOTYPE, - ENOPROTOOPT = libc::ENOPROTOOPT, - EPROTONOSUPPORT = libc::EPROTONOSUPPORT, - ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT, - EOPNOTSUPP = libc::EOPNOTSUPP, - EPFNOSUPPORT = libc::EPFNOSUPPORT, - EAFNOSUPPORT = libc::EAFNOSUPPORT, - EADDRINUSE = libc::EADDRINUSE, - EADDRNOTAVAIL = libc::EADDRNOTAVAIL, - ENETDOWN = libc::ENETDOWN, - ENETUNREACH = libc::ENETUNREACH, - ENETRESET = libc::ENETRESET, - ECONNABORTED = libc::ECONNABORTED, - ECONNRESET = libc::ECONNRESET, - ENOBUFS = libc::ENOBUFS, - EISCONN = libc::EISCONN, - ENOTCONN = libc::ENOTCONN, - ESHUTDOWN = libc::ESHUTDOWN, - ETOOMANYREFS = libc::ETOOMANYREFS, - ETIMEDOUT = libc::ETIMEDOUT, - ECONNREFUSED = libc::ECONNREFUSED, - ELOOP = libc::ELOOP, - ENAMETOOLONG = libc::ENAMETOOLONG, - EHOSTDOWN = libc::EHOSTDOWN, - EHOSTUNREACH = libc::EHOSTUNREACH, - ENOTEMPTY = libc::ENOTEMPTY, - EUSERS = libc::EUSERS, - EDQUOT = libc::EDQUOT, - ESTALE = libc::ESTALE, - EREMOTE = libc::EREMOTE, - ENOLCK = libc::ENOLCK, - ENOSYS = libc::ENOSYS, - EIDRM = libc::EIDRM, - ENOMSG = libc::ENOMSG, - EOVERFLOW = libc::EOVERFLOW, - EILSEQ = libc::EILSEQ, - ECANCELED = libc::ECANCELED, - EBADMSG = libc::EBADMSG, - ENODATA = libc::ENODATA, - ENOSR = libc::ENOSR, - ENOSTR = libc::ENOSTR, - ETIME = libc::ETIME, - EMULTIHOP = libc::EMULTIHOP, - ENOLINK = libc::ENOLINK, - EPROTO = libc::EPROTO, - } - - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::EWOULDBLOCK instead" - )] - pub const EWOULDBLOCK: Errno = Errno::EAGAIN; - - impl Errno { - pub const EWOULDBLOCK: Errno = Errno::EAGAIN; - } - - pub const fn from_i32(e: i32) -> Errno { - use self::Errno::*; - - match e { - libc::EPERM => EPERM, - libc::ENOENT => ENOENT, - libc::ESRCH => ESRCH, - libc::EINTR => EINTR, - libc::EIO => EIO, - libc::ENXIO => ENXIO, - libc::E2BIG => E2BIG, - libc::ENOEXEC => ENOEXEC, - libc::EBADF => EBADF, - libc::ECHILD => ECHILD, - libc::EDEADLK => EDEADLK, - libc::ENOMEM => ENOMEM, - libc::EACCES => EACCES, - libc::EFAULT => EFAULT, - libc::ENOTBLK => ENOTBLK, - libc::EBUSY => EBUSY, - libc::EEXIST => EEXIST, - libc::EXDEV => EXDEV, - libc::ENODEV => ENODEV, - libc::ENOTDIR => ENOTDIR, - libc::EISDIR => EISDIR, - libc::EINVAL => EINVAL, - libc::ENFILE => ENFILE, - libc::EMFILE => EMFILE, - libc::ENOTTY => ENOTTY, - libc::ETXTBSY => ETXTBSY, - libc::EFBIG => EFBIG, - libc::ENOSPC => ENOSPC, - libc::ESPIPE => ESPIPE, - libc::EROFS => EROFS, - libc::EMLINK => EMLINK, - libc::EPIPE => EPIPE, - libc::EDOM => EDOM, - libc::ERANGE => ERANGE, - libc::EAGAIN => EAGAIN, - libc::EINPROGRESS => EINPROGRESS, - libc::EALREADY => EALREADY, - libc::ENOTSOCK => ENOTSOCK, - libc::EDESTADDRREQ => EDESTADDRREQ, - libc::EMSGSIZE => EMSGSIZE, - libc::EPROTOTYPE => EPROTOTYPE, - libc::ENOPROTOOPT => ENOPROTOOPT, - libc::EPROTONOSUPPORT => EPROTONOSUPPORT, - libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT, - libc::EOPNOTSUPP => EOPNOTSUPP, - libc::EPFNOSUPPORT => EPFNOSUPPORT, - libc::EAFNOSUPPORT => EAFNOSUPPORT, - libc::EADDRINUSE => EADDRINUSE, - libc::EADDRNOTAVAIL => EADDRNOTAVAIL, - libc::ENETDOWN => ENETDOWN, - libc::ENETUNREACH => ENETUNREACH, - libc::ENETRESET => ENETRESET, - libc::ECONNABORTED => ECONNABORTED, - libc::ECONNRESET => ECONNRESET, - libc::ENOBUFS => ENOBUFS, - libc::EISCONN => EISCONN, - libc::ENOTCONN => ENOTCONN, - libc::ESHUTDOWN => ESHUTDOWN, - libc::ETOOMANYREFS => ETOOMANYREFS, - libc::ETIMEDOUT => ETIMEDOUT, - libc::ECONNREFUSED => ECONNREFUSED, - libc::ELOOP => ELOOP, - libc::ENAMETOOLONG => ENAMETOOLONG, - libc::EHOSTDOWN => EHOSTDOWN, - libc::EHOSTUNREACH => EHOSTUNREACH, - libc::ENOTEMPTY => ENOTEMPTY, - libc::EUSERS => EUSERS, - libc::EDQUOT => EDQUOT, - libc::ESTALE => ESTALE, - libc::EREMOTE => EREMOTE, - libc::ENOLCK => ENOLCK, - libc::ENOSYS => ENOSYS, - libc::EIDRM => EIDRM, - libc::ENOMSG => ENOMSG, - libc::EOVERFLOW => EOVERFLOW, - libc::EILSEQ => EILSEQ, - libc::ECANCELED => ECANCELED, - libc::EBADMSG => EBADMSG, - libc::ENODATA => ENODATA, - libc::ENOSR => ENOSR, - libc::ENOSTR => ENOSTR, - libc::ETIME => ETIME, - libc::EMULTIHOP => EMULTIHOP, - libc::ENOLINK => ENOLINK, - libc::EPROTO => EPROTO, - _ => UnknownErrno, - } - } -} - -#[cfg(any(target_os = "illumos", target_os = "solaris"))] -mod consts { - #[derive(Clone, Copy, Debug, Eq, PartialEq)] - #[repr(i32)] - #[non_exhaustive] - pub enum Errno { - UnknownErrno = 0, - EPERM = libc::EPERM, - ENOENT = libc::ENOENT, - ESRCH = libc::ESRCH, - EINTR = libc::EINTR, - EIO = libc::EIO, - ENXIO = libc::ENXIO, - E2BIG = libc::E2BIG, - ENOEXEC = libc::ENOEXEC, - EBADF = libc::EBADF, - ECHILD = libc::ECHILD, - EAGAIN = libc::EAGAIN, - ENOMEM = libc::ENOMEM, - EACCES = libc::EACCES, - EFAULT = libc::EFAULT, - ENOTBLK = libc::ENOTBLK, - EBUSY = libc::EBUSY, - EEXIST = libc::EEXIST, - EXDEV = libc::EXDEV, - ENODEV = libc::ENODEV, - ENOTDIR = libc::ENOTDIR, - EISDIR = libc::EISDIR, - EINVAL = libc::EINVAL, - ENFILE = libc::ENFILE, - EMFILE = libc::EMFILE, - ENOTTY = libc::ENOTTY, - ETXTBSY = libc::ETXTBSY, - EFBIG = libc::EFBIG, - ENOSPC = libc::ENOSPC, - ESPIPE = libc::ESPIPE, - EROFS = libc::EROFS, - EMLINK = libc::EMLINK, - EPIPE = libc::EPIPE, - EDOM = libc::EDOM, - ERANGE = libc::ERANGE, - ENOMSG = libc::ENOMSG, - EIDRM = libc::EIDRM, - ECHRNG = libc::ECHRNG, - EL2NSYNC = libc::EL2NSYNC, - EL3HLT = libc::EL3HLT, - EL3RST = libc::EL3RST, - ELNRNG = libc::ELNRNG, - EUNATCH = libc::EUNATCH, - ENOCSI = libc::ENOCSI, - EL2HLT = libc::EL2HLT, - EDEADLK = libc::EDEADLK, - ENOLCK = libc::ENOLCK, - ECANCELED = libc::ECANCELED, - ENOTSUP = libc::ENOTSUP, - EDQUOT = libc::EDQUOT, - EBADE = libc::EBADE, - EBADR = libc::EBADR, - EXFULL = libc::EXFULL, - ENOANO = libc::ENOANO, - EBADRQC = libc::EBADRQC, - EBADSLT = libc::EBADSLT, - EDEADLOCK = libc::EDEADLOCK, - EBFONT = libc::EBFONT, - EOWNERDEAD = libc::EOWNERDEAD, - ENOTRECOVERABLE = libc::ENOTRECOVERABLE, - ENOSTR = libc::ENOSTR, - ENODATA = libc::ENODATA, - ETIME = libc::ETIME, - ENOSR = libc::ENOSR, - ENONET = libc::ENONET, - ENOPKG = libc::ENOPKG, - EREMOTE = libc::EREMOTE, - ENOLINK = libc::ENOLINK, - EADV = libc::EADV, - ESRMNT = libc::ESRMNT, - ECOMM = libc::ECOMM, - EPROTO = libc::EPROTO, - ELOCKUNMAPPED = libc::ELOCKUNMAPPED, - ENOTACTIVE = libc::ENOTACTIVE, - EMULTIHOP = libc::EMULTIHOP, - EBADMSG = libc::EBADMSG, - ENAMETOOLONG = libc::ENAMETOOLONG, - EOVERFLOW = libc::EOVERFLOW, - ENOTUNIQ = libc::ENOTUNIQ, - EBADFD = libc::EBADFD, - EREMCHG = libc::EREMCHG, - ELIBACC = libc::ELIBACC, - ELIBBAD = libc::ELIBBAD, - ELIBSCN = libc::ELIBSCN, - ELIBMAX = libc::ELIBMAX, - ELIBEXEC = libc::ELIBEXEC, - EILSEQ = libc::EILSEQ, - ENOSYS = libc::ENOSYS, - ELOOP = libc::ELOOP, - ERESTART = libc::ERESTART, - ESTRPIPE = libc::ESTRPIPE, - ENOTEMPTY = libc::ENOTEMPTY, - EUSERS = libc::EUSERS, - ENOTSOCK = libc::ENOTSOCK, - EDESTADDRREQ = libc::EDESTADDRREQ, - EMSGSIZE = libc::EMSGSIZE, - EPROTOTYPE = libc::EPROTOTYPE, - ENOPROTOOPT = libc::ENOPROTOOPT, - EPROTONOSUPPORT = libc::EPROTONOSUPPORT, - ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT, - EOPNOTSUPP = libc::EOPNOTSUPP, - EPFNOSUPPORT = libc::EPFNOSUPPORT, - EAFNOSUPPORT = libc::EAFNOSUPPORT, - EADDRINUSE = libc::EADDRINUSE, - EADDRNOTAVAIL = libc::EADDRNOTAVAIL, - ENETDOWN = libc::ENETDOWN, - ENETUNREACH = libc::ENETUNREACH, - ENETRESET = libc::ENETRESET, - ECONNABORTED = libc::ECONNABORTED, - ECONNRESET = libc::ECONNRESET, - ENOBUFS = libc::ENOBUFS, - EISCONN = libc::EISCONN, - ENOTCONN = libc::ENOTCONN, - ESHUTDOWN = libc::ESHUTDOWN, - ETOOMANYREFS = libc::ETOOMANYREFS, - ETIMEDOUT = libc::ETIMEDOUT, - ECONNREFUSED = libc::ECONNREFUSED, - EHOSTDOWN = libc::EHOSTDOWN, - EHOSTUNREACH = libc::EHOSTUNREACH, - EALREADY = libc::EALREADY, - EINPROGRESS = libc::EINPROGRESS, - ESTALE = libc::ESTALE, - } - - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::ELAST instead" - )] - pub const ELAST: Errno = Errno::ELAST; - #[deprecated( - since = "0.22.1", - note = "use nix::errno::Errno::EWOULDBLOCK instead" - )] - pub const EWOULDBLOCK: Errno = Errno::EAGAIN; - - impl Errno { - pub const ELAST: Errno = Errno::ESTALE; - pub const EWOULDBLOCK: Errno = Errno::EAGAIN; - } - - pub const fn from_i32(e: i32) -> Errno { - use self::Errno::*; - - match e { - libc::EPERM => EPERM, - libc::ENOENT => ENOENT, - libc::ESRCH => ESRCH, - libc::EINTR => EINTR, - libc::EIO => EIO, - libc::ENXIO => ENXIO, - libc::E2BIG => E2BIG, - libc::ENOEXEC => ENOEXEC, - libc::EBADF => EBADF, - libc::ECHILD => ECHILD, - libc::EAGAIN => EAGAIN, - libc::ENOMEM => ENOMEM, - libc::EACCES => EACCES, - libc::EFAULT => EFAULT, - libc::ENOTBLK => ENOTBLK, - libc::EBUSY => EBUSY, - libc::EEXIST => EEXIST, - libc::EXDEV => EXDEV, - libc::ENODEV => ENODEV, - libc::ENOTDIR => ENOTDIR, - libc::EISDIR => EISDIR, - libc::EINVAL => EINVAL, - libc::ENFILE => ENFILE, - libc::EMFILE => EMFILE, - libc::ENOTTY => ENOTTY, - libc::ETXTBSY => ETXTBSY, - libc::EFBIG => EFBIG, - libc::ENOSPC => ENOSPC, - libc::ESPIPE => ESPIPE, - libc::EROFS => EROFS, - libc::EMLINK => EMLINK, - libc::EPIPE => EPIPE, - libc::EDOM => EDOM, - libc::ERANGE => ERANGE, - libc::ENOMSG => ENOMSG, - libc::EIDRM => EIDRM, - libc::ECHRNG => ECHRNG, - libc::EL2NSYNC => EL2NSYNC, - libc::EL3HLT => EL3HLT, - libc::EL3RST => EL3RST, - libc::ELNRNG => ELNRNG, - libc::EUNATCH => EUNATCH, - libc::ENOCSI => ENOCSI, - libc::EL2HLT => EL2HLT, - libc::EDEADLK => EDEADLK, - libc::ENOLCK => ENOLCK, - libc::ECANCELED => ECANCELED, - libc::ENOTSUP => ENOTSUP, - libc::EDQUOT => EDQUOT, - libc::EBADE => EBADE, - libc::EBADR => EBADR, - libc::EXFULL => EXFULL, - libc::ENOANO => ENOANO, - libc::EBADRQC => EBADRQC, - libc::EBADSLT => EBADSLT, - libc::EDEADLOCK => EDEADLOCK, - libc::EBFONT => EBFONT, - libc::EOWNERDEAD => EOWNERDEAD, - libc::ENOTRECOVERABLE => ENOTRECOVERABLE, - libc::ENOSTR => ENOSTR, - libc::ENODATA => ENODATA, - libc::ETIME => ETIME, - libc::ENOSR => ENOSR, - libc::ENONET => ENONET, - libc::ENOPKG => ENOPKG, - libc::EREMOTE => EREMOTE, - libc::ENOLINK => ENOLINK, - libc::EADV => EADV, - libc::ESRMNT => ESRMNT, - libc::ECOMM => ECOMM, - libc::EPROTO => EPROTO, - libc::ELOCKUNMAPPED => ELOCKUNMAPPED, - libc::ENOTACTIVE => ENOTACTIVE, - libc::EMULTIHOP => EMULTIHOP, - libc::EBADMSG => EBADMSG, - libc::ENAMETOOLONG => ENAMETOOLONG, - libc::EOVERFLOW => EOVERFLOW, - libc::ENOTUNIQ => ENOTUNIQ, - libc::EBADFD => EBADFD, - libc::EREMCHG => EREMCHG, - libc::ELIBACC => ELIBACC, - libc::ELIBBAD => ELIBBAD, - libc::ELIBSCN => ELIBSCN, - libc::ELIBMAX => ELIBMAX, - libc::ELIBEXEC => ELIBEXEC, - libc::EILSEQ => EILSEQ, - libc::ENOSYS => ENOSYS, - libc::ELOOP => ELOOP, - libc::ERESTART => ERESTART, - libc::ESTRPIPE => ESTRPIPE, - libc::ENOTEMPTY => ENOTEMPTY, - libc::EUSERS => EUSERS, - libc::ENOTSOCK => ENOTSOCK, - libc::EDESTADDRREQ => EDESTADDRREQ, - libc::EMSGSIZE => EMSGSIZE, - libc::EPROTOTYPE => EPROTOTYPE, - libc::ENOPROTOOPT => ENOPROTOOPT, - libc::EPROTONOSUPPORT => EPROTONOSUPPORT, - libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT, - libc::EOPNOTSUPP => EOPNOTSUPP, - libc::EPFNOSUPPORT => EPFNOSUPPORT, - libc::EAFNOSUPPORT => EAFNOSUPPORT, - libc::EADDRINUSE => EADDRINUSE, - libc::EADDRNOTAVAIL => EADDRNOTAVAIL, - libc::ENETDOWN => ENETDOWN, - libc::ENETUNREACH => ENETUNREACH, - libc::ENETRESET => ENETRESET, - libc::ECONNABORTED => ECONNABORTED, - libc::ECONNRESET => ECONNRESET, - libc::ENOBUFS => ENOBUFS, - libc::EISCONN => EISCONN, - libc::ENOTCONN => ENOTCONN, - libc::ESHUTDOWN => ESHUTDOWN, - libc::ETOOMANYREFS => ETOOMANYREFS, - libc::ETIMEDOUT => ETIMEDOUT, - libc::ECONNREFUSED => ECONNREFUSED, - libc::EHOSTDOWN => EHOSTDOWN, - libc::EHOSTUNREACH => EHOSTUNREACH, - libc::EALREADY => EALREADY, - libc::EINPROGRESS => EINPROGRESS, - libc::ESTALE => ESTALE, - _ => UnknownErrno, - } - } -} diff --git a/vendor/nix-v0.23.1-patched/src/fcntl.rs b/vendor/nix-v0.23.1-patched/src/fcntl.rs deleted file mode 100644 index dd8e59a6e..000000000 --- a/vendor/nix-v0.23.1-patched/src/fcntl.rs +++ /dev/null @@ -1,696 +0,0 @@ -use crate::errno::Errno; -use libc::{self, c_char, c_int, c_uint, size_t, ssize_t}; -use std::ffi::OsString; -#[cfg(not(target_os = "redox"))] -use std::os::raw; -use std::os::unix::ffi::OsStringExt; -use std::os::unix::io::RawFd; -use crate::sys::stat::Mode; -use crate::{NixPath, Result}; - -#[cfg(any(target_os = "android", target_os = "linux"))] -use std::ptr; // For splice and copy_file_range -#[cfg(any(target_os = "android", target_os = "linux"))] -use crate::sys::uio::IoVec; // For vmsplice - -#[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia", - any(target_os = "wasi", target_env = "wasi"), - target_env = "uclibc", - target_os = "freebsd" -))] -pub use self::posix_fadvise::*; - -#[cfg(not(target_os = "redox"))] -libc_bitflags! { - pub struct AtFlags: c_int { - AT_REMOVEDIR; - AT_SYMLINK_FOLLOW; - AT_SYMLINK_NOFOLLOW; - #[cfg(any(target_os = "android", target_os = "linux"))] - AT_NO_AUTOMOUNT; - #[cfg(any(target_os = "android", target_os = "linux"))] - AT_EMPTY_PATH; - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - AT_EACCESS; - } -} - -libc_bitflags!( - /// Configuration options for opened files. - pub struct OFlag: c_int { - /// Mask for the access mode of the file. - O_ACCMODE; - /// Use alternate I/O semantics. - #[cfg(target_os = "netbsd")] - O_ALT_IO; - /// Open the file in append-only mode. - O_APPEND; - /// Generate a signal when input or output becomes possible. - #[cfg(not(any(target_os = "illumos", target_os = "solaris")))] - O_ASYNC; - /// Closes the file descriptor once an `execve` call is made. - /// - /// Also sets the file offset to the beginning of the file. - O_CLOEXEC; - /// Create the file if it does not exist. - O_CREAT; - /// Try to minimize cache effects of the I/O for this file. - #[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd"))] - O_DIRECT; - /// If the specified path isn't a directory, fail. - #[cfg(not(any(target_os = "illumos", target_os = "solaris")))] - O_DIRECTORY; - /// Implicitly follow each `write()` with an `fdatasync()`. - #[cfg(any(target_os = "android", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - O_DSYNC; - /// Error out if a file was not created. - O_EXCL; - /// Open for execute only. - #[cfg(target_os = "freebsd")] - O_EXEC; - /// Open with an exclusive file lock. - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "redox"))] - O_EXLOCK; - /// Same as `O_SYNC`. - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - all(target_os = "linux", not(target_env = "musl")), - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "redox"))] - O_FSYNC; - /// Allow files whose sizes can't be represented in an `off_t` to be opened. - #[cfg(any(target_os = "android", target_os = "linux"))] - O_LARGEFILE; - /// Do not update the file last access time during `read(2)`s. - #[cfg(any(target_os = "android", target_os = "linux"))] - O_NOATIME; - /// Don't attach the device as the process' controlling terminal. - #[cfg(not(target_os = "redox"))] - O_NOCTTY; - /// Same as `O_NONBLOCK`. - #[cfg(not(target_os = "redox"))] - O_NDELAY; - /// `open()` will fail if the given path is a symbolic link. - O_NOFOLLOW; - /// When possible, open the file in nonblocking mode. - O_NONBLOCK; - /// Don't deliver `SIGPIPE`. - #[cfg(target_os = "netbsd")] - O_NOSIGPIPE; - /// Obtain a file descriptor for low-level access. - /// - /// The file itself is not opened and other file operations will fail. - #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))] - O_PATH; - /// Only allow reading. - /// - /// This should not be combined with `O_WRONLY` or `O_RDWR`. - O_RDONLY; - /// Allow both reading and writing. - /// - /// This should not be combined with `O_WRONLY` or `O_RDONLY`. - O_RDWR; - /// Similar to `O_DSYNC` but applies to `read`s instead. - #[cfg(any(target_os = "linux", target_os = "netbsd", target_os = "openbsd"))] - O_RSYNC; - /// Skip search permission checks. - #[cfg(target_os = "netbsd")] - O_SEARCH; - /// Open with a shared file lock. - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "redox"))] - O_SHLOCK; - /// Implicitly follow each `write()` with an `fsync()`. - #[cfg(not(target_os = "redox"))] - O_SYNC; - /// Create an unnamed temporary file. - #[cfg(any(target_os = "android", target_os = "linux"))] - O_TMPFILE; - /// Truncate an existing regular file to 0 length if it allows writing. - O_TRUNC; - /// Restore default TTY attributes. - #[cfg(target_os = "freebsd")] - O_TTY_INIT; - /// Only allow writing. - /// - /// This should not be combined with `O_RDONLY` or `O_RDWR`. - O_WRONLY; - } -); - -// The conversion is not identical on all operating systems. -#[allow(clippy::useless_conversion)] -pub fn open(path: &P, oflag: OFlag, mode: Mode) -> Result { - let fd = path.with_nix_path(|cstr| { - unsafe { libc::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) } - })?; - - Errno::result(fd) -} - -// The conversion is not identical on all operating systems. -#[allow(clippy::useless_conversion)] -#[cfg(not(target_os = "redox"))] -pub fn openat( - dirfd: RawFd, - path: &P, - oflag: OFlag, - mode: Mode, -) -> Result { - let fd = path.with_nix_path(|cstr| { - unsafe { libc::openat(dirfd, cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) } - })?; - Errno::result(fd) -} - -#[cfg(not(target_os = "redox"))] -pub fn renameat( - old_dirfd: Option, - old_path: &P1, - new_dirfd: Option, - new_path: &P2, -) -> Result<()> { - let res = old_path.with_nix_path(|old_cstr| { - new_path.with_nix_path(|new_cstr| unsafe { - libc::renameat( - at_rawfd(old_dirfd), - old_cstr.as_ptr(), - at_rawfd(new_dirfd), - new_cstr.as_ptr(), - ) - }) - })??; - Errno::result(res).map(drop) -} - -#[cfg(all( - target_os = "linux", - target_env = "gnu", -))] -libc_bitflags! { - pub struct RenameFlags: u32 { - RENAME_EXCHANGE; - RENAME_NOREPLACE; - RENAME_WHITEOUT; - } -} - -#[cfg(all( - target_os = "linux", - target_env = "gnu", -))] -pub fn renameat2( - old_dirfd: Option, - old_path: &P1, - new_dirfd: Option, - new_path: &P2, - flags: RenameFlags, -) -> Result<()> { - let res = old_path.with_nix_path(|old_cstr| { - new_path.with_nix_path(|new_cstr| unsafe { - libc::renameat2( - at_rawfd(old_dirfd), - old_cstr.as_ptr(), - at_rawfd(new_dirfd), - new_cstr.as_ptr(), - flags.bits(), - ) - }) - })??; - Errno::result(res).map(drop) -} - -fn wrap_readlink_result(mut v: Vec, len: ssize_t) -> Result { - unsafe { v.set_len(len as usize) } - v.shrink_to_fit(); - Ok(OsString::from_vec(v.to_vec())) -} - -fn readlink_maybe_at( - dirfd: Option, - path: &P, - v: &mut Vec, -) -> Result { - path.with_nix_path(|cstr| unsafe { - match dirfd { - #[cfg(target_os = "redox")] - Some(_) => unreachable!(), - #[cfg(not(target_os = "redox"))] - Some(dirfd) => libc::readlinkat( - dirfd, - cstr.as_ptr(), - v.as_mut_ptr() as *mut c_char, - v.capacity() as size_t, - ), - None => libc::readlink( - cstr.as_ptr(), - v.as_mut_ptr() as *mut c_char, - v.capacity() as size_t, - ), - } - }) -} - -fn inner_readlink(dirfd: Option, path: &P) -> Result { - let mut v = Vec::with_capacity(libc::PATH_MAX as usize); - // simple case: result is strictly less than `PATH_MAX` - let res = readlink_maybe_at(dirfd, path, &mut v)?; - let len = Errno::result(res)?; - debug_assert!(len >= 0); - if (len as usize) < v.capacity() { - return wrap_readlink_result(v, res); - } - // Uh oh, the result is too long... - // Let's try to ask lstat how many bytes to allocate. - let reported_size = match dirfd { - #[cfg(target_os = "redox")] - Some(_) => unreachable!(), - #[cfg(any(target_os = "android", target_os = "linux"))] - Some(dirfd) => { - let flags = if path.is_empty() { AtFlags::AT_EMPTY_PATH } else { AtFlags::empty() }; - super::sys::stat::fstatat(dirfd, path, flags | AtFlags::AT_SYMLINK_NOFOLLOW) - }, - #[cfg(not(any(target_os = "android", target_os = "linux", target_os = "redox")))] - Some(dirfd) => super::sys::stat::fstatat(dirfd, path, AtFlags::AT_SYMLINK_NOFOLLOW), - None => super::sys::stat::lstat(path) - } - .map(|x| x.st_size) - .unwrap_or(0); - let mut try_size = if reported_size > 0 { - // Note: even if `lstat`'s apparently valid answer turns out to be - // wrong, we will still read the full symlink no matter what. - reported_size as usize + 1 - } else { - // If lstat doesn't cooperate, or reports an error, be a little less - // precise. - (libc::PATH_MAX as usize).max(128) << 1 - }; - loop { - v.reserve_exact(try_size); - let res = readlink_maybe_at(dirfd, path, &mut v)?; - let len = Errno::result(res)?; - debug_assert!(len >= 0); - if (len as usize) < v.capacity() { - break wrap_readlink_result(v, res); - } else { - // Ugh! Still not big enough! - match try_size.checked_shl(1) { - Some(next_size) => try_size = next_size, - // It's absurd that this would happen, but handle it sanely - // anyway. - None => break Err(Errno::ENAMETOOLONG), - } - } - } -} - -pub fn readlink(path: &P) -> Result { - inner_readlink(None, path) -} - -#[cfg(not(target_os = "redox"))] -pub fn readlinkat(dirfd: RawFd, path: &P) -> Result { - inner_readlink(Some(dirfd), path) -} - -/// Computes the raw fd consumed by a function of the form `*at`. -#[cfg(not(target_os = "redox"))] -pub(crate) fn at_rawfd(fd: Option) -> raw::c_int { - match fd { - None => libc::AT_FDCWD, - Some(fd) => fd, - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -libc_bitflags!( - /// Additional flags for file sealing, which allows for limiting operations on a file. - pub struct SealFlag: c_int { - /// Prevents further calls to `fcntl()` with `F_ADD_SEALS`. - F_SEAL_SEAL; - /// The file cannot be reduced in size. - F_SEAL_SHRINK; - /// The size of the file cannot be increased. - F_SEAL_GROW; - /// The file contents cannot be modified. - F_SEAL_WRITE; - } -); - -libc_bitflags!( - /// Additional configuration flags for `fcntl`'s `F_SETFD`. - pub struct FdFlag: c_int { - /// The file descriptor will automatically be closed during a successful `execve(2)`. - FD_CLOEXEC; - } -); - -#[cfg(not(target_os = "redox"))] -#[derive(Debug, Eq, Hash, PartialEq)] -#[non_exhaustive] -pub enum FcntlArg<'a> { - F_DUPFD(RawFd), - F_DUPFD_CLOEXEC(RawFd), - F_GETFD, - F_SETFD(FdFlag), // FD_FLAGS - F_GETFL, - F_SETFL(OFlag), // O_NONBLOCK - F_SETLK(&'a libc::flock), - F_SETLKW(&'a libc::flock), - F_GETLK(&'a mut libc::flock), - #[cfg(any(target_os = "linux", target_os = "android"))] - F_OFD_SETLK(&'a libc::flock), - #[cfg(any(target_os = "linux", target_os = "android"))] - F_OFD_SETLKW(&'a libc::flock), - #[cfg(any(target_os = "linux", target_os = "android"))] - F_OFD_GETLK(&'a mut libc::flock), - #[cfg(any(target_os = "android", target_os = "linux"))] - F_ADD_SEALS(SealFlag), - #[cfg(any(target_os = "android", target_os = "linux"))] - F_GET_SEALS, - #[cfg(any(target_os = "macos", target_os = "ios"))] - F_FULLFSYNC, - #[cfg(any(target_os = "linux", target_os = "android"))] - F_GETPIPE_SZ, - #[cfg(any(target_os = "linux", target_os = "android"))] - F_SETPIPE_SZ(c_int), - // TODO: Rest of flags -} - -#[cfg(target_os = "redox")] -#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)] -#[non_exhaustive] -pub enum FcntlArg { - F_DUPFD(RawFd), - F_DUPFD_CLOEXEC(RawFd), - F_GETFD, - F_SETFD(FdFlag), // FD_FLAGS - F_GETFL, - F_SETFL(OFlag), // O_NONBLOCK -} -pub use self::FcntlArg::*; - -// TODO: Figure out how to handle value fcntl returns -pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result { - let res = unsafe { - match arg { - F_DUPFD(rawfd) => libc::fcntl(fd, libc::F_DUPFD, rawfd), - F_DUPFD_CLOEXEC(rawfd) => libc::fcntl(fd, libc::F_DUPFD_CLOEXEC, rawfd), - F_GETFD => libc::fcntl(fd, libc::F_GETFD), - F_SETFD(flag) => libc::fcntl(fd, libc::F_SETFD, flag.bits()), - F_GETFL => libc::fcntl(fd, libc::F_GETFL), - F_SETFL(flag) => libc::fcntl(fd, libc::F_SETFL, flag.bits()), - #[cfg(not(target_os = "redox"))] - F_SETLK(flock) => libc::fcntl(fd, libc::F_SETLK, flock), - #[cfg(not(target_os = "redox"))] - F_SETLKW(flock) => libc::fcntl(fd, libc::F_SETLKW, flock), - #[cfg(not(target_os = "redox"))] - F_GETLK(flock) => libc::fcntl(fd, libc::F_GETLK, flock), - #[cfg(any(target_os = "android", target_os = "linux"))] - F_OFD_SETLK(flock) => libc::fcntl(fd, libc::F_OFD_SETLK, flock), - #[cfg(any(target_os = "android", target_os = "linux"))] - F_OFD_SETLKW(flock) => libc::fcntl(fd, libc::F_OFD_SETLKW, flock), - #[cfg(any(target_os = "android", target_os = "linux"))] - F_OFD_GETLK(flock) => libc::fcntl(fd, libc::F_OFD_GETLK, flock), - #[cfg(any(target_os = "android", target_os = "linux"))] - F_ADD_SEALS(flag) => libc::fcntl(fd, libc::F_ADD_SEALS, flag.bits()), - #[cfg(any(target_os = "android", target_os = "linux"))] - F_GET_SEALS => libc::fcntl(fd, libc::F_GET_SEALS), - #[cfg(any(target_os = "macos", target_os = "ios"))] - F_FULLFSYNC => libc::fcntl(fd, libc::F_FULLFSYNC), - #[cfg(any(target_os = "linux", target_os = "android"))] - F_GETPIPE_SZ => libc::fcntl(fd, libc::F_GETPIPE_SZ), - #[cfg(any(target_os = "linux", target_os = "android"))] - F_SETPIPE_SZ(size) => libc::fcntl(fd, libc::F_SETPIPE_SZ, size), - } - }; - - Errno::result(res) -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -#[non_exhaustive] -pub enum FlockArg { - LockShared, - LockExclusive, - Unlock, - LockSharedNonblock, - LockExclusiveNonblock, - UnlockNonblock, -} - -#[cfg(not(target_os = "redox"))] -pub fn flock(fd: RawFd, arg: FlockArg) -> Result<()> { - use self::FlockArg::*; - - let res = unsafe { - match arg { - LockShared => libc::flock(fd, libc::LOCK_SH), - LockExclusive => libc::flock(fd, libc::LOCK_EX), - Unlock => libc::flock(fd, libc::LOCK_UN), - LockSharedNonblock => libc::flock(fd, libc::LOCK_SH | libc::LOCK_NB), - LockExclusiveNonblock => libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB), - UnlockNonblock => libc::flock(fd, libc::LOCK_UN | libc::LOCK_NB), - } - }; - - Errno::result(res).map(drop) -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -libc_bitflags! { - /// Additional flags to `splice` and friends. - pub struct SpliceFFlags: c_uint { - /// Request that pages be moved instead of copied. - /// - /// Not applicable to `vmsplice`. - SPLICE_F_MOVE; - /// Do not block on I/O. - SPLICE_F_NONBLOCK; - /// Hint that more data will be coming in a subsequent splice. - /// - /// Not applicable to `vmsplice`. - SPLICE_F_MORE; - /// Gift the user pages to the kernel. - /// - /// Not applicable to `splice`. - SPLICE_F_GIFT; - } -} - -/// Copy a range of data from one file to another -/// -/// The `copy_file_range` system call performs an in-kernel copy between -/// file descriptors `fd_in` and `fd_out` without the additional cost of -/// transferring data from the kernel to user space and then back into the -/// kernel. It copies up to `len` bytes of data from file descriptor `fd_in` to -/// file descriptor `fd_out`, overwriting any data that exists within the -/// requested range of the target file. -/// -/// If the `off_in` and/or `off_out` arguments are used, the values -/// will be mutated to reflect the new position within the file after -/// copying. If they are not used, the relevant filedescriptors will be seeked -/// to the new position. -/// -/// On successful completion the number of bytes actually copied will be -/// returned. -#[cfg(any(target_os = "android", target_os = "linux"))] -pub fn copy_file_range( - fd_in: RawFd, - off_in: Option<&mut libc::loff_t>, - fd_out: RawFd, - off_out: Option<&mut libc::loff_t>, - len: usize, -) -> Result { - let off_in = off_in - .map(|offset| offset as *mut libc::loff_t) - .unwrap_or(ptr::null_mut()); - let off_out = off_out - .map(|offset| offset as *mut libc::loff_t) - .unwrap_or(ptr::null_mut()); - - let ret = unsafe { - libc::syscall( - libc::SYS_copy_file_range, - fd_in, - off_in, - fd_out, - off_out, - len, - 0, - ) - }; - Errno::result(ret).map(|r| r as usize) -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -pub fn splice( - fd_in: RawFd, - off_in: Option<&mut libc::loff_t>, - fd_out: RawFd, - off_out: Option<&mut libc::loff_t>, - len: usize, - flags: SpliceFFlags, -) -> Result { - let off_in = off_in - .map(|offset| offset as *mut libc::loff_t) - .unwrap_or(ptr::null_mut()); - let off_out = off_out - .map(|offset| offset as *mut libc::loff_t) - .unwrap_or(ptr::null_mut()); - - let ret = unsafe { libc::splice(fd_in, off_in, fd_out, off_out, len, flags.bits()) }; - Errno::result(ret).map(|r| r as usize) -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -pub fn tee(fd_in: RawFd, fd_out: RawFd, len: usize, flags: SpliceFFlags) -> Result { - let ret = unsafe { libc::tee(fd_in, fd_out, len, flags.bits()) }; - Errno::result(ret).map(|r| r as usize) -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -pub fn vmsplice(fd: RawFd, iov: &[IoVec<&[u8]>], flags: SpliceFFlags) -> Result { - let ret = unsafe { - libc::vmsplice( - fd, - iov.as_ptr() as *const libc::iovec, - iov.len(), - flags.bits(), - ) - }; - Errno::result(ret).map(|r| r as usize) -} - -#[cfg(any(target_os = "linux"))] -libc_bitflags!( - /// Mode argument flags for fallocate determining operation performed on a given range. - pub struct FallocateFlags: c_int { - /// File size is not changed. - /// - /// offset + len can be greater than file size. - FALLOC_FL_KEEP_SIZE; - /// Deallocates space by creating a hole. - /// - /// Must be ORed with FALLOC_FL_KEEP_SIZE. Byte range starts at offset and continues for len bytes. - FALLOC_FL_PUNCH_HOLE; - /// Removes byte range from a file without leaving a hole. - /// - /// Byte range to collapse starts at offset and continues for len bytes. - FALLOC_FL_COLLAPSE_RANGE; - /// Zeroes space in specified byte range. - /// - /// Byte range starts at offset and continues for len bytes. - FALLOC_FL_ZERO_RANGE; - /// Increases file space by inserting a hole within the file size. - /// - /// Does not overwrite existing data. Hole starts at offset and continues for len bytes. - FALLOC_FL_INSERT_RANGE; - /// Shared file data extants are made private to the file. - /// - /// Gaurantees that a subsequent write will not fail due to lack of space. - FALLOC_FL_UNSHARE_RANGE; - } -); - -/// Manipulates file space. -/// -/// Allows the caller to directly manipulate the allocated disk space for the -/// file referred to by fd. -#[cfg(any(target_os = "linux"))] -pub fn fallocate( - fd: RawFd, - mode: FallocateFlags, - offset: libc::off_t, - len: libc::off_t, -) -> Result<()> { - let res = unsafe { libc::fallocate(fd, mode.bits(), offset, len) }; - Errno::result(res).map(drop) -} - -#[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia", - any(target_os = "wasi", target_env = "wasi"), - target_env = "uclibc", - target_os = "freebsd" -))] -mod posix_fadvise { - use crate::errno::Errno; - use std::os::unix::io::RawFd; - use crate::Result; - - libc_enum! { - #[repr(i32)] - #[non_exhaustive] - pub enum PosixFadviseAdvice { - POSIX_FADV_NORMAL, - POSIX_FADV_SEQUENTIAL, - POSIX_FADV_RANDOM, - POSIX_FADV_NOREUSE, - POSIX_FADV_WILLNEED, - POSIX_FADV_DONTNEED, - } - } - - pub fn posix_fadvise( - fd: RawFd, - offset: libc::off_t, - len: libc::off_t, - advice: PosixFadviseAdvice, - ) -> Result<()> { - let res = unsafe { libc::posix_fadvise(fd, offset, len, advice as libc::c_int) }; - - if res == 0 { - Ok(()) - } else { - Err(Errno::from_i32(res)) - } - } -} - -#[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia", - any(target_os = "wasi", target_env = "wasi"), - target_os = "freebsd" -))] -pub fn posix_fallocate(fd: RawFd, offset: libc::off_t, len: libc::off_t) -> Result<()> { - let res = unsafe { libc::posix_fallocate(fd, offset, len) }; - match Errno::result(res) { - Err(err) => Err(err), - Ok(0) => Ok(()), - Ok(errno) => Err(Errno::from_i32(errno)), - } -} diff --git a/vendor/nix-v0.23.1-patched/src/features.rs b/vendor/nix-v0.23.1-patched/src/features.rs deleted file mode 100644 index ed80fd714..000000000 --- a/vendor/nix-v0.23.1-patched/src/features.rs +++ /dev/null @@ -1,121 +0,0 @@ -//! Feature tests for OS functionality -pub use self::os::*; - -#[cfg(any(target_os = "linux", target_os = "android"))] -mod os { - use crate::sys::utsname::uname; - - // Features: - // * atomic cloexec on socket: 2.6.27 - // * pipe2: 2.6.27 - // * accept4: 2.6.28 - - static VERS_UNKNOWN: usize = 1; - static VERS_2_6_18: usize = 2; - static VERS_2_6_27: usize = 3; - static VERS_2_6_28: usize = 4; - static VERS_3: usize = 5; - - #[inline] - fn digit(dst: &mut usize, b: u8) { - *dst *= 10; - *dst += (b - b'0') as usize; - } - - fn parse_kernel_version() -> usize { - let u = uname(); - - let mut curr: usize = 0; - let mut major: usize = 0; - let mut minor: usize = 0; - let mut patch: usize = 0; - - for b in u.release().bytes() { - if curr >= 3 { - break; - } - - match b { - b'.' | b'-' => { - curr += 1; - } - b'0'..=b'9' => { - match curr { - 0 => digit(&mut major, b), - 1 => digit(&mut minor, b), - _ => digit(&mut patch, b), - } - } - _ => break, - } - } - - if major >= 3 { - VERS_3 - } else if major >= 2 { - if minor >= 7 { - VERS_UNKNOWN - } else if minor >= 6 { - if patch >= 28 { - VERS_2_6_28 - } else if patch >= 27 { - VERS_2_6_27 - } else { - VERS_2_6_18 - } - } else { - VERS_UNKNOWN - } - } else { - VERS_UNKNOWN - } - } - - fn kernel_version() -> usize { - static mut KERNEL_VERS: usize = 0; - - unsafe { - if KERNEL_VERS == 0 { - KERNEL_VERS = parse_kernel_version(); - } - - KERNEL_VERS - } - } - - /// Check if the OS supports atomic close-on-exec for sockets - pub fn socket_atomic_cloexec() -> bool { - kernel_version() >= VERS_2_6_27 - } - - #[test] - pub fn test_parsing_kernel_version() { - assert!(kernel_version() > 0); - } -} - -#[cfg(any( - target_os = "dragonfly", // Since ??? - target_os = "freebsd", // Since 10.0 - target_os = "illumos", // Since ??? - target_os = "netbsd", // Since 6.0 - target_os = "openbsd", // Since 5.7 - target_os = "redox", // Since 1-july-2020 -))] -mod os { - /// Check if the OS supports atomic close-on-exec for sockets - pub const fn socket_atomic_cloexec() -> bool { - true - } -} - -#[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "fuchsia", - target_os = "solaris"))] -mod os { - /// Check if the OS supports atomic close-on-exec for sockets - pub const fn socket_atomic_cloexec() -> bool { - false - } -} diff --git a/vendor/nix-v0.23.1-patched/src/ifaddrs.rs b/vendor/nix-v0.23.1-patched/src/ifaddrs.rs deleted file mode 100644 index ed6328f3e..000000000 --- a/vendor/nix-v0.23.1-patched/src/ifaddrs.rs +++ /dev/null @@ -1,147 +0,0 @@ -//! Query network interface addresses -//! -//! Uses the Linux and/or BSD specific function `getifaddrs` to query the list -//! of interfaces and their associated addresses. - -use cfg_if::cfg_if; -use std::ffi; -use std::iter::Iterator; -use std::mem; -use std::option::Option; - -use crate::{Result, Errno}; -use crate::sys::socket::SockAddr; -use crate::net::if_::*; - -/// Describes a single address for an interface as returned by `getifaddrs`. -#[derive(Clone, Debug, Eq, Hash, PartialEq)] -pub struct InterfaceAddress { - /// Name of the network interface - pub interface_name: String, - /// Flags as from `SIOCGIFFLAGS` ioctl - pub flags: InterfaceFlags, - /// Network address of this interface - pub address: Option, - /// Netmask of this interface - pub netmask: Option, - /// Broadcast address of this interface, if applicable - pub broadcast: Option, - /// Point-to-point destination address - pub destination: Option, -} - -cfg_if! { - if #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "fuchsia", target_os = "linux"))] { - fn get_ifu_from_sockaddr(info: &libc::ifaddrs) -> *const libc::sockaddr { - info.ifa_ifu - } - } else { - fn get_ifu_from_sockaddr(info: &libc::ifaddrs) -> *const libc::sockaddr { - info.ifa_dstaddr - } - } -} - -impl InterfaceAddress { - /// Create an `InterfaceAddress` from the libc struct. - fn from_libc_ifaddrs(info: &libc::ifaddrs) -> InterfaceAddress { - let ifname = unsafe { ffi::CStr::from_ptr(info.ifa_name) }; - let address = unsafe { SockAddr::from_libc_sockaddr(info.ifa_addr) }; - let netmask = unsafe { SockAddr::from_libc_sockaddr(info.ifa_netmask) }; - let mut addr = InterfaceAddress { - interface_name: ifname.to_string_lossy().to_string(), - flags: InterfaceFlags::from_bits_truncate(info.ifa_flags as i32), - address, - netmask, - broadcast: None, - destination: None, - }; - - let ifu = get_ifu_from_sockaddr(info); - if addr.flags.contains(InterfaceFlags::IFF_POINTOPOINT) { - addr.destination = unsafe { SockAddr::from_libc_sockaddr(ifu) }; - } else if addr.flags.contains(InterfaceFlags::IFF_BROADCAST) { - addr.broadcast = unsafe { SockAddr::from_libc_sockaddr(ifu) }; - } - - addr - } -} - -/// Holds the results of `getifaddrs`. -/// -/// Use the function `getifaddrs` to create this Iterator. Note that the -/// actual list of interfaces can be iterated once and will be freed as -/// soon as the Iterator goes out of scope. -#[derive(Debug, Eq, Hash, PartialEq)] -pub struct InterfaceAddressIterator { - base: *mut libc::ifaddrs, - next: *mut libc::ifaddrs, -} - -impl Drop for InterfaceAddressIterator { - fn drop(&mut self) { - unsafe { libc::freeifaddrs(self.base) }; - } -} - -impl Iterator for InterfaceAddressIterator { - type Item = InterfaceAddress; - fn next(&mut self) -> Option<::Item> { - match unsafe { self.next.as_ref() } { - Some(ifaddr) => { - self.next = ifaddr.ifa_next; - Some(InterfaceAddress::from_libc_ifaddrs(ifaddr)) - } - None => None, - } - } -} - -/// Get interface addresses using libc's `getifaddrs` -/// -/// Note that the underlying implementation differs between OSes. Only the -/// most common address families are supported by the nix crate (due to -/// lack of time and complexity of testing). The address family is encoded -/// in the specific variant of `SockAddr` returned for the fields `address`, -/// `netmask`, `broadcast`, and `destination`. For any entry not supported, -/// the returned list will contain a `None` entry. -/// -/// # Example -/// ``` -/// let addrs = nix::ifaddrs::getifaddrs().unwrap(); -/// for ifaddr in addrs { -/// match ifaddr.address { -/// Some(address) => { -/// println!("interface {} address {}", -/// ifaddr.interface_name, address); -/// }, -/// None => { -/// println!("interface {} with unsupported address family", -/// ifaddr.interface_name); -/// } -/// } -/// } -/// ``` -pub fn getifaddrs() -> Result { - let mut addrs = mem::MaybeUninit::<*mut libc::ifaddrs>::uninit(); - unsafe { - Errno::result(libc::getifaddrs(addrs.as_mut_ptr())).map(|_| { - InterfaceAddressIterator { - base: addrs.assume_init(), - next: addrs.assume_init(), - } - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - // Only checks if `getifaddrs` can be invoked without panicking. - #[test] - fn test_getifaddrs() { - let _ = getifaddrs(); - } -} diff --git a/vendor/nix-v0.23.1-patched/src/kmod.rs b/vendor/nix-v0.23.1-patched/src/kmod.rs deleted file mode 100644 index c42068c70..000000000 --- a/vendor/nix-v0.23.1-patched/src/kmod.rs +++ /dev/null @@ -1,122 +0,0 @@ -//! Load and unload kernel modules. -//! -//! For more details see - -use std::ffi::CStr; -use std::os::unix::io::AsRawFd; - -use crate::errno::Errno; -use crate::Result; - -/// Loads a kernel module from a buffer. -/// -/// It loads an ELF image into kernel space, -/// performs any necessary symbol relocations, -/// initializes module parameters to values provided by the caller, -/// and then runs the module's init function. -/// -/// This function requires `CAP_SYS_MODULE` privilege. -/// -/// The `module_image` argument points to a buffer containing the binary image -/// to be loaded. The buffer should contain a valid ELF image -/// built for the running kernel. -/// -/// The `param_values` argument is a string containing space-delimited specifications -/// of the values for module parameters. -/// Each of the parameter specifications has the form: -/// -/// `name[=value[,value...]]` -/// -/// # Example -/// -/// ```no_run -/// use std::fs::File; -/// use std::io::Read; -/// use std::ffi::CString; -/// use nix::kmod::init_module; -/// -/// let mut f = File::open("mykernel.ko").unwrap(); -/// let mut contents: Vec = Vec::new(); -/// f.read_to_end(&mut contents).unwrap(); -/// init_module(&mut contents, &CString::new("who=Rust when=Now,12").unwrap()).unwrap(); -/// ``` -/// -/// See [`man init_module(2)`](https://man7.org/linux/man-pages/man2/init_module.2.html) for more information. -pub fn init_module(module_image: &[u8], param_values: &CStr) -> Result<()> { - let res = unsafe { - libc::syscall( - libc::SYS_init_module, - module_image.as_ptr(), - module_image.len(), - param_values.as_ptr(), - ) - }; - - Errno::result(res).map(drop) -} - -libc_bitflags!( - /// Flags used by the `finit_module` function. - pub struct ModuleInitFlags: libc::c_uint { - /// Ignore symbol version hashes. - MODULE_INIT_IGNORE_MODVERSIONS; - /// Ignore kernel version magic. - MODULE_INIT_IGNORE_VERMAGIC; - } -); - -/// Loads a kernel module from a given file descriptor. -/// -/// # Example -/// -/// ```no_run -/// use std::fs::File; -/// use std::ffi::CString; -/// use nix::kmod::{finit_module, ModuleInitFlags}; -/// -/// let f = File::open("mymod.ko").unwrap(); -/// finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()).unwrap(); -/// ``` -/// -/// See [`man init_module(2)`](https://man7.org/linux/man-pages/man2/init_module.2.html) for more information. -pub fn finit_module(fd: &T, param_values: &CStr, flags: ModuleInitFlags) -> Result<()> { - let res = unsafe { - libc::syscall( - libc::SYS_finit_module, - fd.as_raw_fd(), - param_values.as_ptr(), - flags.bits(), - ) - }; - - Errno::result(res).map(drop) -} - -libc_bitflags!( - /// Flags used by `delete_module`. - /// - /// See [`man delete_module(2)`](https://man7.org/linux/man-pages/man2/delete_module.2.html) - /// for a detailed description how these flags work. - pub struct DeleteModuleFlags: libc::c_int { - O_NONBLOCK; - O_TRUNC; - } -); - -/// Unloads the kernel module with the given name. -/// -/// # Example -/// -/// ```no_run -/// use std::ffi::CString; -/// use nix::kmod::{delete_module, DeleteModuleFlags}; -/// -/// delete_module(&CString::new("mymod").unwrap(), DeleteModuleFlags::O_NONBLOCK).unwrap(); -/// ``` -/// -/// See [`man delete_module(2)`](https://man7.org/linux/man-pages/man2/delete_module.2.html) for more information. -pub fn delete_module(name: &CStr, flags: DeleteModuleFlags) -> Result<()> { - let res = unsafe { libc::syscall(libc::SYS_delete_module, name.as_ptr(), flags.bits()) }; - - Errno::result(res).map(drop) -} diff --git a/vendor/nix-v0.23.1-patched/src/lib.rs b/vendor/nix-v0.23.1-patched/src/lib.rs deleted file mode 100644 index 3a2b63ab0..000000000 --- a/vendor/nix-v0.23.1-patched/src/lib.rs +++ /dev/null @@ -1,227 +0,0 @@ -//! Rust friendly bindings to the various *nix system functions. -//! -//! Modules are structured according to the C header file that they would be -//! defined in. -#![crate_name = "nix"] -#![cfg(unix)] -#![allow(non_camel_case_types)] -#![cfg_attr(test, deny(warnings))] -#![recursion_limit = "500"] -#![deny(unused)] -#![deny(unstable_features)] -#![deny(missing_copy_implementations)] -#![deny(missing_debug_implementations)] -#![warn(missing_docs)] - -// Re-exported external crates -pub use libc; - -// Private internal modules -#[macro_use] mod macros; - -// Public crates -#[cfg(not(target_os = "redox"))] -#[allow(missing_docs)] -pub mod dir; -pub mod env; -#[allow(missing_docs)] -pub mod errno; -pub mod features; -#[allow(missing_docs)] -pub mod fcntl; -#[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "illumos", - target_os = "openbsd"))] -pub mod ifaddrs; -#[cfg(any(target_os = "android", - target_os = "linux"))] -#[allow(missing_docs)] -pub mod kmod; -#[cfg(any(target_os = "android", - target_os = "freebsd", - target_os = "linux"))] -pub mod mount; -#[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "fushsia", - target_os = "linux", - target_os = "netbsd"))] -#[allow(missing_docs)] -pub mod mqueue; -#[cfg(not(target_os = "redox"))] -pub mod net; -pub mod poll; -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -pub mod pty; -pub mod sched; -pub mod sys; -#[allow(missing_docs)] -pub mod time; -// This can be implemented for other platforms as soon as libc -// provides bindings for them. -#[cfg(all(target_os = "linux", - any(target_arch = "x86", target_arch = "x86_64")))] -#[allow(missing_docs)] -pub mod ucontext; -#[allow(missing_docs)] -pub mod unistd; - -/* - * - * ===== Result / Error ===== - * - */ - -use libc::{c_char, PATH_MAX}; - -use std::{ptr, result}; -use std::ffi::{CStr, OsStr}; -use std::os::unix::ffi::OsStrExt; -use std::path::{Path, PathBuf}; - -use errno::Errno; - -/// Nix Result Type -pub type Result = result::Result; - -/// Nix's main error type. -/// -/// It's a wrapper around Errno. As such, it's very interoperable with -/// [`std::io::Error`], but it has the advantages of: -/// * `Clone` -/// * `Copy` -/// * `Eq` -/// * Small size -/// * Represents all of the system's errnos, instead of just the most common -/// ones. -pub type Error = Errno; - -/// Common trait used to represent file system paths by many Nix functions. -pub trait NixPath { - /// Is the path empty? - fn is_empty(&self) -> bool; - - /// Length of the path in bytes - fn len(&self) -> usize; - - /// Execute a function with this path as a `CStr`. - /// - /// Mostly used internally by Nix. - fn with_nix_path(&self, f: F) -> Result - where F: FnOnce(&CStr) -> T; -} - -impl NixPath for str { - fn is_empty(&self) -> bool { - NixPath::is_empty(OsStr::new(self)) - } - - fn len(&self) -> usize { - NixPath::len(OsStr::new(self)) - } - - fn with_nix_path(&self, f: F) -> Result - where F: FnOnce(&CStr) -> T { - OsStr::new(self).with_nix_path(f) - } -} - -impl NixPath for OsStr { - fn is_empty(&self) -> bool { - self.as_bytes().is_empty() - } - - fn len(&self) -> usize { - self.as_bytes().len() - } - - fn with_nix_path(&self, f: F) -> Result - where F: FnOnce(&CStr) -> T { - self.as_bytes().with_nix_path(f) - } -} - -impl NixPath for CStr { - fn is_empty(&self) -> bool { - self.to_bytes().is_empty() - } - - fn len(&self) -> usize { - self.to_bytes().len() - } - - fn with_nix_path(&self, f: F) -> Result - where F: FnOnce(&CStr) -> T { - // Equivalence with the [u8] impl. - if self.len() >= PATH_MAX as usize { - return Err(Errno::ENAMETOOLONG) - } - - Ok(f(self)) - } -} - -impl NixPath for [u8] { - fn is_empty(&self) -> bool { - self.is_empty() - } - - fn len(&self) -> usize { - self.len() - } - - fn with_nix_path(&self, f: F) -> Result - where F: FnOnce(&CStr) -> T { - let mut buf = [0u8; PATH_MAX as usize]; - - if self.len() >= PATH_MAX as usize { - return Err(Errno::ENAMETOOLONG) - } - - match self.iter().position(|b| *b == 0) { - Some(_) => Err(Errno::EINVAL), - None => { - unsafe { - // TODO: Replace with bytes::copy_memory. rust-lang/rust#24028 - ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len()); - Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char))) - } - - } - } - } -} - -impl NixPath for Path { - fn is_empty(&self) -> bool { - NixPath::is_empty(self.as_os_str()) - } - - fn len(&self) -> usize { - NixPath::len(self.as_os_str()) - } - - fn with_nix_path(&self, f: F) -> Result where F: FnOnce(&CStr) -> T { - self.as_os_str().with_nix_path(f) - } -} - -impl NixPath for PathBuf { - fn is_empty(&self) -> bool { - NixPath::is_empty(self.as_os_str()) - } - - fn len(&self) -> usize { - NixPath::len(self.as_os_str()) - } - - fn with_nix_path(&self, f: F) -> Result where F: FnOnce(&CStr) -> T { - self.as_os_str().with_nix_path(f) - } -} diff --git a/vendor/nix-v0.23.1-patched/src/macros.rs b/vendor/nix-v0.23.1-patched/src/macros.rs deleted file mode 100644 index 3ccbfdd43..000000000 --- a/vendor/nix-v0.23.1-patched/src/macros.rs +++ /dev/null @@ -1,311 +0,0 @@ -/// The `libc_bitflags!` macro helps with a common use case of defining a public bitflags type -/// with values from the libc crate. It is used the same way as the `bitflags!` macro, except -/// that only the name of the flag value has to be given. -/// -/// The `libc` crate must be in scope with the name `libc`. -/// -/// # Example -/// ``` -/// libc_bitflags!{ -/// pub struct ProtFlags: libc::c_int { -/// PROT_NONE; -/// PROT_READ; -/// /// PROT_WRITE enables write protect -/// PROT_WRITE; -/// PROT_EXEC; -/// #[cfg(any(target_os = "linux", target_os = "android"))] -/// PROT_GROWSDOWN; -/// #[cfg(any(target_os = "linux", target_os = "android"))] -/// PROT_GROWSUP; -/// } -/// } -/// ``` -/// -/// Example with casting, due to a mistake in libc. In this example, the -/// various flags have different types, so we cast the broken ones to the right -/// type. -/// -/// ``` -/// libc_bitflags!{ -/// pub struct SaFlags: libc::c_ulong { -/// SA_NOCLDSTOP as libc::c_ulong; -/// SA_NOCLDWAIT; -/// SA_NODEFER as libc::c_ulong; -/// SA_ONSTACK; -/// SA_RESETHAND as libc::c_ulong; -/// SA_RESTART as libc::c_ulong; -/// SA_SIGINFO; -/// } -/// } -/// ``` -macro_rules! libc_bitflags { - ( - $(#[$outer:meta])* - pub struct $BitFlags:ident: $T:ty { - $( - $(#[$inner:ident $($args:tt)*])* - $Flag:ident $(as $cast:ty)*; - )+ - } - ) => { - ::bitflags::bitflags! { - $(#[$outer])* - pub struct $BitFlags: $T { - $( - $(#[$inner $($args)*])* - const $Flag = libc::$Flag $(as $cast)*; - )+ - } - } - }; -} - -/// The `libc_enum!` macro helps with a common use case of defining an enum exclusively using -/// values from the `libc` crate. This macro supports both `pub` and private `enum`s. -/// -/// The `libc` crate must be in scope with the name `libc`. -/// -/// # Example -/// ``` -/// libc_enum!{ -/// pub enum ProtFlags { -/// PROT_NONE, -/// PROT_READ, -/// PROT_WRITE, -/// PROT_EXEC, -/// #[cfg(any(target_os = "linux", target_os = "android"))] -/// PROT_GROWSDOWN, -/// #[cfg(any(target_os = "linux", target_os = "android"))] -/// PROT_GROWSUP, -/// } -/// } -/// ``` -macro_rules! libc_enum { - // Exit rule. - (@make_enum - name: $BitFlags:ident, - { - $v:vis - attrs: [$($attrs:tt)*], - entries: [$($entries:tt)*], - } - ) => { - $($attrs)* - #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - $v enum $BitFlags { - $($entries)* - } - }; - - // Exit rule including TryFrom - (@make_enum - name: $BitFlags:ident, - { - $v:vis - attrs: [$($attrs:tt)*], - entries: [$($entries:tt)*], - from_type: $repr:path, - try_froms: [$($try_froms:tt)*] - } - ) => { - $($attrs)* - #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] - $v enum $BitFlags { - $($entries)* - } - impl ::std::convert::TryFrom<$repr> for $BitFlags { - type Error = $crate::Error; - #[allow(unused_doc_comments)] - fn try_from(x: $repr) -> $crate::Result { - match x { - $($try_froms)* - _ => Err($crate::Error::EINVAL) - } - } - } - }; - - // Done accumulating. - (@accumulate_entries - name: $BitFlags:ident, - { - $v:vis - attrs: $attrs:tt, - }, - $entries:tt, - $try_froms:tt; - ) => { - libc_enum! { - @make_enum - name: $BitFlags, - { - $v - attrs: $attrs, - entries: $entries, - } - } - }; - - // Done accumulating and want TryFrom - (@accumulate_entries - name: $BitFlags:ident, - { - $v:vis - attrs: $attrs:tt, - from_type: $repr:path, - }, - $entries:tt, - $try_froms:tt; - ) => { - libc_enum! { - @make_enum - name: $BitFlags, - { - $v - attrs: $attrs, - entries: $entries, - from_type: $repr, - try_froms: $try_froms - } - } - }; - - // Munch an attr. - (@accumulate_entries - name: $BitFlags:ident, - $prefix:tt, - [$($entries:tt)*], - [$($try_froms:tt)*]; - #[$attr:meta] $($tail:tt)* - ) => { - libc_enum! { - @accumulate_entries - name: $BitFlags, - $prefix, - [ - $($entries)* - #[$attr] - ], - [ - $($try_froms)* - #[$attr] - ]; - $($tail)* - } - }; - - // Munch last ident if not followed by a comma. - (@accumulate_entries - name: $BitFlags:ident, - $prefix:tt, - [$($entries:tt)*], - [$($try_froms:tt)*]; - $entry:ident - ) => { - libc_enum! { - @accumulate_entries - name: $BitFlags, - $prefix, - [ - $($entries)* - $entry = libc::$entry, - ], - [ - $($try_froms)* - libc::$entry => Ok($BitFlags::$entry), - ]; - } - }; - - // Munch an ident; covers terminating comma case. - (@accumulate_entries - name: $BitFlags:ident, - $prefix:tt, - [$($entries:tt)*], - [$($try_froms:tt)*]; - $entry:ident, - $($tail:tt)* - ) => { - libc_enum! { - @accumulate_entries - name: $BitFlags, - $prefix, - [ - $($entries)* - $entry = libc::$entry, - ], - [ - $($try_froms)* - libc::$entry => Ok($BitFlags::$entry), - ]; - $($tail)* - } - }; - - // Munch an ident and cast it to the given type; covers terminating comma. - (@accumulate_entries - name: $BitFlags:ident, - $prefix:tt, - [$($entries:tt)*], - [$($try_froms:tt)*]; - $entry:ident as $ty:ty, - $($tail:tt)* - ) => { - libc_enum! { - @accumulate_entries - name: $BitFlags, - $prefix, - [ - $($entries)* - $entry = libc::$entry as $ty, - ], - [ - $($try_froms)* - libc::$entry as $ty => Ok($BitFlags::$entry), - ]; - $($tail)* - } - }; - - // Entry rule. - ( - $(#[$attr:meta])* - $v:vis enum $BitFlags:ident { - $($vals:tt)* - } - ) => { - libc_enum! { - @accumulate_entries - name: $BitFlags, - { - $v - attrs: [$(#[$attr])*], - }, - [], - []; - $($vals)* - } - }; - - // Entry rule including TryFrom - ( - $(#[$attr:meta])* - $v:vis enum $BitFlags:ident { - $($vals:tt)* - } - impl TryFrom<$repr:path> - ) => { - libc_enum! { - @accumulate_entries - name: $BitFlags, - { - $v - attrs: [$(#[$attr])*], - from_type: $repr, - }, - [], - []; - $($vals)* - } - }; -} diff --git a/vendor/nix-v0.23.1-patched/src/mount/bsd.rs b/vendor/nix-v0.23.1-patched/src/mount/bsd.rs deleted file mode 100644 index 627bfa5ec..000000000 --- a/vendor/nix-v0.23.1-patched/src/mount/bsd.rs +++ /dev/null @@ -1,426 +0,0 @@ -use crate::{ - Error, - Errno, - NixPath, - Result, - sys::uio::IoVec -}; -use libc::{c_char, c_int, c_uint, c_void}; -use std::{ - borrow::Cow, - ffi::{CString, CStr}, - fmt, - io, - ptr -}; - - -libc_bitflags!( - /// Used with [`Nmount::nmount`]. - pub struct MntFlags: c_int { - /// ACL support enabled. - #[cfg(any(target_os = "netbsd", target_os = "freebsd"))] - MNT_ACLS; - /// All I/O to the file system should be done asynchronously. - MNT_ASYNC; - /// dir should instead be a file system ID encoded as “FSID:val0:val1”. - #[cfg(target_os = "freebsd")] - MNT_BYFSID; - /// Force a read-write mount even if the file system appears to be - /// unclean. - MNT_FORCE; - /// GEOM journal support enabled. - #[cfg(target_os = "freebsd")] - MNT_GJOURNAL; - /// MAC support for objects. - #[cfg(any(target_os = "macos", target_os = "freebsd"))] - MNT_MULTILABEL; - /// Disable read clustering. - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - MNT_NOCLUSTERR; - /// Disable write clustering. - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - MNT_NOCLUSTERW; - /// Enable NFS version 4 ACLs. - #[cfg(target_os = "freebsd")] - MNT_NFS4ACLS; - /// Do not update access times. - MNT_NOATIME; - /// Disallow program execution. - MNT_NOEXEC; - /// Do not honor setuid or setgid bits on files when executing them. - MNT_NOSUID; - /// Do not follow symlinks. - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - MNT_NOSYMFOLLOW; - /// Mount read-only. - MNT_RDONLY; - /// Causes the vfs subsystem to update its data structures pertaining to - /// the specified already mounted file system. - MNT_RELOAD; - /// Create a snapshot of the file system. - /// - /// See [mksnap_ffs(8)](https://www.freebsd.org/cgi/man.cgi?query=mksnap_ffs) - #[cfg(any(target_os = "macos", target_os = "freebsd"))] - MNT_SNAPSHOT; - /// Using soft updates. - #[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "netbsd", - target_os = "openbsd" - ))] - MNT_SOFTDEP; - /// Directories with the SUID bit set chown new files to their own - /// owner. - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - MNT_SUIDDIR; - /// All I/O to the file system should be done synchronously. - MNT_SYNCHRONOUS; - /// Union with underlying fs. - #[cfg(any( - target_os = "macos", - target_os = "freebsd", - target_os = "netbsd" - ))] - MNT_UNION; - /// Indicates that the mount command is being applied to an already - /// mounted file system. - MNT_UPDATE; - /// Check vnode use counts. - #[cfg(target_os = "freebsd")] - MNT_NONBUSY; - } -); - - -/// The Error type of [`Nmount::nmount`]. -/// -/// It wraps an [`Errno`], but also may contain an additional message returned -/// by `nmount(2)`. -#[derive(Debug)] -pub struct NmountError { - errno: Error, - errmsg: Option -} - -impl NmountError { - /// Returns the additional error string sometimes generated by `nmount(2)`. - pub fn errmsg(&self) -> Option<&str> { - self.errmsg.as_deref() - } - - /// Returns the inner [`Error`] - pub const fn error(&self) -> Error { - self.errno - } - - fn new(error: Error, errmsg: Option<&CStr>) -> Self { - Self { - errno: error, - errmsg: errmsg.map(CStr::to_string_lossy).map(Cow::into_owned) - } - } -} - -impl std::error::Error for NmountError {} - -impl fmt::Display for NmountError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if let Some(errmsg) = &self.errmsg { - write!(f, "{:?}: {}: {}", self.errno, errmsg, self.errno.desc()) - } else { - write!(f, "{:?}: {}", self.errno, self.errno.desc()) - } - } -} - -impl From for io::Error { - fn from(err: NmountError) -> Self { - err.errno.into() - } -} - -/// Result type of [`Nmount::nmount`]. -pub type NmountResult = std::result::Result<(), NmountError>; - -/// Mount a FreeBSD file system. -/// -/// The `nmount(2)` system call works similarly to the `mount(8)` program; it -/// takes its options as a series of name-value pairs. Most of the values are -/// strings, as are all of the names. The `Nmount` structure builds up an -/// argument list and then executes the syscall. -/// -/// # Examples -/// -/// To mount `target` onto `mountpoint` with `nullfs`: -/// ``` -/// # use nix::unistd::Uid; -/// # use ::sysctl::CtlValue; -/// # if !Uid::current().is_root() && CtlValue::Int(0) == ::sysctl::value("vfs.usermount").unwrap() { -/// # return; -/// # }; -/// use nix::mount::{MntFlags, Nmount, unmount}; -/// use std::ffi::CString; -/// use tempfile::tempdir; -/// -/// let mountpoint = tempdir().unwrap(); -/// let target = tempdir().unwrap(); -/// -/// let fstype = CString::new("fstype").unwrap(); -/// let nullfs = CString::new("nullfs").unwrap(); -/// Nmount::new() -/// .str_opt(&fstype, &nullfs) -/// .str_opt_owned("fspath", mountpoint.path().to_str().unwrap()) -/// .str_opt_owned("target", target.path().to_str().unwrap()) -/// .nmount(MntFlags::empty()).unwrap(); -/// -/// unmount(mountpoint.path(), MntFlags::empty()).unwrap(); -/// ``` -/// -/// # See Also -/// * [`nmount(2)`](https://www.freebsd.org/cgi/man.cgi?query=nmount) -/// * [`nullfs(5)`](https://www.freebsd.org/cgi/man.cgi?query=nullfs) -#[cfg(target_os = "freebsd")] -#[derive(Debug, Default)] -pub struct Nmount<'a>{ - iov: Vec>, - is_owned: Vec, -} - -#[cfg(target_os = "freebsd")] -impl<'a> Nmount<'a> { - /// Add an opaque mount option. - /// - /// Some file systems take binary-valued mount options. They can be set - /// with this method. - /// - /// # Safety - /// - /// Unsafe because it will cause `Nmount::nmount` to dereference a raw - /// pointer. The user is responsible for ensuring that `val` is valid and - /// its lifetime outlives `self`! An easy way to do that is to give the - /// value a larger scope than `name` - /// - /// # Examples - /// ``` - /// use libc::c_void; - /// use nix::mount::Nmount; - /// use std::ffi::CString; - /// use std::mem; - /// - /// // Note that flags outlives name - /// let mut flags: u32 = 0xdeadbeef; - /// let name = CString::new("flags").unwrap(); - /// let p = &mut flags as *mut u32 as *mut c_void; - /// let len = mem::size_of_val(&flags); - /// let mut nmount = Nmount::new(); - /// unsafe { nmount.mut_ptr_opt(&name, p, len) }; - /// ``` - pub unsafe fn mut_ptr_opt( - &mut self, - name: &'a CStr, - val: *mut c_void, - len: usize - ) -> &mut Self - { - self.iov.push(IoVec::from_slice(name.to_bytes_with_nul())); - self.is_owned.push(false); - self.iov.push(IoVec::from_raw_parts(val, len)); - self.is_owned.push(false); - self - } - - /// Add a mount option that does not take a value. - /// - /// # Examples - /// ``` - /// use nix::mount::Nmount; - /// use std::ffi::CString; - /// - /// let read_only = CString::new("ro").unwrap(); - /// Nmount::new() - /// .null_opt(&read_only); - /// ``` - pub fn null_opt(&mut self, name: &'a CStr) -> &mut Self { - self.iov.push(IoVec::from_slice(name.to_bytes_with_nul())); - self.is_owned.push(false); - self.iov.push(IoVec::from_raw_parts(ptr::null_mut(), 0)); - self.is_owned.push(false); - self - } - - /// Add a mount option that does not take a value, but whose name must be - /// owned. - /// - /// - /// This has higher runtime cost than [`Nmount::null_opt`], but is useful - /// when the name's lifetime doesn't outlive the `Nmount`, or it's a - /// different string type than `CStr`. - /// - /// # Examples - /// ``` - /// use nix::mount::Nmount; - /// - /// let read_only = "ro"; - /// let mut nmount: Nmount<'static> = Nmount::new(); - /// nmount.null_opt_owned(read_only); - /// ``` - pub fn null_opt_owned(&mut self, name: &P) -> &mut Self - { - name.with_nix_path(|s| { - let len = s.to_bytes_with_nul().len(); - self.iov.push(IoVec::from_raw_parts( - // Must free it later - s.to_owned().into_raw() as *mut c_void, - len - )); - self.is_owned.push(true); - }).unwrap(); - self.iov.push(IoVec::from_raw_parts(ptr::null_mut(), 0)); - self.is_owned.push(false); - self - } - - /// Add a mount option as a [`CStr`]. - /// - /// # Examples - /// ``` - /// use nix::mount::Nmount; - /// use std::ffi::CString; - /// - /// let fstype = CString::new("fstype").unwrap(); - /// let nullfs = CString::new("nullfs").unwrap(); - /// Nmount::new() - /// .str_opt(&fstype, &nullfs); - /// ``` - pub fn str_opt( - &mut self, - name: &'a CStr, - val: &'a CStr - ) -> &mut Self - { - self.iov.push(IoVec::from_slice(name.to_bytes_with_nul())); - self.is_owned.push(false); - self.iov.push(IoVec::from_slice(val.to_bytes_with_nul())); - self.is_owned.push(false); - self - } - - /// Add a mount option as an owned string. - /// - /// This has higher runtime cost than [`Nmount::str_opt`], but is useful - /// when the value's lifetime doesn't outlive the `Nmount`, or it's a - /// different string type than `CStr`. - /// - /// # Examples - /// ``` - /// use nix::mount::Nmount; - /// use std::path::Path; - /// - /// let mountpoint = Path::new("/mnt"); - /// Nmount::new() - /// .str_opt_owned("fspath", mountpoint.to_str().unwrap()); - /// ``` - pub fn str_opt_owned(&mut self, name: &P1, val: &P2) -> &mut Self - where P1: ?Sized + NixPath, - P2: ?Sized + NixPath - { - name.with_nix_path(|s| { - let len = s.to_bytes_with_nul().len(); - self.iov.push(IoVec::from_raw_parts( - // Must free it later - s.to_owned().into_raw() as *mut c_void, - len - )); - self.is_owned.push(true); - }).unwrap(); - val.with_nix_path(|s| { - let len = s.to_bytes_with_nul().len(); - self.iov.push(IoVec::from_raw_parts( - // Must free it later - s.to_owned().into_raw() as *mut c_void, - len - )); - self.is_owned.push(true); - }).unwrap(); - self - } - - /// Create a new `Nmount` struct with no options - pub fn new() -> Self { - Self::default() - } - - /// Actually mount the file system. - pub fn nmount(&mut self, flags: MntFlags) -> NmountResult { - // nmount can return extra error information via a "errmsg" return - // argument. - const ERRMSG_NAME: &[u8] = b"errmsg\0"; - let mut errmsg = vec![0u8; 255]; - self.iov.push(IoVec::from_raw_parts( - ERRMSG_NAME.as_ptr() as *mut c_void, - ERRMSG_NAME.len() - )); - self.iov.push(IoVec::from_raw_parts( - errmsg.as_mut_ptr() as *mut c_void, - errmsg.len() - )); - - let niov = self.iov.len() as c_uint; - let iovp = self.iov.as_mut_ptr() as *mut libc::iovec; - let res = unsafe { - libc::nmount(iovp, niov, flags.bits) - }; - match Errno::result(res) { - Ok(_) => Ok(()), - Err(error) => { - let errmsg = match errmsg.iter().position(|&x| x == 0) { - None => None, - Some(0) => None, - Some(n) => { - let sl = &errmsg[0..n + 1]; - Some(CStr::from_bytes_with_nul(sl).unwrap()) - } - }; - Err(NmountError::new(error, errmsg)) - } - } - } -} - -#[cfg(target_os = "freebsd")] -impl<'a> Drop for Nmount<'a> { - fn drop(&mut self) { - for (iov, is_owned) in self.iov.iter().zip(self.is_owned.iter()) { - if *is_owned { - // Free the owned string. Safe because we recorded ownership, - // and Nmount does not implement Clone. - unsafe { - drop(CString::from_raw(iov.0.iov_base as *mut c_char)); - } - } - } - } -} - -/// Unmount the file system mounted at `mountpoint`. -/// -/// Useful flags include -/// * `MNT_FORCE` - Unmount even if still in use. -/// * `MNT_BYFSID` - `mountpoint` is not a path, but a file system ID -/// encoded as `FSID:val0:val1`, where `val0` and `val1` -/// are the contents of the `fsid_t val[]` array in decimal. -/// The file system that has the specified file system ID -/// will be unmounted. See -/// [`statfs`](crate::sys::statfs::statfs) to determine the -/// `fsid`. -pub fn unmount

(mountpoint: &P, flags: MntFlags) -> Result<()> - where P: ?Sized + NixPath -{ - let res = mountpoint.with_nix_path(|cstr| { - unsafe { libc::unmount(cstr.as_ptr(), flags.bits) } - })?; - - Errno::result(res).map(drop) -} diff --git a/vendor/nix-v0.23.1-patched/src/mount/linux.rs b/vendor/nix-v0.23.1-patched/src/mount/linux.rs deleted file mode 100644 index 4cb2fa549..000000000 --- a/vendor/nix-v0.23.1-patched/src/mount/linux.rs +++ /dev/null @@ -1,111 +0,0 @@ -#![allow(missing_docs)] -use libc::{self, c_ulong, c_int}; -use crate::{Result, NixPath}; -use crate::errno::Errno; - -libc_bitflags!( - pub struct MsFlags: c_ulong { - /// Mount read-only - MS_RDONLY; - /// Ignore suid and sgid bits - MS_NOSUID; - /// Disallow access to device special files - MS_NODEV; - /// Disallow program execution - MS_NOEXEC; - /// Writes are synced at once - MS_SYNCHRONOUS; - /// Alter flags of a mounted FS - MS_REMOUNT; - /// Allow mandatory locks on a FS - MS_MANDLOCK; - /// Directory modifications are synchronous - MS_DIRSYNC; - /// Do not update access times - MS_NOATIME; - /// Do not update directory access times - MS_NODIRATIME; - /// Linux 2.4.0 - Bind directory at different place - MS_BIND; - MS_MOVE; - MS_REC; - MS_SILENT; - MS_POSIXACL; - MS_UNBINDABLE; - MS_PRIVATE; - MS_SLAVE; - MS_SHARED; - MS_RELATIME; - MS_KERNMOUNT; - MS_I_VERSION; - MS_STRICTATIME; - MS_LAZYTIME; - MS_ACTIVE; - MS_NOUSER; - MS_RMT_MASK; - MS_MGC_VAL; - MS_MGC_MSK; - } -); - -libc_bitflags!( - pub struct MntFlags: c_int { - MNT_FORCE; - MNT_DETACH; - MNT_EXPIRE; - } -); - -pub fn mount( - source: Option<&P1>, - target: &P2, - fstype: Option<&P3>, - flags: MsFlags, - data: Option<&P4>) -> Result<()> { - - fn with_opt_nix_path(p: Option<&P>, f: F) -> Result - where P: ?Sized + NixPath, - F: FnOnce(*const libc::c_char) -> T - { - match p { - Some(path) => path.with_nix_path(|p_str| f(p_str.as_ptr())), - None => Ok(f(std::ptr::null())) - } - } - - let res = with_opt_nix_path(source, |s| { - target.with_nix_path(|t| { - with_opt_nix_path(fstype, |ty| { - with_opt_nix_path(data, |d| { - unsafe { - libc::mount( - s, - t.as_ptr(), - ty, - flags.bits, - d as *const libc::c_void - ) - } - }) - }) - }) - })????; - - Errno::result(res).map(drop) -} - -pub fn umount(target: &P) -> Result<()> { - let res = target.with_nix_path(|cstr| { - unsafe { libc::umount(cstr.as_ptr()) } - })?; - - Errno::result(res).map(drop) -} - -pub fn umount2(target: &P, flags: MntFlags) -> Result<()> { - let res = target.with_nix_path(|cstr| { - unsafe { libc::umount2(cstr.as_ptr(), flags.bits) } - })?; - - Errno::result(res).map(drop) -} diff --git a/vendor/nix-v0.23.1-patched/src/mount/mod.rs b/vendor/nix-v0.23.1-patched/src/mount/mod.rs deleted file mode 100644 index 14bf2a963..000000000 --- a/vendor/nix-v0.23.1-patched/src/mount/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -//! Mount file systems -#[cfg(any(target_os = "android", target_os = "linux"))] -mod linux; - -#[cfg(any(target_os = "android", target_os = "linux"))] -pub use self::linux::*; - -#[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] -mod bsd; - -#[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd" - ))] -pub use self::bsd::*; diff --git a/vendor/nix-v0.23.1-patched/src/mqueue.rs b/vendor/nix-v0.23.1-patched/src/mqueue.rs deleted file mode 100644 index 34fd80278..000000000 --- a/vendor/nix-v0.23.1-patched/src/mqueue.rs +++ /dev/null @@ -1,178 +0,0 @@ -//! Posix Message Queue functions -//! -//! [Further reading and details on the C API](https://man7.org/linux/man-pages/man7/mq_overview.7.html) - -use crate::Result; -use crate::errno::Errno; - -use libc::{self, c_char, mqd_t, size_t}; -use std::ffi::CString; -use crate::sys::stat::Mode; -use std::mem; - -libc_bitflags!{ - pub struct MQ_OFlag: libc::c_int { - O_RDONLY; - O_WRONLY; - O_RDWR; - O_CREAT; - O_EXCL; - O_NONBLOCK; - O_CLOEXEC; - } -} - -libc_bitflags!{ - pub struct FdFlag: libc::c_int { - FD_CLOEXEC; - } -} - -#[repr(C)] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct MqAttr { - mq_attr: libc::mq_attr, -} - -// x32 compatibility -// See https://sourceware.org/bugzilla/show_bug.cgi?id=21279 -#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] -pub type mq_attr_member_t = i64; -#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] -pub type mq_attr_member_t = libc::c_long; - -impl MqAttr { - pub fn new(mq_flags: mq_attr_member_t, - mq_maxmsg: mq_attr_member_t, - mq_msgsize: mq_attr_member_t, - mq_curmsgs: mq_attr_member_t) - -> MqAttr - { - let mut attr = mem::MaybeUninit::::uninit(); - unsafe { - let p = attr.as_mut_ptr(); - (*p).mq_flags = mq_flags; - (*p).mq_maxmsg = mq_maxmsg; - (*p).mq_msgsize = mq_msgsize; - (*p).mq_curmsgs = mq_curmsgs; - MqAttr { mq_attr: attr.assume_init() } - } - } - - pub const fn flags(&self) -> mq_attr_member_t { - self.mq_attr.mq_flags - } -} - - -/// Open a message queue -/// -/// See also [`mq_open(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html) -// The mode.bits cast is only lossless on some OSes -#[allow(clippy::cast_lossless)] -pub fn mq_open(name: &CString, - oflag: MQ_OFlag, - mode: Mode, - attr: Option<&MqAttr>) - -> Result { - let res = match attr { - Some(mq_attr) => unsafe { - libc::mq_open(name.as_ptr(), - oflag.bits(), - mode.bits() as libc::c_int, - &mq_attr.mq_attr as *const libc::mq_attr) - }, - None => unsafe { libc::mq_open(name.as_ptr(), oflag.bits()) }, - }; - Errno::result(res) -} - -/// Remove a message queue -/// -/// See also [`mq_unlink(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_unlink.html) -pub fn mq_unlink(name: &CString) -> Result<()> { - let res = unsafe { libc::mq_unlink(name.as_ptr()) }; - Errno::result(res).map(drop) -} - -/// Close a message queue -/// -/// See also [`mq_close(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_close.html) -pub fn mq_close(mqdes: mqd_t) -> Result<()> { - let res = unsafe { libc::mq_close(mqdes) }; - Errno::result(res).map(drop) -} - -/// Receive a message from a message queue -/// -/// See also [`mq_receive(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html) -pub fn mq_receive(mqdes: mqd_t, message: &mut [u8], msg_prio: &mut u32) -> Result { - let len = message.len() as size_t; - let res = unsafe { - libc::mq_receive(mqdes, - message.as_mut_ptr() as *mut c_char, - len, - msg_prio as *mut u32) - }; - Errno::result(res).map(|r| r as usize) -} - -/// Send a message to a message queue -/// -/// See also [`mq_send(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html) -pub fn mq_send(mqdes: mqd_t, message: &[u8], msq_prio: u32) -> Result<()> { - let res = unsafe { - libc::mq_send(mqdes, - message.as_ptr() as *const c_char, - message.len(), - msq_prio) - }; - Errno::result(res).map(drop) -} - -/// Get message queue attributes -/// -/// See also [`mq_getattr(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_getattr.html) -pub fn mq_getattr(mqd: mqd_t) -> Result { - let mut attr = mem::MaybeUninit::::uninit(); - let res = unsafe { libc::mq_getattr(mqd, attr.as_mut_ptr()) }; - Errno::result(res).map(|_| unsafe{MqAttr { mq_attr: attr.assume_init() }}) -} - -/// Set the attributes of the message queue. Only `O_NONBLOCK` can be set, everything else will be ignored -/// Returns the old attributes -/// It is recommend to use the `mq_set_nonblock()` and `mq_remove_nonblock()` convenience functions as they are easier to use -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_setattr.html) -pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result { - let mut attr = mem::MaybeUninit::::uninit(); - let res = unsafe { - libc::mq_setattr(mqd, &newattr.mq_attr as *const libc::mq_attr, attr.as_mut_ptr()) - }; - Errno::result(res).map(|_| unsafe{ MqAttr { mq_attr: attr.assume_init() }}) -} - -/// Convenience function. -/// Sets the `O_NONBLOCK` attribute for a given message queue descriptor -/// Returns the old attributes -#[allow(clippy::useless_conversion)] // Not useless on all OSes -pub fn mq_set_nonblock(mqd: mqd_t) -> Result { - let oldattr = mq_getattr(mqd)?; - let newattr = MqAttr::new(mq_attr_member_t::from(MQ_OFlag::O_NONBLOCK.bits()), - oldattr.mq_attr.mq_maxmsg, - oldattr.mq_attr.mq_msgsize, - oldattr.mq_attr.mq_curmsgs); - mq_setattr(mqd, &newattr) -} - -/// Convenience function. -/// Removes `O_NONBLOCK` attribute for a given message queue descriptor -/// Returns the old attributes -pub fn mq_remove_nonblock(mqd: mqd_t) -> Result { - let oldattr = mq_getattr(mqd)?; - let newattr = MqAttr::new(0, - oldattr.mq_attr.mq_maxmsg, - oldattr.mq_attr.mq_msgsize, - oldattr.mq_attr.mq_curmsgs); - mq_setattr(mqd, &newattr) -} diff --git a/vendor/nix-v0.23.1-patched/src/net/if_.rs b/vendor/nix-v0.23.1-patched/src/net/if_.rs deleted file mode 100644 index bc00a4328..000000000 --- a/vendor/nix-v0.23.1-patched/src/net/if_.rs +++ /dev/null @@ -1,411 +0,0 @@ -//! Network interface name resolution. -//! -//! Uses Linux and/or POSIX functions to resolve interface names like "eth0" -//! or "socan1" into device numbers. - -use crate::{Error, NixPath, Result}; -use libc::c_uint; - -/// Resolve an interface into a interface number. -pub fn if_nametoindex(name: &P) -> Result { - let if_index = name.with_nix_path(|name| unsafe { libc::if_nametoindex(name.as_ptr()) })?; - - if if_index == 0 { - Err(Error::last()) - } else { - Ok(if_index) - } -} - -libc_bitflags!( - /// Standard interface flags, used by `getifaddrs` - pub struct InterfaceFlags: libc::c_int { - /// Interface is running. (see - /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) - IFF_UP; - /// Valid broadcast address set. (see - /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) - IFF_BROADCAST; - /// Internal debugging flag. (see - /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) - IFF_DEBUG; - /// Interface is a loopback interface. (see - /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) - IFF_LOOPBACK; - /// Interface is a point-to-point link. (see - /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) - IFF_POINTOPOINT; - /// Avoid use of trailers. (see - /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) - #[cfg(any(target_os = "android", - target_os = "fuchsia", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "illumos", - target_os = "solaris"))] - IFF_NOTRAILERS; - /// Interface manages own routes. - #[cfg(any(target_os = "dragonfly"))] - IFF_SMART; - /// Resources allocated. (see - /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) - #[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "fuchsia", - target_os = "illumos", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris"))] - IFF_RUNNING; - /// No arp protocol, L2 destination address not set. (see - /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) - IFF_NOARP; - /// Interface is in promiscuous mode. (see - /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) - IFF_PROMISC; - /// Receive all multicast packets. (see - /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) - IFF_ALLMULTI; - /// Master of a load balancing bundle. (see - /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] - IFF_MASTER; - /// transmission in progress, tx hardware queue is full - #[cfg(any(target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "ios"))] - IFF_OACTIVE; - /// Protocol code on board. - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_INTELLIGENT; - /// Slave of a load balancing bundle. (see - /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] - IFF_SLAVE; - /// Can't hear own transmissions. - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "osx"))] - IFF_SIMPLEX; - /// Supports multicast. (see - /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) - IFF_MULTICAST; - /// Per link layer defined bit. - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "ios"))] - IFF_LINK0; - /// Multicast using broadcast. - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_MULTI_BCAST; - /// Is able to select media type via ifmap. (see - /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] - IFF_PORTSEL; - /// Per link layer defined bit. - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "ios"))] - IFF_LINK1; - /// Non-unique address. - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_UNNUMBERED; - /// Auto media selection active. (see - /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] - IFF_AUTOMEDIA; - /// Per link layer defined bit. - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "ios"))] - IFF_LINK2; - /// Use alternate physical connection. - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "ios"))] - IFF_ALTPHYS; - /// DHCP controls interface. - #[cfg(any(target_os = "solaris", target_os = "illumos"))] - IFF_DHCPRUNNING; - /// The addresses are lost when the interface goes down. (see - /// [`netdevice(7)`](https://man7.org/linux/man-pages/man7/netdevice.7.html)) - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] - IFF_DYNAMIC; - /// Do not advertise. - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_PRIVATE; - /// Driver signals L1 up. Volatile. - #[cfg(any(target_os = "fuchsia", target_os = "linux"))] - IFF_LOWER_UP; - /// Interface is in polling mode. - #[cfg(any(target_os = "dragonfly"))] - IFF_POLLING_COMPAT; - /// Unconfigurable using ioctl(2). - #[cfg(any(target_os = "freebsd"))] - IFF_CANTCONFIG; - /// Do not transmit packets. - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_NOXMIT; - /// Driver signals dormant. Volatile. - #[cfg(any(target_os = "fuchsia", target_os = "linux"))] - IFF_DORMANT; - /// User-requested promisc mode. - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - IFF_PPROMISC; - /// Just on-link subnet. - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_NOLOCAL; - /// Echo sent packets. Volatile. - #[cfg(any(target_os = "fuchsia", target_os = "linux"))] - IFF_ECHO; - /// User-requested monitor mode. - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - IFF_MONITOR; - /// Address is deprecated. - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_DEPRECATED; - /// Static ARP. - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - IFF_STATICARP; - /// Address from stateless addrconf. - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_ADDRCONF; - /// Interface is in polling mode. - #[cfg(any(target_os = "dragonfly"))] - IFF_NPOLLING; - /// Router on interface. - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_ROUTER; - /// Interface is in polling mode. - #[cfg(any(target_os = "dragonfly"))] - IFF_IDIRECT; - /// Interface is winding down - #[cfg(any(target_os = "freebsd"))] - IFF_DYING; - /// No NUD on interface. - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_NONUD; - /// Interface is being renamed - #[cfg(any(target_os = "freebsd"))] - IFF_RENAMING; - /// Anycast address. - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_ANYCAST; - /// Don't exchange routing info. - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_NORTEXCH; - /// Do not provide packet information - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] - IFF_NO_PI as libc::c_int; - /// TUN device (no Ethernet headers) - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] - IFF_TUN as libc::c_int; - /// TAP device - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] - IFF_TAP as libc::c_int; - /// IPv4 interface. - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_IPV4; - /// IPv6 interface. - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_IPV6; - /// in.mpathd test address - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_NOFAILOVER; - /// Interface has failed - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_FAILED; - /// Interface is a hot-spare - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_STANDBY; - /// Functioning but not used - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_INACTIVE; - /// Interface is offline - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - IFF_OFFLINE; - #[cfg(target_os = "solaris")] - IFF_COS_ENABLED; - /// Prefer as source addr. - #[cfg(target_os = "solaris")] - IFF_PREFERRED; - /// RFC3041 - #[cfg(target_os = "solaris")] - IFF_TEMPORARY; - /// MTU set with SIOCSLIFMTU - #[cfg(target_os = "solaris")] - IFF_FIXEDMTU; - /// Cannot send / receive packets - #[cfg(target_os = "solaris")] - IFF_VIRTUAL; - /// Local address in use - #[cfg(target_os = "solaris")] - IFF_DUPLICATE; - /// IPMP IP interface - #[cfg(target_os = "solaris")] - IFF_IPMP; - } -); - -#[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "fuchsia", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -))] -mod if_nameindex { - use super::*; - - use std::ffi::CStr; - use std::fmt; - use std::marker::PhantomData; - use std::ptr::NonNull; - - /// A network interface. Has a name like "eth0" or "wlp4s0" or "wlan0", as well as an index - /// (1, 2, 3, etc) that identifies it in the OS's networking stack. - #[allow(missing_copy_implementations)] - #[repr(transparent)] - pub struct Interface(libc::if_nameindex); - - impl Interface { - /// Obtain the index of this interface. - pub fn index(&self) -> c_uint { - self.0.if_index - } - - /// Obtain the name of this interface. - pub fn name(&self) -> &CStr { - unsafe { CStr::from_ptr(self.0.if_name) } - } - } - - impl fmt::Debug for Interface { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Interface") - .field("index", &self.index()) - .field("name", &self.name()) - .finish() - } - } - - /// A list of the network interfaces available on this system. Obtained from [`if_nameindex()`]. - pub struct Interfaces { - ptr: NonNull, - } - - impl Interfaces { - /// Iterate over the interfaces in this list. - #[inline] - pub fn iter(&self) -> InterfacesIter<'_> { - self.into_iter() - } - - /// Convert this to a slice of interfaces. Note that the underlying interfaces list is - /// null-terminated, so calling this calculates the length. If random access isn't needed, - /// [`Interfaces::iter()`] should be used instead. - pub fn to_slice(&self) -> &[Interface] { - let ifs = self.ptr.as_ptr() as *const Interface; - let len = self.iter().count(); - unsafe { std::slice::from_raw_parts(ifs, len) } - } - } - - impl Drop for Interfaces { - fn drop(&mut self) { - unsafe { libc::if_freenameindex(self.ptr.as_ptr()) }; - } - } - - impl fmt::Debug for Interfaces { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.to_slice().fmt(f) - } - } - - impl<'a> IntoIterator for &'a Interfaces { - type IntoIter = InterfacesIter<'a>; - type Item = &'a Interface; - #[inline] - fn into_iter(self) -> Self::IntoIter { - InterfacesIter { - ptr: self.ptr.as_ptr(), - _marker: PhantomData, - } - } - } - - /// An iterator over the interfaces in an [`Interfaces`]. - #[derive(Debug)] - pub struct InterfacesIter<'a> { - ptr: *const libc::if_nameindex, - _marker: PhantomData<&'a Interfaces>, - } - - impl<'a> Iterator for InterfacesIter<'a> { - type Item = &'a Interface; - #[inline] - fn next(&mut self) -> Option { - unsafe { - if (*self.ptr).if_index == 0 { - None - } else { - let ret = &*(self.ptr as *const Interface); - self.ptr = self.ptr.add(1); - Some(ret) - } - } - } - } - - /// Retrieve a list of the network interfaces available on the local system. - /// - /// ``` - /// let interfaces = nix::net::if_::if_nameindex().unwrap(); - /// for iface in &interfaces { - /// println!("Interface #{} is called {}", iface.index(), iface.name().to_string_lossy()); - /// } - /// ``` - pub fn if_nameindex() -> Result { - unsafe { - let ifs = libc::if_nameindex(); - let ptr = NonNull::new(ifs).ok_or_else(Error::last)?; - Ok(Interfaces { ptr }) - } - } -} -#[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "fuchsia", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -))] -pub use if_nameindex::*; diff --git a/vendor/nix-v0.23.1-patched/src/net/mod.rs b/vendor/nix-v0.23.1-patched/src/net/mod.rs deleted file mode 100644 index 079fcfde6..000000000 --- a/vendor/nix-v0.23.1-patched/src/net/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -//! Functionality involving network interfaces -// To avoid clashing with the keyword "if", we use "if_" as the module name. -// The original header is called "net/if.h". -pub mod if_; diff --git a/vendor/nix-v0.23.1-patched/src/poll.rs b/vendor/nix-v0.23.1-patched/src/poll.rs deleted file mode 100644 index 8556c1bb7..000000000 --- a/vendor/nix-v0.23.1-patched/src/poll.rs +++ /dev/null @@ -1,163 +0,0 @@ -//! Wait for events to trigger on specific file descriptors -#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))] -use crate::sys::time::TimeSpec; -#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))] -use crate::sys::signal::SigSet; -use std::os::unix::io::{AsRawFd, RawFd}; - -use crate::Result; -use crate::errno::Errno; - -/// This is a wrapper around `libc::pollfd`. -/// -/// It's meant to be used as an argument to the [`poll`](fn.poll.html) and -/// [`ppoll`](fn.ppoll.html) functions to specify the events of interest -/// for a specific file descriptor. -/// -/// After a call to `poll` or `ppoll`, the events that occured can be -/// retrieved by calling [`revents()`](#method.revents) on the `PollFd`. -#[repr(transparent)] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct PollFd { - pollfd: libc::pollfd, -} - -impl PollFd { - /// Creates a new `PollFd` specifying the events of interest - /// for a given file descriptor. - pub const fn new(fd: RawFd, events: PollFlags) -> PollFd { - PollFd { - pollfd: libc::pollfd { - fd, - events: events.bits(), - revents: PollFlags::empty().bits(), - }, - } - } - - /// Returns the events that occured in the last call to `poll` or `ppoll`. Will only return - /// `None` if the kernel provides status flags that Nix does not know about. - pub fn revents(self) -> Option { - PollFlags::from_bits(self.pollfd.revents) - } - - /// The events of interest for this `PollFd`. - pub fn events(self) -> PollFlags { - PollFlags::from_bits(self.pollfd.events).unwrap() - } - - /// Modify the events of interest for this `PollFd`. - pub fn set_events(&mut self, events: PollFlags) { - self.pollfd.events = events.bits(); - } -} - -impl AsRawFd for PollFd { - fn as_raw_fd(&self) -> RawFd { - self.pollfd.fd - } -} - -libc_bitflags! { - /// These flags define the different events that can be monitored by `poll` and `ppoll` - pub struct PollFlags: libc::c_short { - /// There is data to read. - POLLIN; - /// There is some exceptional condition on the file descriptor. - /// - /// Possibilities include: - /// - /// * There is out-of-band data on a TCP socket (see - /// [tcp(7)](https://man7.org/linux/man-pages/man7/tcp.7.html)). - /// * A pseudoterminal master in packet mode has seen a state - /// change on the slave (see - /// [ioctl_tty(2)](https://man7.org/linux/man-pages/man2/ioctl_tty.2.html)). - /// * A cgroup.events file has been modified (see - /// [cgroups(7)](https://man7.org/linux/man-pages/man7/cgroups.7.html)). - POLLPRI; - /// Writing is now possible, though a write larger that the - /// available space in a socket or pipe will still block (unless - /// `O_NONBLOCK` is set). - POLLOUT; - /// Equivalent to [`POLLIN`](constant.POLLIN.html) - #[cfg(not(target_os = "redox"))] - POLLRDNORM; - #[cfg(not(target_os = "redox"))] - /// Equivalent to [`POLLOUT`](constant.POLLOUT.html) - POLLWRNORM; - /// Priority band data can be read (generally unused on Linux). - #[cfg(not(target_os = "redox"))] - POLLRDBAND; - /// Priority data may be written. - #[cfg(not(target_os = "redox"))] - POLLWRBAND; - /// Error condition (only returned in - /// [`PollFd::revents`](struct.PollFd.html#method.revents); - /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)). - /// This bit is also set for a file descriptor referring to the - /// write end of a pipe when the read end has been closed. - POLLERR; - /// Hang up (only returned in [`PollFd::revents`](struct.PollFd.html#method.revents); - /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)). - /// Note that when reading from a channel such as a pipe or a stream - /// socket, this event merely indicates that the peer closed its - /// end of the channel. Subsequent reads from the channel will - /// return 0 (end of file) only after all outstanding data in the - /// channel has been consumed. - POLLHUP; - /// Invalid request: `fd` not open (only returned in - /// [`PollFd::revents`](struct.PollFd.html#method.revents); - /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)). - POLLNVAL; - } -} - -/// `poll` waits for one of a set of file descriptors to become ready to perform I/O. -/// ([`poll(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html)) -/// -/// `fds` contains all [`PollFd`](struct.PollFd.html) to poll. -/// The function will return as soon as any event occur for any of these `PollFd`s. -/// -/// The `timeout` argument specifies the number of milliseconds that `poll()` -/// should block waiting for a file descriptor to become ready. The call -/// will block until either: -/// -/// * a file descriptor becomes ready; -/// * the call is interrupted by a signal handler; or -/// * the timeout expires. -/// -/// Note that the timeout interval will be rounded up to the system clock -/// granularity, and kernel scheduling delays mean that the blocking -/// interval may overrun by a small amount. Specifying a negative value -/// in timeout means an infinite timeout. Specifying a timeout of zero -/// causes `poll()` to return immediately, even if no file descriptors are -/// ready. -pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result { - let res = unsafe { - libc::poll(fds.as_mut_ptr() as *mut libc::pollfd, - fds.len() as libc::nfds_t, - timeout) - }; - - Errno::result(res) -} - -/// `ppoll()` allows an application to safely wait until either a file -/// descriptor becomes ready or until a signal is caught. -/// ([`poll(2)`](https://man7.org/linux/man-pages/man2/poll.2.html)) -/// -/// `ppoll` behaves like `poll`, but let you specify what signals may interrupt it -/// with the `sigmask` argument. If you want `ppoll` to block indefinitely, -/// specify `None` as `timeout` (it is like `timeout = -1` for `poll`). -/// -#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))] -pub fn ppoll(fds: &mut [PollFd], timeout: Option, sigmask: SigSet) -> Result { - let timeout = timeout.as_ref().map_or(core::ptr::null(), |r| r.as_ref()); - let res = unsafe { - libc::ppoll(fds.as_mut_ptr() as *mut libc::pollfd, - fds.len() as libc::nfds_t, - timeout, - sigmask.as_ref()) - }; - Errno::result(res) -} diff --git a/vendor/nix-v0.23.1-patched/src/pty.rs b/vendor/nix-v0.23.1-patched/src/pty.rs deleted file mode 100644 index facc9aaf4..000000000 --- a/vendor/nix-v0.23.1-patched/src/pty.rs +++ /dev/null @@ -1,348 +0,0 @@ -//! Create master and slave virtual pseudo-terminals (PTYs) - -pub use libc::pid_t as SessionId; -pub use libc::winsize as Winsize; - -use std::ffi::CStr; -use std::io; -use std::mem; -use std::os::unix::prelude::*; - -use crate::sys::termios::Termios; -use crate::unistd::{self, ForkResult, Pid}; -use crate::{Result, fcntl}; -use crate::errno::Errno; - -/// Representation of a master/slave pty pair -/// -/// This is returned by `openpty`. Note that this type does *not* implement `Drop`, so the user -/// must manually close the file descriptors. -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct OpenptyResult { - /// The master port in a virtual pty pair - pub master: RawFd, - /// The slave port in a virtual pty pair - pub slave: RawFd, -} - -/// Representation of a master with a forked pty -/// -/// This is returned by `forkpty`. Note that this type does *not* implement `Drop`, so the user -/// must manually close the file descriptors. -#[derive(Clone, Copy, Debug)] -pub struct ForkptyResult { - /// The master port in a virtual pty pair - pub master: RawFd, - /// Metadata about forked process - pub fork_result: ForkResult, -} - - -/// Representation of the Master device in a master/slave pty pair -/// -/// While this datatype is a thin wrapper around `RawFd`, it enforces that the available PTY -/// functions are given the correct file descriptor. Additionally this type implements `Drop`, -/// so that when it's consumed or goes out of scope, it's automatically cleaned-up. -#[derive(Debug, Eq, Hash, PartialEq)] -pub struct PtyMaster(RawFd); - -impl AsRawFd for PtyMaster { - fn as_raw_fd(&self) -> RawFd { - self.0 - } -} - -impl IntoRawFd for PtyMaster { - fn into_raw_fd(self) -> RawFd { - let fd = self.0; - mem::forget(self); - fd - } -} - -impl Drop for PtyMaster { - fn drop(&mut self) { - // On drop, we ignore errors like EINTR and EIO because there's no clear - // way to handle them, we can't return anything, and (on FreeBSD at - // least) the file descriptor is deallocated in these cases. However, - // we must panic on EBADF, because it is always an error to close an - // invalid file descriptor. That frequently indicates a double-close - // condition, which can cause confusing errors for future I/O - // operations. - let e = unistd::close(self.0); - if e == Err(Errno::EBADF) { - panic!("Closing an invalid file descriptor!"); - }; - } -} - -impl io::Read for PtyMaster { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - unistd::read(self.0, buf).map_err(io::Error::from) - } -} - -impl io::Write for PtyMaster { - fn write(&mut self, buf: &[u8]) -> io::Result { - unistd::write(self.0, buf).map_err(io::Error::from) - } - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -/// Grant access to a slave pseudoterminal (see -/// [`grantpt(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/grantpt.html)) -/// -/// `grantpt()` changes the mode and owner of the slave pseudoterminal device corresponding to the -/// master pseudoterminal referred to by `fd`. This is a necessary step towards opening the slave. -#[inline] -pub fn grantpt(fd: &PtyMaster) -> Result<()> { - if unsafe { libc::grantpt(fd.as_raw_fd()) } < 0 { - return Err(Errno::last()); - } - - Ok(()) -} - -/// Open a pseudoterminal device (see -/// [`posix_openpt(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_openpt.html)) -/// -/// `posix_openpt()` returns a file descriptor to an existing unused pseuterminal master device. -/// -/// # Examples -/// -/// A common use case with this function is to open both a master and slave PTY pair. This can be -/// done as follows: -/// -/// ``` -/// use std::path::Path; -/// use nix::fcntl::{OFlag, open}; -/// use nix::pty::{grantpt, posix_openpt, ptsname, unlockpt}; -/// use nix::sys::stat::Mode; -/// -/// # #[allow(dead_code)] -/// # fn run() -> nix::Result<()> { -/// // Open a new PTY master -/// let master_fd = posix_openpt(OFlag::O_RDWR)?; -/// -/// // Allow a slave to be generated for it -/// grantpt(&master_fd)?; -/// unlockpt(&master_fd)?; -/// -/// // Get the name of the slave -/// let slave_name = unsafe { ptsname(&master_fd) }?; -/// -/// // Try to open the slave -/// let _slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, Mode::empty())?; -/// # Ok(()) -/// # } -/// ``` -#[inline] -pub fn posix_openpt(flags: fcntl::OFlag) -> Result { - let fd = unsafe { - libc::posix_openpt(flags.bits()) - }; - - if fd < 0 { - return Err(Errno::last()); - } - - Ok(PtyMaster(fd)) -} - -/// Get the name of the slave pseudoterminal (see -/// [`ptsname(3)`](https://man7.org/linux/man-pages/man3/ptsname.3.html)) -/// -/// `ptsname()` returns the name of the slave pseudoterminal device corresponding to the master -/// referred to by `fd`. -/// -/// This value is useful for opening the slave pty once the master has already been opened with -/// `posix_openpt()`. -/// -/// # Safety -/// -/// `ptsname()` mutates global variables and is *not* threadsafe. -/// Mutating global variables is always considered `unsafe` by Rust and this -/// function is marked as `unsafe` to reflect that. -/// -/// For a threadsafe and non-`unsafe` alternative on Linux, see `ptsname_r()`. -#[inline] -pub unsafe fn ptsname(fd: &PtyMaster) -> Result { - let name_ptr = libc::ptsname(fd.as_raw_fd()); - if name_ptr.is_null() { - return Err(Errno::last()); - } - - let name = CStr::from_ptr(name_ptr); - Ok(name.to_string_lossy().into_owned()) -} - -/// Get the name of the slave pseudoterminal (see -/// [`ptsname(3)`](https://man7.org/linux/man-pages/man3/ptsname.3.html)) -/// -/// `ptsname_r()` returns the name of the slave pseudoterminal device corresponding to the master -/// referred to by `fd`. This is the threadsafe version of `ptsname()`, but it is not part of the -/// POSIX standard and is instead a Linux-specific extension. -/// -/// This value is useful for opening the slave ptty once the master has already been opened with -/// `posix_openpt()`. -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -pub fn ptsname_r(fd: &PtyMaster) -> Result { - let mut name_buf = Vec::::with_capacity(64); - let name_buf_ptr = name_buf.as_mut_ptr(); - let cname = unsafe { - let cap = name_buf.capacity(); - if libc::ptsname_r(fd.as_raw_fd(), name_buf_ptr, cap) != 0 { - return Err(crate::Error::last()); - } - CStr::from_ptr(name_buf.as_ptr()) - }; - - let name = cname.to_string_lossy().into_owned(); - Ok(name) -} - -/// Unlock a pseudoterminal master/slave pseudoterminal pair (see -/// [`unlockpt(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlockpt.html)) -/// -/// `unlockpt()` unlocks the slave pseudoterminal device corresponding to the master pseudoterminal -/// referred to by `fd`. This must be called before trying to open the slave side of a -/// pseuoterminal. -#[inline] -pub fn unlockpt(fd: &PtyMaster) -> Result<()> { - if unsafe { libc::unlockpt(fd.as_raw_fd()) } < 0 { - return Err(Errno::last()); - } - - Ok(()) -} - - -/// Create a new pseudoterminal, returning the slave and master file descriptors -/// in `OpenptyResult` -/// (see [`openpty`](https://man7.org/linux/man-pages/man3/openpty.3.html)). -/// -/// If `winsize` is not `None`, the window size of the slave will be set to -/// the values in `winsize`. If `termios` is not `None`, the pseudoterminal's -/// terminal settings of the slave will be set to the values in `termios`. -#[inline] -pub fn openpty<'a, 'b, T: Into>, U: Into>>(winsize: T, termios: U) -> Result { - use std::ptr; - - let mut slave = mem::MaybeUninit::::uninit(); - let mut master = mem::MaybeUninit::::uninit(); - let ret = { - match (termios.into(), winsize.into()) { - (Some(termios), Some(winsize)) => { - let inner_termios = termios.get_libc_termios(); - unsafe { - libc::openpty( - master.as_mut_ptr(), - slave.as_mut_ptr(), - ptr::null_mut(), - &*inner_termios as *const libc::termios as *mut _, - winsize as *const Winsize as *mut _, - ) - } - } - (None, Some(winsize)) => { - unsafe { - libc::openpty( - master.as_mut_ptr(), - slave.as_mut_ptr(), - ptr::null_mut(), - ptr::null_mut(), - winsize as *const Winsize as *mut _, - ) - } - } - (Some(termios), None) => { - let inner_termios = termios.get_libc_termios(); - unsafe { - libc::openpty( - master.as_mut_ptr(), - slave.as_mut_ptr(), - ptr::null_mut(), - &*inner_termios as *const libc::termios as *mut _, - ptr::null_mut(), - ) - } - } - (None, None) => { - unsafe { - libc::openpty( - master.as_mut_ptr(), - slave.as_mut_ptr(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ) - } - } - } - }; - - Errno::result(ret)?; - - unsafe { - Ok(OpenptyResult { - master: master.assume_init(), - slave: slave.assume_init(), - }) - } -} - -/// Create a new pseudoterminal, returning the master file descriptor and forked pid. -/// in `ForkptyResult` -/// (see [`forkpty`](https://man7.org/linux/man-pages/man3/forkpty.3.html)). -/// -/// If `winsize` is not `None`, the window size of the slave will be set to -/// the values in `winsize`. If `termios` is not `None`, the pseudoterminal's -/// terminal settings of the slave will be set to the values in `termios`. -/// -/// # Safety -/// -/// In a multithreaded program, only [async-signal-safe] functions like `pause` -/// and `_exit` may be called by the child (the parent isn't restricted). Note -/// that memory allocation may **not** be async-signal-safe and thus must be -/// prevented. -/// -/// Those functions are only a small subset of your operating system's API, so -/// special care must be taken to only invoke code you can control and audit. -/// -/// [async-signal-safe]: https://man7.org/linux/man-pages/man7/signal-safety.7.html -pub unsafe fn forkpty<'a, 'b, T: Into>, U: Into>>( - winsize: T, - termios: U, -) -> Result { - use std::ptr; - - let mut master = mem::MaybeUninit::::uninit(); - - let term = match termios.into() { - Some(termios) => { - let inner_termios = termios.get_libc_termios(); - &*inner_termios as *const libc::termios as *mut _ - }, - None => ptr::null_mut(), - }; - - let win = winsize - .into() - .map(|ws| ws as *const Winsize as *mut _) - .unwrap_or(ptr::null_mut()); - - let res = libc::forkpty(master.as_mut_ptr(), ptr::null_mut(), term, win); - - let fork_result = Errno::result(res).map(|res| match res { - 0 => ForkResult::Child, - res => ForkResult::Parent { child: Pid::from_raw(res) }, - })?; - - Ok(ForkptyResult { - master: master.assume_init(), - fork_result, - }) -} diff --git a/vendor/nix-v0.23.1-patched/src/sched.rs b/vendor/nix-v0.23.1-patched/src/sched.rs deleted file mode 100644 index c2dd7b84c..000000000 --- a/vendor/nix-v0.23.1-patched/src/sched.rs +++ /dev/null @@ -1,282 +0,0 @@ -//! Execution scheduling -//! -//! See Also -//! [sched.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sched.h.html) -use crate::{Errno, Result}; - -#[cfg(any(target_os = "android", target_os = "linux"))] -pub use self::sched_linux_like::*; - -#[cfg(any(target_os = "android", target_os = "linux"))] -mod sched_linux_like { - use crate::errno::Errno; - use libc::{self, c_int, c_void}; - use std::mem; - use std::option::Option; - use std::os::unix::io::RawFd; - use crate::unistd::Pid; - use crate::Result; - - // For some functions taking with a parameter of type CloneFlags, - // only a subset of these flags have an effect. - libc_bitflags! { - /// Options for use with [`clone`] - pub struct CloneFlags: c_int { - /// The calling process and the child process run in the same - /// memory space. - CLONE_VM; - /// The caller and the child process share the same filesystem - /// information. - CLONE_FS; - /// The calling process and the child process share the same file - /// descriptor table. - CLONE_FILES; - /// The calling process and the child process share the same table - /// of signal handlers. - CLONE_SIGHAND; - /// If the calling process is being traced, then trace the child - /// also. - CLONE_PTRACE; - /// The execution of the calling process is suspended until the - /// child releases its virtual memory resources via a call to - /// execve(2) or _exit(2) (as with vfork(2)). - CLONE_VFORK; - /// The parent of the new child (as returned by getppid(2)) - /// will be the same as that of the calling process. - CLONE_PARENT; - /// The child is placed in the same thread group as the calling - /// process. - CLONE_THREAD; - /// The cloned child is started in a new mount namespace. - CLONE_NEWNS; - /// The child and the calling process share a single list of System - /// V semaphore adjustment values - CLONE_SYSVSEM; - // Not supported by Nix due to lack of varargs support in Rust FFI - // CLONE_SETTLS; - // Not supported by Nix due to lack of varargs support in Rust FFI - // CLONE_PARENT_SETTID; - // Not supported by Nix due to lack of varargs support in Rust FFI - // CLONE_CHILD_CLEARTID; - /// Unused since Linux 2.6.2 - #[deprecated(since = "0.23.0", note = "Deprecated by Linux 2.6.2")] - CLONE_DETACHED; - /// A tracing process cannot force `CLONE_PTRACE` on this child - /// process. - CLONE_UNTRACED; - // Not supported by Nix due to lack of varargs support in Rust FFI - // CLONE_CHILD_SETTID; - /// Create the process in a new cgroup namespace. - CLONE_NEWCGROUP; - /// Create the process in a new UTS namespace. - CLONE_NEWUTS; - /// Create the process in a new IPC namespace. - CLONE_NEWIPC; - /// Create the process in a new user namespace. - CLONE_NEWUSER; - /// Create the process in a new PID namespace. - CLONE_NEWPID; - /// Create the process in a new network namespace. - CLONE_NEWNET; - /// The new process shares an I/O context with the calling process. - CLONE_IO; - } - } - - /// Type for the function executed by [`clone`]. - pub type CloneCb<'a> = Box isize + 'a>; - - /// CpuSet represent a bit-mask of CPUs. - /// CpuSets are used by sched_setaffinity and - /// sched_getaffinity for example. - /// - /// This is a wrapper around `libc::cpu_set_t`. - #[repr(C)] - #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] - pub struct CpuSet { - cpu_set: libc::cpu_set_t, - } - - impl CpuSet { - /// Create a new and empty CpuSet. - pub fn new() -> CpuSet { - CpuSet { - cpu_set: unsafe { mem::zeroed() }, - } - } - - /// Test to see if a CPU is in the CpuSet. - /// `field` is the CPU id to test - pub fn is_set(&self, field: usize) -> Result { - if field >= CpuSet::count() { - Err(Errno::EINVAL) - } else { - Ok(unsafe { libc::CPU_ISSET(field, &self.cpu_set) }) - } - } - - /// Add a CPU to CpuSet. - /// `field` is the CPU id to add - pub fn set(&mut self, field: usize) -> Result<()> { - if field >= CpuSet::count() { - Err(Errno::EINVAL) - } else { - unsafe { libc::CPU_SET(field, &mut self.cpu_set); } - Ok(()) - } - } - - /// Remove a CPU from CpuSet. - /// `field` is the CPU id to remove - pub fn unset(&mut self, field: usize) -> Result<()> { - if field >= CpuSet::count() { - Err(Errno::EINVAL) - } else { - unsafe { libc::CPU_CLR(field, &mut self.cpu_set);} - Ok(()) - } - } - - /// Return the maximum number of CPU in CpuSet - pub const fn count() -> usize { - 8 * mem::size_of::() - } - } - - impl Default for CpuSet { - fn default() -> Self { - Self::new() - } - } - - /// `sched_setaffinity` set a thread's CPU affinity mask - /// ([`sched_setaffinity(2)`](https://man7.org/linux/man-pages/man2/sched_setaffinity.2.html)) - /// - /// `pid` is the thread ID to update. - /// If pid is zero, then the calling thread is updated. - /// - /// The `cpuset` argument specifies the set of CPUs on which the thread - /// will be eligible to run. - /// - /// # Example - /// - /// Binding the current thread to CPU 0 can be done as follows: - /// - /// ```rust,no_run - /// use nix::sched::{CpuSet, sched_setaffinity}; - /// use nix::unistd::Pid; - /// - /// let mut cpu_set = CpuSet::new(); - /// cpu_set.set(0); - /// sched_setaffinity(Pid::from_raw(0), &cpu_set); - /// ``` - pub fn sched_setaffinity(pid: Pid, cpuset: &CpuSet) -> Result<()> { - let res = unsafe { - libc::sched_setaffinity( - pid.into(), - mem::size_of::() as libc::size_t, - &cpuset.cpu_set, - ) - }; - - Errno::result(res).map(drop) - } - - /// `sched_getaffinity` get a thread's CPU affinity mask - /// ([`sched_getaffinity(2)`](https://man7.org/linux/man-pages/man2/sched_getaffinity.2.html)) - /// - /// `pid` is the thread ID to check. - /// If pid is zero, then the calling thread is checked. - /// - /// Returned `cpuset` is the set of CPUs on which the thread - /// is eligible to run. - /// - /// # Example - /// - /// Checking if the current thread can run on CPU 0 can be done as follows: - /// - /// ```rust,no_run - /// use nix::sched::sched_getaffinity; - /// use nix::unistd::Pid; - /// - /// let cpu_set = sched_getaffinity(Pid::from_raw(0)).unwrap(); - /// if cpu_set.is_set(0).unwrap() { - /// println!("Current thread can run on CPU 0"); - /// } - /// ``` - pub fn sched_getaffinity(pid: Pid) -> Result { - let mut cpuset = CpuSet::new(); - let res = unsafe { - libc::sched_getaffinity( - pid.into(), - mem::size_of::() as libc::size_t, - &mut cpuset.cpu_set, - ) - }; - - Errno::result(res).and(Ok(cpuset)) - } - - /// `clone` create a child process - /// ([`clone(2)`](https://man7.org/linux/man-pages/man2/clone.2.html)) - /// - /// `stack` is a reference to an array which will hold the stack of the new - /// process. Unlike when calling `clone(2)` from C, the provided stack - /// address need not be the highest address of the region. Nix will take - /// care of that requirement. The user only needs to provide a reference to - /// a normally allocated buffer. - pub fn clone( - mut cb: CloneCb, - stack: &mut [u8], - flags: CloneFlags, - signal: Option, - ) -> Result { - extern "C" fn callback(data: *mut CloneCb) -> c_int { - let cb: &mut CloneCb = unsafe { &mut *data }; - (*cb)() as c_int - } - - let res = unsafe { - let combined = flags.bits() | signal.unwrap_or(0); - let ptr = stack.as_mut_ptr().add(stack.len()); - let ptr_aligned = ptr.sub(ptr as usize % 16); - libc::clone( - mem::transmute( - callback as extern "C" fn(*mut Box isize>) -> i32, - ), - ptr_aligned as *mut c_void, - combined, - &mut cb as *mut _ as *mut c_void, - ) - }; - - Errno::result(res).map(Pid::from_raw) - } - - /// disassociate parts of the process execution context - /// - /// See also [unshare(2)](https://man7.org/linux/man-pages/man2/unshare.2.html) - pub fn unshare(flags: CloneFlags) -> Result<()> { - let res = unsafe { libc::unshare(flags.bits()) }; - - Errno::result(res).map(drop) - } - - /// reassociate thread with a namespace - /// - /// See also [setns(2)](https://man7.org/linux/man-pages/man2/setns.2.html) - pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> { - let res = unsafe { libc::setns(fd, nstype.bits()) }; - - Errno::result(res).map(drop) - } -} - -/// Explicitly yield the processor to other threads. -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_yield.html) -pub fn sched_yield() -> Result<()> { - let res = unsafe { libc::sched_yield() }; - - Errno::result(res).map(drop) -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/aio.rs b/vendor/nix-v0.23.1-patched/src/sys/aio.rs deleted file mode 100644 index e64a2a823..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/aio.rs +++ /dev/null @@ -1,1122 +0,0 @@ -// vim: tw=80 -//! POSIX Asynchronous I/O -//! -//! The POSIX AIO interface is used for asynchronous I/O on files and disk-like -//! devices. It supports [`read`](struct.AioCb.html#method.read), -//! [`write`](struct.AioCb.html#method.write), and -//! [`fsync`](struct.AioCb.html#method.fsync) operations. Completion -//! notifications can optionally be delivered via -//! [signals](../signal/enum.SigevNotify.html#variant.SigevSignal), via the -//! [`aio_suspend`](fn.aio_suspend.html) function, or via polling. Some -//! platforms support other completion -//! notifications, such as -//! [kevent](../signal/enum.SigevNotify.html#variant.SigevKevent). -//! -//! Multiple operations may be submitted in a batch with -//! [`lio_listio`](fn.lio_listio.html), though the standard does not guarantee -//! that they will be executed atomically. -//! -//! Outstanding operations may be cancelled with -//! [`cancel`](struct.AioCb.html#method.cancel) or -//! [`aio_cancel_all`](fn.aio_cancel_all.html), though the operating system may -//! not support this for all filesystems and devices. - -use crate::Result; -use crate::errno::Errno; -use std::os::unix::io::RawFd; -use libc::{c_void, off_t, size_t}; -use std::fmt; -use std::fmt::Debug; -use std::marker::PhantomData; -use std::mem; -use std::pin::Pin; -use std::ptr::{null, null_mut}; -use crate::sys::signal::*; -use std::thread; -use crate::sys::time::TimeSpec; - -libc_enum! { - /// Mode for `AioCb::fsync`. Controls whether only data or both data and - /// metadata are synced. - #[repr(i32)] - #[non_exhaustive] - pub enum AioFsyncMode { - /// do it like `fsync` - O_SYNC, - /// on supported operating systems only, do it like `fdatasync` - #[cfg(any(target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - O_DSYNC - } -} - -libc_enum! { - /// When used with [`lio_listio`](fn.lio_listio.html), determines whether a - /// given `aiocb` should be used for a read operation, a write operation, or - /// ignored. Has no effect for any other aio functions. - #[repr(i32)] - #[non_exhaustive] - pub enum LioOpcode { - /// No operation - LIO_NOP, - /// Write data as if by a call to [`AioCb::write`] - LIO_WRITE, - /// Write data as if by a call to [`AioCb::read`] - LIO_READ, - } -} - -libc_enum! { - /// Mode for [`lio_listio`](fn.lio_listio.html) - #[repr(i32)] - pub enum LioMode { - /// Requests that [`lio_listio`](fn.lio_listio.html) block until all - /// requested operations have been completed - LIO_WAIT, - /// Requests that [`lio_listio`](fn.lio_listio.html) return immediately - LIO_NOWAIT, - } -} - -/// Return values for [`AioCb::cancel`](struct.AioCb.html#method.cancel) and -/// [`aio_cancel_all`](fn.aio_cancel_all.html) -#[repr(i32)] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum AioCancelStat { - /// All outstanding requests were canceled - AioCanceled = libc::AIO_CANCELED, - /// Some requests were not canceled. Their status should be checked with - /// `AioCb::error` - AioNotCanceled = libc::AIO_NOTCANCELED, - /// All of the requests have already finished - AioAllDone = libc::AIO_ALLDONE, -} - -/// Newtype that adds Send and Sync to libc::aiocb, which contains raw pointers -#[repr(transparent)] -struct LibcAiocb(libc::aiocb); - -unsafe impl Send for LibcAiocb {} -unsafe impl Sync for LibcAiocb {} - -/// AIO Control Block. -/// -/// The basic structure used by all aio functions. Each `AioCb` represents one -/// I/O request. -pub struct AioCb<'a> { - aiocb: LibcAiocb, - /// Tracks whether the buffer pointed to by `libc::aiocb.aio_buf` is mutable - mutable: bool, - /// Could this `AioCb` potentially have any in-kernel state? - in_progress: bool, - _buffer: std::marker::PhantomData<&'a [u8]>, - _pin: std::marker::PhantomPinned -} - -impl<'a> AioCb<'a> { - /// Returns the underlying file descriptor associated with the `AioCb` - pub fn fd(&self) -> RawFd { - self.aiocb.0.aio_fildes - } - - /// Constructs a new `AioCb` with no associated buffer. - /// - /// The resulting `AioCb` structure is suitable for use with `AioCb::fsync`. - /// - /// # Parameters - /// - /// * `fd`: File descriptor. Required for all aio functions. - /// * `prio`: If POSIX Prioritized IO is supported, then the - /// operation will be prioritized at the process's - /// priority level minus `prio`. - /// * `sigev_notify`: Determines how you will be notified of event - /// completion. - /// - /// # Examples - /// - /// Create an `AioCb` from a raw file descriptor and use it for an - /// [`fsync`](#method.fsync) operation. - /// - /// ``` - /// # use nix::errno::Errno; - /// # use nix::Error; - /// # use nix::sys::aio::*; - /// # use nix::sys::signal::SigevNotify::SigevNone; - /// # use std::{thread, time}; - /// # use std::os::unix::io::AsRawFd; - /// # use tempfile::tempfile; - /// let f = tempfile().unwrap(); - /// let mut aiocb = AioCb::from_fd( f.as_raw_fd(), 0, SigevNone); - /// aiocb.fsync(AioFsyncMode::O_SYNC).expect("aio_fsync failed early"); - /// while (aiocb.error() == Err(Errno::EINPROGRESS)) { - /// thread::sleep(time::Duration::from_millis(10)); - /// } - /// aiocb.aio_return().expect("aio_fsync failed late"); - /// ``` - pub fn from_fd(fd: RawFd, prio: libc::c_int, - sigev_notify: SigevNotify) -> Pin>> { - let mut a = AioCb::common_init(fd, prio, sigev_notify); - a.0.aio_offset = 0; - a.0.aio_nbytes = 0; - a.0.aio_buf = null_mut(); - - Box::pin(AioCb { - aiocb: a, - mutable: false, - in_progress: false, - _buffer: PhantomData, - _pin: std::marker::PhantomPinned - }) - } - - // Private helper - #[cfg(not(any(target_os = "ios", target_os = "macos")))] - fn from_mut_slice_unpinned(fd: RawFd, offs: off_t, buf: &'a mut [u8], - prio: libc::c_int, sigev_notify: SigevNotify, - opcode: LioOpcode) -> AioCb<'a> - { - let mut a = AioCb::common_init(fd, prio, sigev_notify); - a.0.aio_offset = offs; - a.0.aio_nbytes = buf.len() as size_t; - a.0.aio_buf = buf.as_ptr() as *mut c_void; - a.0.aio_lio_opcode = opcode as libc::c_int; - - AioCb { - aiocb: a, - mutable: true, - in_progress: false, - _buffer: PhantomData, - _pin: std::marker::PhantomPinned - } - } - - /// Constructs a new `AioCb` from a mutable slice. - /// - /// The resulting `AioCb` will be suitable for both read and write - /// operations, but only if the borrow checker can guarantee that the slice - /// will outlive the `AioCb`. That will usually be the case if the `AioCb` - /// is stack-allocated. - /// - /// # Parameters - /// - /// * `fd`: File descriptor. Required for all aio functions. - /// * `offs`: File offset - /// * `buf`: A memory buffer - /// * `prio`: If POSIX Prioritized IO is supported, then the - /// operation will be prioritized at the process's - /// priority level minus `prio` - /// * `sigev_notify`: Determines how you will be notified of event - /// completion. - /// * `opcode`: This field is only used for `lio_listio`. It - /// determines which operation to use for this individual - /// aiocb - /// - /// # Examples - /// - /// Create an `AioCb` from a mutable slice and read into it. - /// - /// ``` - /// # use nix::errno::Errno; - /// # use nix::Error; - /// # use nix::sys::aio::*; - /// # use nix::sys::signal::SigevNotify; - /// # use std::{thread, time}; - /// # use std::io::Write; - /// # use std::os::unix::io::AsRawFd; - /// # use tempfile::tempfile; - /// const INITIAL: &[u8] = b"abcdef123456"; - /// const LEN: usize = 4; - /// let mut rbuf = vec![0; LEN]; - /// let mut f = tempfile().unwrap(); - /// f.write_all(INITIAL).unwrap(); - /// { - /// let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(), - /// 2, //offset - /// &mut rbuf, - /// 0, //priority - /// SigevNotify::SigevNone, - /// LioOpcode::LIO_NOP); - /// aiocb.read().unwrap(); - /// while (aiocb.error() == Err(Errno::EINPROGRESS)) { - /// thread::sleep(time::Duration::from_millis(10)); - /// } - /// assert_eq!(aiocb.aio_return().unwrap() as usize, LEN); - /// } - /// assert_eq!(rbuf, b"cdef"); - /// ``` - pub fn from_mut_slice(fd: RawFd, offs: off_t, buf: &'a mut [u8], - prio: libc::c_int, sigev_notify: SigevNotify, - opcode: LioOpcode) -> Pin>> { - let mut a = AioCb::common_init(fd, prio, sigev_notify); - a.0.aio_offset = offs; - a.0.aio_nbytes = buf.len() as size_t; - a.0.aio_buf = buf.as_ptr() as *mut c_void; - a.0.aio_lio_opcode = opcode as libc::c_int; - - Box::pin(AioCb { - aiocb: a, - mutable: true, - in_progress: false, - _buffer: PhantomData, - _pin: std::marker::PhantomPinned - }) - } - - /// Constructs a new `AioCb` from a mutable raw pointer - /// - /// Unlike `from_mut_slice`, this method returns a structure suitable for - /// placement on the heap. It may be used for both reads and writes. Due - /// to its unsafety, this method is not recommended. It is most useful when - /// heap allocation is required. - /// - /// # Parameters - /// - /// * `fd`: File descriptor. Required for all aio functions. - /// * `offs`: File offset - /// * `buf`: Pointer to the memory buffer - /// * `len`: Length of the buffer pointed to by `buf` - /// * `prio`: If POSIX Prioritized IO is supported, then the - /// operation will be prioritized at the process's - /// priority level minus `prio` - /// * `sigev_notify`: Determines how you will be notified of event - /// completion. - /// * `opcode`: This field is only used for `lio_listio`. It - /// determines which operation to use for this individual - /// aiocb - /// - /// # Safety - /// - /// The caller must ensure that the storage pointed to by `buf` outlives the - /// `AioCb`. The lifetime checker can't help here. - pub unsafe fn from_mut_ptr(fd: RawFd, offs: off_t, - buf: *mut c_void, len: usize, - prio: libc::c_int, sigev_notify: SigevNotify, - opcode: LioOpcode) -> Pin>> { - let mut a = AioCb::common_init(fd, prio, sigev_notify); - a.0.aio_offset = offs; - a.0.aio_nbytes = len; - a.0.aio_buf = buf; - a.0.aio_lio_opcode = opcode as libc::c_int; - - Box::pin(AioCb { - aiocb: a, - mutable: true, - in_progress: false, - _buffer: PhantomData, - _pin: std::marker::PhantomPinned, - }) - } - - /// Constructs a new `AioCb` from a raw pointer. - /// - /// Unlike `from_slice`, this method returns a structure suitable for - /// placement on the heap. Due to its unsafety, this method is not - /// recommended. It is most useful when heap allocation is required. - /// - /// # Parameters - /// - /// * `fd`: File descriptor. Required for all aio functions. - /// * `offs`: File offset - /// * `buf`: Pointer to the memory buffer - /// * `len`: Length of the buffer pointed to by `buf` - /// * `prio`: If POSIX Prioritized IO is supported, then the - /// operation will be prioritized at the process's - /// priority level minus `prio` - /// * `sigev_notify`: Determines how you will be notified of event - /// completion. - /// * `opcode`: This field is only used for `lio_listio`. It - /// determines which operation to use for this individual - /// aiocb - /// - /// # Safety - /// - /// The caller must ensure that the storage pointed to by `buf` outlives the - /// `AioCb`. The lifetime checker can't help here. - pub unsafe fn from_ptr(fd: RawFd, offs: off_t, - buf: *const c_void, len: usize, - prio: libc::c_int, sigev_notify: SigevNotify, - opcode: LioOpcode) -> Pin>> { - let mut a = AioCb::common_init(fd, prio, sigev_notify); - a.0.aio_offset = offs; - a.0.aio_nbytes = len; - // casting a const ptr to a mutable ptr here is ok, because we set the - // AioCb's mutable field to false - a.0.aio_buf = buf as *mut c_void; - a.0.aio_lio_opcode = opcode as libc::c_int; - - Box::pin(AioCb { - aiocb: a, - mutable: false, - in_progress: false, - _buffer: PhantomData, - _pin: std::marker::PhantomPinned - }) - } - - // Private helper - fn from_slice_unpinned(fd: RawFd, offs: off_t, buf: &'a [u8], - prio: libc::c_int, sigev_notify: SigevNotify, - opcode: LioOpcode) -> AioCb - { - let mut a = AioCb::common_init(fd, prio, sigev_notify); - a.0.aio_offset = offs; - a.0.aio_nbytes = buf.len() as size_t; - // casting an immutable buffer to a mutable pointer looks unsafe, - // but technically its only unsafe to dereference it, not to create - // it. - a.0.aio_buf = buf.as_ptr() as *mut c_void; - assert!(opcode != LioOpcode::LIO_READ, "Can't read into an immutable buffer"); - a.0.aio_lio_opcode = opcode as libc::c_int; - - AioCb { - aiocb: a, - mutable: false, - in_progress: false, - _buffer: PhantomData, - _pin: std::marker::PhantomPinned - } - } - - /// Like [`AioCb::from_mut_slice`], but works on constant slices rather than - /// mutable slices. - /// - /// An `AioCb` created this way cannot be used with `read`, and its - /// `LioOpcode` cannot be set to `LIO_READ`. This method is useful when - /// writing a const buffer with `AioCb::write`, since `from_mut_slice` can't - /// work with const buffers. - /// - /// # Examples - /// - /// Construct an `AioCb` from a slice and use it for writing. - /// - /// ``` - /// # use nix::errno::Errno; - /// # use nix::Error; - /// # use nix::sys::aio::*; - /// # use nix::sys::signal::SigevNotify; - /// # use std::{thread, time}; - /// # use std::os::unix::io::AsRawFd; - /// # use tempfile::tempfile; - /// const WBUF: &[u8] = b"abcdef123456"; - /// let mut f = tempfile().unwrap(); - /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(), - /// 2, //offset - /// WBUF, - /// 0, //priority - /// SigevNotify::SigevNone, - /// LioOpcode::LIO_NOP); - /// aiocb.write().unwrap(); - /// while (aiocb.error() == Err(Errno::EINPROGRESS)) { - /// thread::sleep(time::Duration::from_millis(10)); - /// } - /// assert_eq!(aiocb.aio_return().unwrap() as usize, WBUF.len()); - /// ``` - // Note: another solution to the problem of writing const buffers would be - // to genericize AioCb for both &mut [u8] and &[u8] buffers. AioCb::read - // could take the former and AioCb::write could take the latter. However, - // then lio_listio wouldn't work, because that function needs a slice of - // AioCb, and they must all be of the same type. - pub fn from_slice(fd: RawFd, offs: off_t, buf: &'a [u8], - prio: libc::c_int, sigev_notify: SigevNotify, - opcode: LioOpcode) -> Pin> - { - Box::pin(AioCb::from_slice_unpinned(fd, offs, buf, prio, sigev_notify, - opcode)) - } - - fn common_init(fd: RawFd, prio: libc::c_int, - sigev_notify: SigevNotify) -> LibcAiocb { - // Use mem::zeroed instead of explicitly zeroing each field, because the - // number and name of reserved fields is OS-dependent. On some OSes, - // some reserved fields are used the kernel for state, and must be - // explicitly zeroed when allocated. - let mut a = unsafe { mem::zeroed::()}; - a.aio_fildes = fd; - a.aio_reqprio = prio; - a.aio_sigevent = SigEvent::new(sigev_notify).sigevent(); - LibcAiocb(a) - } - - /// Update the notification settings for an existing `aiocb` - pub fn set_sigev_notify(self: &mut Pin>, - sigev_notify: SigevNotify) - { - // Safe because we don't move any of the data - let selfp = unsafe { - self.as_mut().get_unchecked_mut() - }; - selfp.aiocb.0.aio_sigevent = SigEvent::new(sigev_notify).sigevent(); - } - - /// Cancels an outstanding AIO request. - /// - /// The operating system is not required to implement cancellation for all - /// file and device types. Even if it does, there is no guarantee that the - /// operation has not already completed. So the caller must check the - /// result and handle operations that were not canceled or that have already - /// completed. - /// - /// # Examples - /// - /// Cancel an outstanding aio operation. Note that we must still call - /// `aio_return` to free resources, even though we don't care about the - /// result. - /// - /// ``` - /// # use nix::errno::Errno; - /// # use nix::Error; - /// # use nix::sys::aio::*; - /// # use nix::sys::signal::SigevNotify; - /// # use std::{thread, time}; - /// # use std::io::Write; - /// # use std::os::unix::io::AsRawFd; - /// # use tempfile::tempfile; - /// let wbuf = b"CDEF"; - /// let mut f = tempfile().unwrap(); - /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(), - /// 2, //offset - /// &wbuf[..], - /// 0, //priority - /// SigevNotify::SigevNone, - /// LioOpcode::LIO_NOP); - /// aiocb.write().unwrap(); - /// let cs = aiocb.cancel().unwrap(); - /// if cs == AioCancelStat::AioNotCanceled { - /// while (aiocb.error() == Err(Errno::EINPROGRESS)) { - /// thread::sleep(time::Duration::from_millis(10)); - /// } - /// } - /// // Must call `aio_return`, but ignore the result - /// let _ = aiocb.aio_return(); - /// ``` - /// - /// # References - /// - /// [aio_cancel](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html) - pub fn cancel(self: &mut Pin>) -> Result { - let r = unsafe { - let selfp = self.as_mut().get_unchecked_mut(); - libc::aio_cancel(selfp.aiocb.0.aio_fildes, &mut selfp.aiocb.0) - }; - match r { - libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled), - libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled), - libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone), - -1 => Err(Errno::last()), - _ => panic!("unknown aio_cancel return value") - } - } - - fn error_unpinned(&mut self) -> Result<()> { - let r = unsafe { - libc::aio_error(&mut self.aiocb.0 as *mut libc::aiocb) - }; - match r { - 0 => Ok(()), - num if num > 0 => Err(Errno::from_i32(num)), - -1 => Err(Errno::last()), - num => panic!("unknown aio_error return value {:?}", num) - } - } - - /// Retrieve error status of an asynchronous operation. - /// - /// If the request has not yet completed, returns `EINPROGRESS`. Otherwise, - /// returns `Ok` or any other error. - /// - /// # Examples - /// - /// Issue an aio operation and use `error` to poll for completion. Polling - /// is an alternative to `aio_suspend`, used by most of the other examples. - /// - /// ``` - /// # use nix::errno::Errno; - /// # use nix::Error; - /// # use nix::sys::aio::*; - /// # use nix::sys::signal::SigevNotify; - /// # use std::{thread, time}; - /// # use std::os::unix::io::AsRawFd; - /// # use tempfile::tempfile; - /// const WBUF: &[u8] = b"abcdef123456"; - /// let mut f = tempfile().unwrap(); - /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(), - /// 2, //offset - /// WBUF, - /// 0, //priority - /// SigevNotify::SigevNone, - /// LioOpcode::LIO_NOP); - /// aiocb.write().unwrap(); - /// while (aiocb.error() == Err(Errno::EINPROGRESS)) { - /// thread::sleep(time::Duration::from_millis(10)); - /// } - /// assert_eq!(aiocb.aio_return().unwrap() as usize, WBUF.len()); - /// ``` - /// - /// # References - /// - /// [aio_error](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_error.html) - pub fn error(self: &mut Pin>) -> Result<()> { - // Safe because error_unpinned doesn't move the data - let selfp = unsafe { - self.as_mut().get_unchecked_mut() - }; - selfp.error_unpinned() - } - - /// An asynchronous version of `fsync(2)`. - /// - /// # References - /// - /// [aio_fsync](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_fsync.html) - pub fn fsync(self: &mut Pin>, mode: AioFsyncMode) -> Result<()> { - // Safe because we don't move the libc::aiocb - unsafe { - let selfp = self.as_mut().get_unchecked_mut(); - Errno::result({ - let p: *mut libc::aiocb = &mut selfp.aiocb.0; - libc::aio_fsync(mode as libc::c_int, p) - }).map(|_| { - selfp.in_progress = true; - }) - } - } - - /// Returns the `aiocb`'s `LioOpcode` field - /// - /// If the value cannot be represented as an `LioOpcode`, returns `None` - /// instead. - pub fn lio_opcode(&self) -> Option { - match self.aiocb.0.aio_lio_opcode { - libc::LIO_READ => Some(LioOpcode::LIO_READ), - libc::LIO_WRITE => Some(LioOpcode::LIO_WRITE), - libc::LIO_NOP => Some(LioOpcode::LIO_NOP), - _ => None - } - } - - /// Returns the requested length of the aio operation in bytes - /// - /// This method returns the *requested* length of the operation. To get the - /// number of bytes actually read or written by a completed operation, use - /// `aio_return` instead. - pub fn nbytes(&self) -> usize { - self.aiocb.0.aio_nbytes - } - - /// Returns the file offset stored in the `AioCb` - pub fn offset(&self) -> off_t { - self.aiocb.0.aio_offset - } - - /// Returns the priority of the `AioCb` - pub fn priority(&self) -> libc::c_int { - self.aiocb.0.aio_reqprio - } - - /// Asynchronously reads from a file descriptor into a buffer - /// - /// # References - /// - /// [aio_read](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_read.html) - pub fn read(self: &mut Pin>) -> Result<()> { - assert!(self.mutable, "Can't read into an immutable buffer"); - // Safe because we don't move anything - let selfp = unsafe { - self.as_mut().get_unchecked_mut() - }; - Errno::result({ - let p: *mut libc::aiocb = &mut selfp.aiocb.0; - unsafe { libc::aio_read(p) } - }).map(|_| { - selfp.in_progress = true; - }) - } - - /// Returns the `SigEvent` stored in the `AioCb` - pub fn sigevent(&self) -> SigEvent { - SigEvent::from(&self.aiocb.0.aio_sigevent) - } - - fn aio_return_unpinned(&mut self) -> Result { - unsafe { - let p: *mut libc::aiocb = &mut self.aiocb.0; - self.in_progress = false; - Errno::result(libc::aio_return(p)) - } - } - - /// Retrieve return status of an asynchronous operation. - /// - /// Should only be called once for each `AioCb`, after `AioCb::error` - /// indicates that it has completed. The result is the same as for the - /// synchronous `read(2)`, `write(2)`, of `fsync(2)` functions. - /// - /// # References - /// - /// [aio_return](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_return.html) - // Note: this should be just `return`, but that's a reserved word - pub fn aio_return(self: &mut Pin>) -> Result { - // Safe because aio_return_unpinned does not move the data - let selfp = unsafe { - self.as_mut().get_unchecked_mut() - }; - selfp.aio_return_unpinned() - } - - /// Asynchronously writes from a buffer to a file descriptor - /// - /// # References - /// - /// [aio_write](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_write.html) - pub fn write(self: &mut Pin>) -> Result<()> { - // Safe because we don't move anything - let selfp = unsafe { - self.as_mut().get_unchecked_mut() - }; - Errno::result({ - let p: *mut libc::aiocb = &mut selfp.aiocb.0; - unsafe{ libc::aio_write(p) } - }).map(|_| { - selfp.in_progress = true; - }) - } -} - -/// Cancels outstanding AIO requests for a given file descriptor. -/// -/// # Examples -/// -/// Issue an aio operation, then cancel all outstanding operations on that file -/// descriptor. -/// -/// ``` -/// # use nix::errno::Errno; -/// # use nix::Error; -/// # use nix::sys::aio::*; -/// # use nix::sys::signal::SigevNotify; -/// # use std::{thread, time}; -/// # use std::io::Write; -/// # use std::os::unix::io::AsRawFd; -/// # use tempfile::tempfile; -/// let wbuf = b"CDEF"; -/// let mut f = tempfile().unwrap(); -/// let mut aiocb = AioCb::from_slice( f.as_raw_fd(), -/// 2, //offset -/// &wbuf[..], -/// 0, //priority -/// SigevNotify::SigevNone, -/// LioOpcode::LIO_NOP); -/// aiocb.write().unwrap(); -/// let cs = aio_cancel_all(f.as_raw_fd()).unwrap(); -/// if cs == AioCancelStat::AioNotCanceled { -/// while (aiocb.error() == Err(Errno::EINPROGRESS)) { -/// thread::sleep(time::Duration::from_millis(10)); -/// } -/// } -/// // Must call `aio_return`, but ignore the result -/// let _ = aiocb.aio_return(); -/// ``` -/// -/// # References -/// -/// [`aio_cancel`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html) -pub fn aio_cancel_all(fd: RawFd) -> Result { - match unsafe { libc::aio_cancel(fd, null_mut()) } { - libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled), - libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled), - libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone), - -1 => Err(Errno::last()), - _ => panic!("unknown aio_cancel return value") - } -} - -/// Suspends the calling process until at least one of the specified `AioCb`s -/// has completed, a signal is delivered, or the timeout has passed. -/// -/// If `timeout` is `None`, `aio_suspend` will block indefinitely. -/// -/// # Examples -/// -/// Use `aio_suspend` to block until an aio operation completes. -/// -/// ``` -/// # use nix::sys::aio::*; -/// # use nix::sys::signal::SigevNotify; -/// # use std::os::unix::io::AsRawFd; -/// # use tempfile::tempfile; -/// const WBUF: &[u8] = b"abcdef123456"; -/// let mut f = tempfile().unwrap(); -/// let mut aiocb = AioCb::from_slice( f.as_raw_fd(), -/// 2, //offset -/// WBUF, -/// 0, //priority -/// SigevNotify::SigevNone, -/// LioOpcode::LIO_NOP); -/// aiocb.write().unwrap(); -/// aio_suspend(&[aiocb.as_ref()], None).expect("aio_suspend failed"); -/// assert_eq!(aiocb.aio_return().unwrap() as usize, WBUF.len()); -/// ``` -/// # References -/// -/// [`aio_suspend`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_suspend.html) -pub fn aio_suspend(list: &[Pin<&AioCb>], timeout: Option) -> Result<()> { - let plist = list as *const [Pin<&AioCb>] as *const [*const libc::aiocb]; - let p = plist as *const *const libc::aiocb; - let timep = match timeout { - None => null::(), - Some(x) => x.as_ref() as *const libc::timespec - }; - Errno::result(unsafe { - libc::aio_suspend(p, list.len() as i32, timep) - }).map(drop) -} - -impl<'a> Debug for AioCb<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("AioCb") - .field("aiocb", &self.aiocb.0) - .field("mutable", &self.mutable) - .field("in_progress", &self.in_progress) - .finish() - } -} - -impl<'a> Drop for AioCb<'a> { - /// If the `AioCb` has no remaining state in the kernel, just drop it. - /// Otherwise, dropping constitutes a resource leak, which is an error - fn drop(&mut self) { - assert!(thread::panicking() || !self.in_progress, - "Dropped an in-progress AioCb"); - } -} - -/// LIO Control Block. -/// -/// The basic structure used to issue multiple AIO operations simultaneously. -#[cfg(not(any(target_os = "ios", target_os = "macos")))] -pub struct LioCb<'a> { - /// A collection of [`AioCb`]s. All of these will be issued simultaneously - /// by the [`listio`] method. - /// - /// [`AioCb`]: struct.AioCb.html - /// [`listio`]: #method.listio - // Their locations in memory must be fixed once they are passed to the - // kernel. So this field must be non-public so the user can't swap. - aiocbs: Box<[AioCb<'a>]>, - - /// The actual list passed to `libc::lio_listio`. - /// - /// It must live for as long as any of the operations are still being - /// processesed, because the aio subsystem uses its address as a unique - /// identifier. - list: Vec<*mut libc::aiocb>, - - /// A partial set of results. This field will get populated by - /// `listio_resubmit` when an `LioCb` is resubmitted after an error - results: Vec>> -} - -/// LioCb can't automatically impl Send and Sync just because of the raw -/// pointers in list. But that's stupid. There's no reason that raw pointers -/// should automatically be non-Send -#[cfg(not(any(target_os = "ios", target_os = "macos")))] -unsafe impl<'a> Send for LioCb<'a> {} -#[cfg(not(any(target_os = "ios", target_os = "macos")))] -unsafe impl<'a> Sync for LioCb<'a> {} - -#[cfg(not(any(target_os = "ios", target_os = "macos")))] -impl<'a> LioCb<'a> { - /// Are no [`AioCb`]s contained? - pub fn is_empty(&self) -> bool { - self.aiocbs.is_empty() - } - - /// Return the number of individual [`AioCb`]s contained. - pub fn len(&self) -> usize { - self.aiocbs.len() - } - - /// Submits multiple asynchronous I/O requests with a single system call. - /// - /// They are not guaranteed to complete atomically, and the order in which - /// the requests are carried out is not specified. Reads, writes, and - /// fsyncs may be freely mixed. - /// - /// This function is useful for reducing the context-switch overhead of - /// submitting many AIO operations. It can also be used with - /// `LioMode::LIO_WAIT` to block on the result of several independent - /// operations. Used that way, it is often useful in programs that - /// otherwise make little use of AIO. - /// - /// # Examples - /// - /// Use `listio` to submit an aio operation and wait for its completion. In - /// this case, there is no need to use [`aio_suspend`] to wait or - /// [`AioCb::error`] to poll. - /// - /// ``` - /// # use nix::sys::aio::*; - /// # use nix::sys::signal::SigevNotify; - /// # use std::os::unix::io::AsRawFd; - /// # use tempfile::tempfile; - /// const WBUF: &[u8] = b"abcdef123456"; - /// let mut f = tempfile().unwrap(); - /// let mut liocb = LioCbBuilder::with_capacity(1) - /// .emplace_slice( - /// f.as_raw_fd(), - /// 2, //offset - /// WBUF, - /// 0, //priority - /// SigevNotify::SigevNone, - /// LioOpcode::LIO_WRITE - /// ).finish(); - /// liocb.listio(LioMode::LIO_WAIT, - /// SigevNotify::SigevNone).unwrap(); - /// assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len()); - /// ``` - /// - /// # References - /// - /// [`lio_listio`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html) - /// - /// [`aio_suspend`]: fn.aio_suspend.html - /// [`AioCb::error`]: struct.AioCb.html#method.error - pub fn listio(&mut self, mode: LioMode, - sigev_notify: SigevNotify) -> Result<()> { - let sigev = SigEvent::new(sigev_notify); - let sigevp = &mut sigev.sigevent() as *mut libc::sigevent; - self.list.clear(); - for a in &mut self.aiocbs.iter_mut() { - a.in_progress = true; - self.list.push(a as *mut AioCb<'a> - as *mut libc::aiocb); - } - let p = self.list.as_ptr(); - Errno::result(unsafe { - libc::lio_listio(mode as i32, p, self.list.len() as i32, sigevp) - }).map(drop) - } - - /// Resubmits any incomplete operations with [`lio_listio`]. - /// - /// Sometimes, due to system resource limitations, an `lio_listio` call will - /// return `EIO`, or `EAGAIN`. Or, if a signal is received, it may return - /// `EINTR`. In any of these cases, only a subset of its constituent - /// operations will actually have been initiated. `listio_resubmit` will - /// resubmit any operations that are still uninitiated. - /// - /// After calling `listio_resubmit`, results should be collected by - /// [`LioCb::aio_return`]. - /// - /// # Examples - /// ```no_run - /// # use nix::Error; - /// # use nix::errno::Errno; - /// # use nix::sys::aio::*; - /// # use nix::sys::signal::SigevNotify; - /// # use std::os::unix::io::AsRawFd; - /// # use std::{thread, time}; - /// # use tempfile::tempfile; - /// const WBUF: &[u8] = b"abcdef123456"; - /// let mut f = tempfile().unwrap(); - /// let mut liocb = LioCbBuilder::with_capacity(1) - /// .emplace_slice( - /// f.as_raw_fd(), - /// 2, //offset - /// WBUF, - /// 0, //priority - /// SigevNotify::SigevNone, - /// LioOpcode::LIO_WRITE - /// ).finish(); - /// let mut err = liocb.listio(LioMode::LIO_WAIT, SigevNotify::SigevNone); - /// while err == Err(Errno::EIO) || - /// err == Err(Errno::EAGAIN) { - /// thread::sleep(time::Duration::from_millis(10)); - /// err = liocb.listio_resubmit(LioMode::LIO_WAIT, SigevNotify::SigevNone); - /// } - /// assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len()); - /// ``` - /// - /// # References - /// - /// [`lio_listio`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html) - /// - /// [`lio_listio`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html - /// [`LioCb::aio_return`]: struct.LioCb.html#method.aio_return - // Note: the addresses of any EINPROGRESS or EOK aiocbs _must_ not be - // changed by this method, because the kernel relies on their addresses - // being stable. - // Note: aiocbs that are Ok(()) must be finalized by aio_return, or else the - // sigev_notify will immediately refire. - pub fn listio_resubmit(&mut self, mode:LioMode, - sigev_notify: SigevNotify) -> Result<()> { - let sigev = SigEvent::new(sigev_notify); - let sigevp = &mut sigev.sigevent() as *mut libc::sigevent; - self.list.clear(); - - while self.results.len() < self.aiocbs.len() { - self.results.push(None); - } - - for (i, a) in self.aiocbs.iter_mut().enumerate() { - if self.results[i].is_some() { - // Already collected final status for this operation - continue; - } - match a.error_unpinned() { - Ok(()) => { - // aiocb is complete; collect its status and don't resubmit - self.results[i] = Some(a.aio_return_unpinned()); - }, - Err(Errno::EAGAIN) => { - self.list.push(a as *mut AioCb<'a> as *mut libc::aiocb); - }, - Err(Errno::EINPROGRESS) => { - // aiocb is was successfully queued; no need to do anything - }, - Err(Errno::EINVAL) => panic!( - "AioCb was never submitted, or already finalized"), - _ => unreachable!() - } - } - let p = self.list.as_ptr(); - Errno::result(unsafe { - libc::lio_listio(mode as i32, p, self.list.len() as i32, sigevp) - }).map(drop) - } - - /// Collect final status for an individual `AioCb` submitted as part of an - /// `LioCb`. - /// - /// This is just like [`AioCb::aio_return`], except it takes into account - /// operations that were restarted by [`LioCb::listio_resubmit`] - /// - /// [`AioCb::aio_return`]: struct.AioCb.html#method.aio_return - /// [`LioCb::listio_resubmit`]: #method.listio_resubmit - pub fn aio_return(&mut self, i: usize) -> Result { - if i >= self.results.len() || self.results[i].is_none() { - self.aiocbs[i].aio_return_unpinned() - } else { - self.results[i].unwrap() - } - } - - /// Retrieve error status of an individual `AioCb` submitted as part of an - /// `LioCb`. - /// - /// This is just like [`AioCb::error`], except it takes into account - /// operations that were restarted by [`LioCb::listio_resubmit`] - /// - /// [`AioCb::error`]: struct.AioCb.html#method.error - /// [`LioCb::listio_resubmit`]: #method.listio_resubmit - pub fn error(&mut self, i: usize) -> Result<()> { - if i >= self.results.len() || self.results[i].is_none() { - self.aiocbs[i].error_unpinned() - } else { - Ok(()) - } - } -} - -#[cfg(not(any(target_os = "ios", target_os = "macos")))] -impl<'a> Debug for LioCb<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("LioCb") - .field("aiocbs", &self.aiocbs) - .finish() - } -} - -/// Used to construct `LioCb` -// This must be a separate class from LioCb due to pinning constraints. LioCb -// must use a boxed slice of AioCbs so they will have stable storage, but -// LioCbBuilder must use a Vec to make construction possible when the final size -// is unknown. -#[cfg(not(any(target_os = "ios", target_os = "macos")))] -#[derive(Debug)] -pub struct LioCbBuilder<'a> { - /// A collection of [`AioCb`]s. - /// - /// [`AioCb`]: struct.AioCb.html - pub aiocbs: Vec>, -} - -#[cfg(not(any(target_os = "ios", target_os = "macos")))] -impl<'a> LioCbBuilder<'a> { - /// Initialize an empty `LioCb` - pub fn with_capacity(capacity: usize) -> LioCbBuilder<'a> { - LioCbBuilder { - aiocbs: Vec::with_capacity(capacity), - } - } - - /// Add a new operation on an immutable slice to the [`LioCb`] under - /// construction. - /// - /// Arguments are the same as for [`AioCb::from_slice`] - /// - /// [`LioCb`]: struct.LioCb.html - /// [`AioCb::from_slice`]: struct.AioCb.html#method.from_slice - pub fn emplace_slice(mut self, fd: RawFd, offs: off_t, buf: &'a [u8], - prio: libc::c_int, sigev_notify: SigevNotify, - opcode: LioOpcode) -> Self - { - self.aiocbs.push(AioCb::from_slice_unpinned(fd, offs, buf, prio, - sigev_notify, opcode)); - self - } - - /// Add a new operation on a mutable slice to the [`LioCb`] under - /// construction. - /// - /// Arguments are the same as for [`AioCb::from_mut_slice`] - /// - /// [`LioCb`]: struct.LioCb.html - /// [`AioCb::from_mut_slice`]: struct.AioCb.html#method.from_mut_slice - pub fn emplace_mut_slice(mut self, fd: RawFd, offs: off_t, - buf: &'a mut [u8], prio: libc::c_int, - sigev_notify: SigevNotify, opcode: LioOpcode) - -> Self - { - self.aiocbs.push(AioCb::from_mut_slice_unpinned(fd, offs, buf, prio, - sigev_notify, opcode)); - self - } - - /// Finalize this [`LioCb`]. - /// - /// Afterwards it will be possible to issue the operations with - /// [`LioCb::listio`]. Conversely, it will no longer be possible to add new - /// operations with [`LioCbBuilder::emplace_slice`] or - /// [`LioCbBuilder::emplace_mut_slice`]. - /// - /// [`LioCb::listio`]: struct.LioCb.html#method.listio - /// [`LioCb::from_mut_slice`]: struct.LioCb.html#method.from_mut_slice - /// [`LioCb::from_slice`]: struct.LioCb.html#method.from_slice - pub fn finish(self) -> LioCb<'a> { - let len = self.aiocbs.len(); - LioCb { - aiocbs: self.aiocbs.into(), - list: Vec::with_capacity(len), - results: Vec::with_capacity(len) - } - } -} - -#[cfg(not(any(target_os = "ios", target_os = "macos")))] -#[cfg(test)] -mod t { - use super::*; - - // It's important that `LioCb` be `UnPin`. The tokio-file crate relies on - // it. - #[test] - fn liocb_is_unpin() { - use assert_impl::assert_impl; - - assert_impl!(Unpin: LioCb); - } -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/epoll.rs b/vendor/nix-v0.23.1-patched/src/sys/epoll.rs deleted file mode 100644 index 6bc2a2539..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/epoll.rs +++ /dev/null @@ -1,109 +0,0 @@ -use crate::Result; -use crate::errno::Errno; -use libc::{self, c_int}; -use std::os::unix::io::RawFd; -use std::ptr; -use std::mem; - -libc_bitflags!( - pub struct EpollFlags: c_int { - EPOLLIN; - EPOLLPRI; - EPOLLOUT; - EPOLLRDNORM; - EPOLLRDBAND; - EPOLLWRNORM; - EPOLLWRBAND; - EPOLLMSG; - EPOLLERR; - EPOLLHUP; - EPOLLRDHUP; - #[cfg(target_os = "linux")] // Added in 4.5; not in Android. - EPOLLEXCLUSIVE; - #[cfg(not(target_arch = "mips"))] - EPOLLWAKEUP; - EPOLLONESHOT; - EPOLLET; - } -); - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -#[repr(i32)] -#[non_exhaustive] -pub enum EpollOp { - EpollCtlAdd = libc::EPOLL_CTL_ADD, - EpollCtlDel = libc::EPOLL_CTL_DEL, - EpollCtlMod = libc::EPOLL_CTL_MOD, -} - -libc_bitflags!{ - pub struct EpollCreateFlags: c_int { - EPOLL_CLOEXEC; - } -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -#[repr(transparent)] -pub struct EpollEvent { - event: libc::epoll_event, -} - -impl EpollEvent { - pub fn new(events: EpollFlags, data: u64) -> Self { - EpollEvent { event: libc::epoll_event { events: events.bits() as u32, u64: data } } - } - - pub fn empty() -> Self { - unsafe { mem::zeroed::() } - } - - pub fn events(&self) -> EpollFlags { - EpollFlags::from_bits(self.event.events as c_int).unwrap() - } - - pub fn data(&self) -> u64 { - self.event.u64 - } -} - -#[inline] -pub fn epoll_create() -> Result { - let res = unsafe { libc::epoll_create(1024) }; - - Errno::result(res) -} - -#[inline] -pub fn epoll_create1(flags: EpollCreateFlags) -> Result { - let res = unsafe { libc::epoll_create1(flags.bits()) }; - - Errno::result(res) -} - -#[inline] -pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result<()> - where T: Into> -{ - let mut event: Option<&mut EpollEvent> = event.into(); - if event.is_none() && op != EpollOp::EpollCtlDel { - Err(Errno::EINVAL) - } else { - let res = unsafe { - if let Some(ref mut event) = event { - libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event) - } else { - libc::epoll_ctl(epfd, op as c_int, fd, ptr::null_mut()) - } - }; - Errno::result(res).map(drop) - } -} - -#[inline] -pub fn epoll_wait(epfd: RawFd, events: &mut [EpollEvent], timeout_ms: isize) -> Result { - let res = unsafe { - libc::epoll_wait(epfd, events.as_mut_ptr() as *mut libc::epoll_event, events.len() as c_int, timeout_ms as c_int) - }; - - Errno::result(res).map(|r| r as usize) -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/event.rs b/vendor/nix-v0.23.1-patched/src/sys/event.rs deleted file mode 100644 index c648f5ebc..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/event.rs +++ /dev/null @@ -1,348 +0,0 @@ -/* TOOD: Implement for other kqueue based systems - */ - -use crate::{Errno, Result}; -#[cfg(not(target_os = "netbsd"))] -use libc::{timespec, time_t, c_int, c_long, intptr_t, uintptr_t}; -#[cfg(target_os = "netbsd")] -use libc::{timespec, time_t, c_long, intptr_t, uintptr_t, size_t}; -use std::convert::TryInto; -use std::os::unix::io::RawFd; -use std::ptr; - -// Redefine kevent in terms of programmer-friendly enums and bitfields. -#[repr(C)] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct KEvent { - kevent: libc::kevent, -} - -#[cfg(any(target_os = "dragonfly", target_os = "freebsd", - target_os = "ios", target_os = "macos", - target_os = "openbsd"))] -type type_of_udata = *mut libc::c_void; -#[cfg(any(target_os = "dragonfly", target_os = "freebsd", - target_os = "ios", target_os = "macos"))] -type type_of_data = intptr_t; -#[cfg(any(target_os = "netbsd"))] -type type_of_udata = intptr_t; -#[cfg(any(target_os = "netbsd", target_os = "openbsd"))] -type type_of_data = i64; - -#[cfg(target_os = "netbsd")] -type type_of_event_filter = u32; -#[cfg(not(target_os = "netbsd"))] -type type_of_event_filter = i16; -libc_enum! { - #[cfg_attr(target_os = "netbsd", repr(u32))] - #[cfg_attr(not(target_os = "netbsd"), repr(i16))] - #[non_exhaustive] - pub enum EventFilter { - EVFILT_AIO, - /// Returns whenever there is no remaining data in the write buffer - #[cfg(target_os = "freebsd")] - EVFILT_EMPTY, - #[cfg(target_os = "dragonfly")] - EVFILT_EXCEPT, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos"))] - EVFILT_FS, - #[cfg(target_os = "freebsd")] - EVFILT_LIO, - #[cfg(any(target_os = "ios", target_os = "macos"))] - EVFILT_MACHPORT, - EVFILT_PROC, - /// Returns events associated with the process referenced by a given - /// process descriptor, created by `pdfork()`. The events to monitor are: - /// - /// - NOTE_EXIT: the process has exited. The exit status will be stored in data. - #[cfg(target_os = "freebsd")] - EVFILT_PROCDESC, - EVFILT_READ, - /// Returns whenever an asynchronous `sendfile()` call completes. - #[cfg(target_os = "freebsd")] - EVFILT_SENDFILE, - EVFILT_SIGNAL, - EVFILT_TIMER, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos"))] - EVFILT_USER, - #[cfg(any(target_os = "ios", target_os = "macos"))] - EVFILT_VM, - EVFILT_VNODE, - EVFILT_WRITE, - } - impl TryFrom -} - -#[cfg(any(target_os = "dragonfly", target_os = "freebsd", - target_os = "ios", target_os = "macos", - target_os = "openbsd"))] -pub type type_of_event_flag = u16; -#[cfg(any(target_os = "netbsd"))] -pub type type_of_event_flag = u32; -libc_bitflags!{ - pub struct EventFlag: type_of_event_flag { - EV_ADD; - EV_CLEAR; - EV_DELETE; - EV_DISABLE; - #[cfg(any(target_os = "dragonfly", target_os = "freebsd", - target_os = "ios", target_os = "macos", - target_os = "netbsd", target_os = "openbsd"))] - EV_DISPATCH; - #[cfg(target_os = "freebsd")] - EV_DROP; - EV_ENABLE; - EV_EOF; - EV_ERROR; - #[cfg(any(target_os = "macos", target_os = "ios"))] - EV_FLAG0; - EV_FLAG1; - #[cfg(target_os = "dragonfly")] - EV_NODATA; - EV_ONESHOT; - #[cfg(any(target_os = "macos", target_os = "ios"))] - EV_OOBAND; - #[cfg(any(target_os = "macos", target_os = "ios"))] - EV_POLL; - #[cfg(any(target_os = "dragonfly", target_os = "freebsd", - target_os = "ios", target_os = "macos", - target_os = "netbsd", target_os = "openbsd"))] - EV_RECEIPT; - EV_SYSFLAGS; - } -} - -libc_bitflags!( - pub struct FilterFlag: u32 { - #[cfg(any(target_os = "macos", target_os = "ios"))] - NOTE_ABSOLUTE; - NOTE_ATTRIB; - NOTE_CHILD; - NOTE_DELETE; - #[cfg(target_os = "openbsd")] - NOTE_EOF; - NOTE_EXEC; - NOTE_EXIT; - #[cfg(any(target_os = "macos", target_os = "ios"))] - NOTE_EXITSTATUS; - NOTE_EXTEND; - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] - NOTE_FFAND; - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] - NOTE_FFCOPY; - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] - NOTE_FFCTRLMASK; - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] - NOTE_FFLAGSMASK; - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] - NOTE_FFNOP; - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] - NOTE_FFOR; - NOTE_FORK; - NOTE_LINK; - NOTE_LOWAT; - #[cfg(target_os = "freebsd")] - NOTE_MSECONDS; - #[cfg(any(target_os = "macos", target_os = "ios"))] - NOTE_NONE; - #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))] - NOTE_NSECONDS; - #[cfg(target_os = "dragonfly")] - NOTE_OOB; - NOTE_PCTRLMASK; - NOTE_PDATAMASK; - NOTE_RENAME; - NOTE_REVOKE; - #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))] - NOTE_SECONDS; - #[cfg(any(target_os = "macos", target_os = "ios"))] - NOTE_SIGNAL; - NOTE_TRACK; - NOTE_TRACKERR; - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly"))] - NOTE_TRIGGER; - #[cfg(target_os = "openbsd")] - NOTE_TRUNCATE; - #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))] - NOTE_USECONDS; - #[cfg(any(target_os = "macos", target_os = "ios"))] - NOTE_VM_ERROR; - #[cfg(any(target_os = "macos", target_os = "ios"))] - NOTE_VM_PRESSURE; - #[cfg(any(target_os = "macos", target_os = "ios"))] - NOTE_VM_PRESSURE_SUDDEN_TERMINATE; - #[cfg(any(target_os = "macos", target_os = "ios"))] - NOTE_VM_PRESSURE_TERMINATE; - NOTE_WRITE; - } -); - -pub fn kqueue() -> Result { - let res = unsafe { libc::kqueue() }; - - Errno::result(res) -} - - -// KEvent can't derive Send because on some operating systems, udata is defined -// as a void*. However, KEvent's public API always treats udata as an intptr_t, -// which is safe to Send. -unsafe impl Send for KEvent { -} - -impl KEvent { - pub fn new(ident: uintptr_t, filter: EventFilter, flags: EventFlag, - fflags:FilterFlag, data: intptr_t, udata: intptr_t) -> KEvent { - KEvent { kevent: libc::kevent { - ident, - filter: filter as type_of_event_filter, - flags: flags.bits(), - fflags: fflags.bits(), - data: data as type_of_data, - udata: udata as type_of_udata - } } - } - - pub fn ident(&self) -> uintptr_t { - self.kevent.ident - } - - pub fn filter(&self) -> Result { - self.kevent.filter.try_into() - } - - pub fn flags(&self) -> EventFlag { - EventFlag::from_bits(self.kevent.flags).unwrap() - } - - pub fn fflags(&self) -> FilterFlag { - FilterFlag::from_bits(self.kevent.fflags).unwrap() - } - - pub fn data(&self) -> intptr_t { - self.kevent.data as intptr_t - } - - pub fn udata(&self) -> intptr_t { - self.kevent.udata as intptr_t - } -} - -pub fn kevent(kq: RawFd, - changelist: &[KEvent], - eventlist: &mut [KEvent], - timeout_ms: usize) -> Result { - - // Convert ms to timespec - let timeout = timespec { - tv_sec: (timeout_ms / 1000) as time_t, - tv_nsec: ((timeout_ms % 1000) * 1_000_000) as c_long - }; - - kevent_ts(kq, changelist, eventlist, Some(timeout)) -} - -#[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly", - target_os = "openbsd"))] -type type_of_nchanges = c_int; -#[cfg(target_os = "netbsd")] -type type_of_nchanges = size_t; - -pub fn kevent_ts(kq: RawFd, - changelist: &[KEvent], - eventlist: &mut [KEvent], - timeout_opt: Option) -> Result { - - let res = unsafe { - libc::kevent( - kq, - changelist.as_ptr() as *const libc::kevent, - changelist.len() as type_of_nchanges, - eventlist.as_mut_ptr() as *mut libc::kevent, - eventlist.len() as type_of_nchanges, - if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()}) - }; - - Errno::result(res).map(|r| r as usize) -} - -#[inline] -pub fn ev_set(ev: &mut KEvent, - ident: usize, - filter: EventFilter, - flags: EventFlag, - fflags: FilterFlag, - udata: intptr_t) { - - ev.kevent.ident = ident as uintptr_t; - ev.kevent.filter = filter as type_of_event_filter; - ev.kevent.flags = flags.bits(); - ev.kevent.fflags = fflags.bits(); - ev.kevent.data = 0; - ev.kevent.udata = udata as type_of_udata; -} - -#[test] -fn test_struct_kevent() { - use std::mem; - - let udata : intptr_t = 12345; - - let actual = KEvent::new(0xdead_beef, - EventFilter::EVFILT_READ, - EventFlag::EV_ONESHOT | EventFlag::EV_ADD, - FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT, - 0x1337, - udata); - assert_eq!(0xdead_beef, actual.ident()); - let filter = actual.kevent.filter; - assert_eq!(libc::EVFILT_READ, filter); - assert_eq!(libc::EV_ONESHOT | libc::EV_ADD, actual.flags().bits()); - assert_eq!(libc::NOTE_CHILD | libc::NOTE_EXIT, actual.fflags().bits()); - assert_eq!(0x1337, actual.data() as type_of_data); - assert_eq!(udata as type_of_udata, actual.udata() as type_of_udata); - assert_eq!(mem::size_of::(), mem::size_of::()); -} - -#[test] -fn test_kevent_filter() { - let udata : intptr_t = 12345; - - let actual = KEvent::new(0xdead_beef, - EventFilter::EVFILT_READ, - EventFlag::EV_ONESHOT | EventFlag::EV_ADD, - FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT, - 0x1337, - udata); - assert_eq!(EventFilter::EVFILT_READ, actual.filter().unwrap()); -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/eventfd.rs b/vendor/nix-v0.23.1-patched/src/sys/eventfd.rs deleted file mode 100644 index c54f952f0..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/eventfd.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::os::unix::io::RawFd; -use crate::Result; -use crate::errno::Errno; - -libc_bitflags! { - pub struct EfdFlags: libc::c_int { - EFD_CLOEXEC; // Since Linux 2.6.27 - EFD_NONBLOCK; // Since Linux 2.6.27 - EFD_SEMAPHORE; // Since Linux 2.6.30 - } -} - -pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result { - let res = unsafe { libc::eventfd(initval, flags.bits()) }; - - Errno::result(res).map(|r| r as RawFd) -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/inotify.rs b/vendor/nix-v0.23.1-patched/src/sys/inotify.rs deleted file mode 100644 index 3f5ae22ab..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/inotify.rs +++ /dev/null @@ -1,233 +0,0 @@ -//! Monitoring API for filesystem events. -//! -//! Inotify is a Linux-only API to monitor filesystems events. -//! -//! For more documentation, please read [inotify(7)](https://man7.org/linux/man-pages/man7/inotify.7.html). -//! -//! # Examples -//! -//! Monitor all events happening in directory "test": -//! ```no_run -//! # use nix::sys::inotify::{AddWatchFlags,InitFlags,Inotify}; -//! # -//! // We create a new inotify instance. -//! let instance = Inotify::init(InitFlags::empty()).unwrap(); -//! -//! // We add a new watch on directory "test" for all events. -//! let wd = instance.add_watch("test", AddWatchFlags::IN_ALL_EVENTS).unwrap(); -//! -//! loop { -//! // We read from our inotify instance for events. -//! let events = instance.read_events().unwrap(); -//! println!("Events: {:?}", events); -//! } -//! ``` - -use libc::{ - c_char, - c_int, -}; -use std::ffi::{OsString,OsStr,CStr}; -use std::os::unix::ffi::OsStrExt; -use std::mem::{MaybeUninit, size_of}; -use std::os::unix::io::{RawFd,AsRawFd,FromRawFd}; -use std::ptr; -use crate::unistd::read; -use crate::Result; -use crate::NixPath; -use crate::errno::Errno; - -libc_bitflags! { - /// Configuration options for [`inotify_add_watch`](fn.inotify_add_watch.html). - pub struct AddWatchFlags: u32 { - IN_ACCESS; - IN_MODIFY; - IN_ATTRIB; - IN_CLOSE_WRITE; - IN_CLOSE_NOWRITE; - IN_OPEN; - IN_MOVED_FROM; - IN_MOVED_TO; - IN_CREATE; - IN_DELETE; - IN_DELETE_SELF; - IN_MOVE_SELF; - - IN_UNMOUNT; - IN_Q_OVERFLOW; - IN_IGNORED; - - IN_CLOSE; - IN_MOVE; - - IN_ONLYDIR; - IN_DONT_FOLLOW; - - IN_ISDIR; - IN_ONESHOT; - IN_ALL_EVENTS; - } -} - -libc_bitflags! { - /// Configuration options for [`inotify_init1`](fn.inotify_init1.html). - pub struct InitFlags: c_int { - IN_CLOEXEC; - IN_NONBLOCK; - } -} - -/// An inotify instance. This is also a file descriptor, you can feed it to -/// other interfaces consuming file descriptors, epoll for example. -#[derive(Debug, Clone, Copy)] -pub struct Inotify { - fd: RawFd -} - -/// This object is returned when you create a new watch on an inotify instance. -/// It is then returned as part of an event once triggered. It allows you to -/// know which watch triggered which event. -#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)] -pub struct WatchDescriptor { - wd: i32 -} - -/// A single inotify event. -/// -/// For more documentation see, [inotify(7)](https://man7.org/linux/man-pages/man7/inotify.7.html). -#[derive(Debug)] -pub struct InotifyEvent { - /// Watch descriptor. This field corresponds to the watch descriptor you - /// were issued when calling add_watch. It allows you to know which watch - /// this event comes from. - pub wd: WatchDescriptor, - /// Event mask. This field is a bitfield describing the exact event that - /// occured. - pub mask: AddWatchFlags, - /// This cookie is a number that allows you to connect related events. For - /// now only IN_MOVED_FROM and IN_MOVED_TO can be connected. - pub cookie: u32, - /// Filename. This field exists only if the event was triggered for a file - /// inside the watched directory. - pub name: Option -} - -impl Inotify { - /// Initialize a new inotify instance. - /// - /// Returns a Result containing an inotify instance. - /// - /// For more information see, [inotify_init(2)](https://man7.org/linux/man-pages/man2/inotify_init.2.html). - pub fn init(flags: InitFlags) -> Result { - let res = Errno::result(unsafe { - libc::inotify_init1(flags.bits()) - }); - - res.map(|fd| Inotify { fd }) - } - - /// Adds a new watch on the target file or directory. - /// - /// Returns a watch descriptor. This is not a File Descriptor! - /// - /// For more information see, [inotify_add_watch(2)](https://man7.org/linux/man-pages/man2/inotify_add_watch.2.html). - pub fn add_watch(self, - path: &P, - mask: AddWatchFlags) - -> Result - { - let res = path.with_nix_path(|cstr| { - unsafe { - libc::inotify_add_watch(self.fd, cstr.as_ptr(), mask.bits()) - } - })?; - - Errno::result(res).map(|wd| WatchDescriptor { wd }) - } - - /// Removes an existing watch using the watch descriptor returned by - /// inotify_add_watch. - /// - /// Returns an EINVAL error if the watch descriptor is invalid. - /// - /// For more information see, [inotify_rm_watch(2)](https://man7.org/linux/man-pages/man2/inotify_rm_watch.2.html). - #[cfg(target_os = "linux")] - pub fn rm_watch(self, wd: WatchDescriptor) -> Result<()> { - let res = unsafe { libc::inotify_rm_watch(self.fd, wd.wd) }; - - Errno::result(res).map(drop) - } - - #[cfg(target_os = "android")] - pub fn rm_watch(self, wd: WatchDescriptor) -> Result<()> { - let res = unsafe { libc::inotify_rm_watch(self.fd, wd.wd as u32) }; - - Errno::result(res).map(drop) - } - - /// Reads a collection of events from the inotify file descriptor. This call - /// can either be blocking or non blocking depending on whether IN_NONBLOCK - /// was set at initialization. - /// - /// Returns as many events as available. If the call was non blocking and no - /// events could be read then the EAGAIN error is returned. - pub fn read_events(self) -> Result> { - let header_size = size_of::(); - const BUFSIZ: usize = 4096; - let mut buffer = [0u8; BUFSIZ]; - let mut events = Vec::new(); - let mut offset = 0; - - let nread = read(self.fd, &mut buffer)?; - - while (nread - offset) >= header_size { - let event = unsafe { - let mut event = MaybeUninit::::uninit(); - ptr::copy_nonoverlapping( - buffer.as_ptr().add(offset), - event.as_mut_ptr() as *mut u8, - (BUFSIZ - offset).min(header_size) - ); - event.assume_init() - }; - - let name = match event.len { - 0 => None, - _ => { - let ptr = unsafe { - buffer - .as_ptr() - .add(offset + header_size) - as *const c_char - }; - let cstr = unsafe { CStr::from_ptr(ptr) }; - - Some(OsStr::from_bytes(cstr.to_bytes()).to_owned()) - } - }; - - events.push(InotifyEvent { - wd: WatchDescriptor { wd: event.wd }, - mask: AddWatchFlags::from_bits_truncate(event.mask), - cookie: event.cookie, - name - }); - - offset += header_size + event.len as usize; - } - - Ok(events) - } -} - -impl AsRawFd for Inotify { - fn as_raw_fd(&self) -> RawFd { - self.fd - } -} - -impl FromRawFd for Inotify { - unsafe fn from_raw_fd(fd: RawFd) -> Self { - Inotify { fd } - } -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/ioctl/bsd.rs b/vendor/nix-v0.23.1-patched/src/sys/ioctl/bsd.rs deleted file mode 100644 index 4ce4d332a..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/ioctl/bsd.rs +++ /dev/null @@ -1,109 +0,0 @@ -/// The datatype used for the ioctl number -#[doc(hidden)] -#[cfg(not(target_os = "illumos"))] -pub type ioctl_num_type = ::libc::c_ulong; - -#[doc(hidden)] -#[cfg(target_os = "illumos")] -pub type ioctl_num_type = ::libc::c_int; - -/// The datatype used for the 3rd argument -#[doc(hidden)] -pub type ioctl_param_type = ::libc::c_int; - -mod consts { - use crate::sys::ioctl::ioctl_num_type; - #[doc(hidden)] - pub const VOID: ioctl_num_type = 0x2000_0000; - #[doc(hidden)] - pub const OUT: ioctl_num_type = 0x4000_0000; - #[doc(hidden)] - #[allow(overflowing_literals)] - pub const IN: ioctl_num_type = 0x8000_0000; - #[doc(hidden)] - pub const INOUT: ioctl_num_type = IN|OUT; - #[doc(hidden)] - pub const IOCPARM_MASK: ioctl_num_type = 0x1fff; -} - -pub use self::consts::*; - -#[macro_export] -#[doc(hidden)] -macro_rules! ioc { - ($inout:expr, $group:expr, $num:expr, $len:expr) => ( - $inout | (($len as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::IOCPARM_MASK) << 16) | (($group as $crate::sys::ioctl::ioctl_num_type) << 8) | ($num as $crate::sys::ioctl::ioctl_num_type) - ) -} - -/// Generate an ioctl request code for a command that passes no data. -/// -/// This is equivalent to the `_IO()` macro exposed by the C ioctl API. -/// -/// You should only use this macro directly if the `ioctl` you're working -/// with is "bad" and you cannot use `ioctl_none!()` directly. -/// -/// # Example -/// -/// ``` -/// # #[macro_use] extern crate nix; -/// const KVMIO: u8 = 0xAE; -/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03)); -/// # fn main() {} -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! request_code_none { - ($g:expr, $n:expr) => (ioc!($crate::sys::ioctl::VOID, $g, $n, 0)) -} - -/// Generate an ioctl request code for a command that passes an integer -/// -/// This is equivalent to the `_IOWINT()` macro exposed by the C ioctl API. -/// -/// You should only use this macro directly if the `ioctl` you're working -/// with is "bad" and you cannot use `ioctl_write_int!()` directly. -#[macro_export(local_inner_macros)] -macro_rules! request_code_write_int { - ($g:expr, $n:expr) => (ioc!($crate::sys::ioctl::VOID, $g, $n, ::std::mem::size_of::<$crate::libc::c_int>())) -} - -/// Generate an ioctl request code for a command that reads. -/// -/// This is equivalent to the `_IOR()` macro exposed by the C ioctl API. -/// -/// You should only use this macro directly if the `ioctl` you're working -/// with is "bad" and you cannot use `ioctl_read!()` directly. -/// -/// The read/write direction is relative to userland, so this -/// command would be userland is reading and the kernel is -/// writing. -#[macro_export(local_inner_macros)] -macro_rules! request_code_read { - ($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::OUT, $g, $n, $len)) -} - -/// Generate an ioctl request code for a command that writes. -/// -/// This is equivalent to the `_IOW()` macro exposed by the C ioctl API. -/// -/// You should only use this macro directly if the `ioctl` you're working -/// with is "bad" and you cannot use `ioctl_write!()` directly. -/// -/// The read/write direction is relative to userland, so this -/// command would be userland is writing and the kernel is -/// reading. -#[macro_export(local_inner_macros)] -macro_rules! request_code_write { - ($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::IN, $g, $n, $len)) -} - -/// Generate an ioctl request code for a command that reads and writes. -/// -/// This is equivalent to the `_IOWR()` macro exposed by the C ioctl API. -/// -/// You should only use this macro directly if the `ioctl` you're working -/// with is "bad" and you cannot use `ioctl_readwrite!()` directly. -#[macro_export(local_inner_macros)] -macro_rules! request_code_readwrite { - ($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::INOUT, $g, $n, $len)) -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/ioctl/linux.rs b/vendor/nix-v0.23.1-patched/src/sys/ioctl/linux.rs deleted file mode 100644 index 68ebaba9b..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/ioctl/linux.rs +++ /dev/null @@ -1,141 +0,0 @@ -/// The datatype used for the ioctl number -#[cfg(any(target_os = "android", target_env = "musl"))] -#[doc(hidden)] -pub type ioctl_num_type = ::libc::c_int; -#[cfg(not(any(target_os = "android", target_env = "musl")))] -#[doc(hidden)] -pub type ioctl_num_type = ::libc::c_ulong; -/// The datatype used for the 3rd argument -#[doc(hidden)] -pub type ioctl_param_type = ::libc::c_ulong; - -#[doc(hidden)] -pub const NRBITS: ioctl_num_type = 8; -#[doc(hidden)] -pub const TYPEBITS: ioctl_num_type = 8; - -#[cfg(any(target_arch = "mips", target_arch = "mips64", target_arch = "powerpc", target_arch = "powerpc64", target_arch = "sparc64"))] -mod consts { - #[doc(hidden)] - pub const NONE: u8 = 1; - #[doc(hidden)] - pub const READ: u8 = 2; - #[doc(hidden)] - pub const WRITE: u8 = 4; - #[doc(hidden)] - pub const SIZEBITS: u8 = 13; - #[doc(hidden)] - pub const DIRBITS: u8 = 3; -} - -// "Generic" ioctl protocol -#[cfg(any(target_arch = "x86", - target_arch = "arm", - target_arch = "s390x", - target_arch = "x86_64", - target_arch = "aarch64", - target_arch = "riscv64"))] -mod consts { - #[doc(hidden)] - pub const NONE: u8 = 0; - #[doc(hidden)] - pub const READ: u8 = 2; - #[doc(hidden)] - pub const WRITE: u8 = 1; - #[doc(hidden)] - pub const SIZEBITS: u8 = 14; - #[doc(hidden)] - pub const DIRBITS: u8 = 2; -} - -pub use self::consts::*; - -#[doc(hidden)] -pub const NRSHIFT: ioctl_num_type = 0; -#[doc(hidden)] -pub const TYPESHIFT: ioctl_num_type = NRSHIFT + NRBITS as ioctl_num_type; -#[doc(hidden)] -pub const SIZESHIFT: ioctl_num_type = TYPESHIFT + TYPEBITS as ioctl_num_type; -#[doc(hidden)] -pub const DIRSHIFT: ioctl_num_type = SIZESHIFT + SIZEBITS as ioctl_num_type; - -#[doc(hidden)] -pub const NRMASK: ioctl_num_type = (1 << NRBITS) - 1; -#[doc(hidden)] -pub const TYPEMASK: ioctl_num_type = (1 << TYPEBITS) - 1; -#[doc(hidden)] -pub const SIZEMASK: ioctl_num_type = (1 << SIZEBITS) - 1; -#[doc(hidden)] -pub const DIRMASK: ioctl_num_type = (1 << DIRBITS) - 1; - -/// Encode an ioctl command. -#[macro_export] -#[doc(hidden)] -macro_rules! ioc { - ($dir:expr, $ty:expr, $nr:expr, $sz:expr) => ( - (($dir as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::DIRMASK) << $crate::sys::ioctl::DIRSHIFT) | - (($ty as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::TYPEMASK) << $crate::sys::ioctl::TYPESHIFT) | - (($nr as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::NRMASK) << $crate::sys::ioctl::NRSHIFT) | - (($sz as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::SIZEMASK) << $crate::sys::ioctl::SIZESHIFT)) -} - -/// Generate an ioctl request code for a command that passes no data. -/// -/// This is equivalent to the `_IO()` macro exposed by the C ioctl API. -/// -/// You should only use this macro directly if the `ioctl` you're working -/// with is "bad" and you cannot use `ioctl_none!()` directly. -/// -/// # Example -/// -/// ``` -/// # #[macro_use] extern crate nix; -/// const KVMIO: u8 = 0xAE; -/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03)); -/// # fn main() {} -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! request_code_none { - ($ty:expr, $nr:expr) => (ioc!($crate::sys::ioctl::NONE, $ty, $nr, 0)) -} - -/// Generate an ioctl request code for a command that reads. -/// -/// This is equivalent to the `_IOR()` macro exposed by the C ioctl API. -/// -/// You should only use this macro directly if the `ioctl` you're working -/// with is "bad" and you cannot use `ioctl_read!()` directly. -/// -/// The read/write direction is relative to userland, so this -/// command would be userland is reading and the kernel is -/// writing. -#[macro_export(local_inner_macros)] -macro_rules! request_code_read { - ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::READ, $ty, $nr, $sz)) -} - -/// Generate an ioctl request code for a command that writes. -/// -/// This is equivalent to the `_IOW()` macro exposed by the C ioctl API. -/// -/// You should only use this macro directly if the `ioctl` you're working -/// with is "bad" and you cannot use `ioctl_write!()` directly. -/// -/// The read/write direction is relative to userland, so this -/// command would be userland is writing and the kernel is -/// reading. -#[macro_export(local_inner_macros)] -macro_rules! request_code_write { - ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::WRITE, $ty, $nr, $sz)) -} - -/// Generate an ioctl request code for a command that reads and writes. -/// -/// This is equivalent to the `_IOWR()` macro exposed by the C ioctl API. -/// -/// You should only use this macro directly if the `ioctl` you're working -/// with is "bad" and you cannot use `ioctl_readwrite!()` directly. -#[macro_export(local_inner_macros)] -macro_rules! request_code_readwrite { - ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::READ | $crate::sys::ioctl::WRITE, $ty, $nr, $sz)) -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/ioctl/mod.rs b/vendor/nix-v0.23.1-patched/src/sys/ioctl/mod.rs deleted file mode 100644 index 203b7d06f..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/ioctl/mod.rs +++ /dev/null @@ -1,778 +0,0 @@ -//! Provide helpers for making ioctl system calls. -//! -//! This library is pretty low-level and messy. `ioctl` is not fun. -//! -//! What is an `ioctl`? -//! =================== -//! -//! The `ioctl` syscall is the grab-bag syscall on POSIX systems. Don't want to add a new -//! syscall? Make it an `ioctl`! `ioctl` refers to both the syscall, and the commands that can be -//! sent with it. `ioctl` stands for "IO control", and the commands are always sent to a file -//! descriptor. -//! -//! It is common to see `ioctl`s used for the following purposes: -//! -//! * Provide read/write access to out-of-band data related to a device such as configuration -//! (for instance, setting serial port options) -//! * Provide a mechanism for performing full-duplex data transfers (for instance, xfer on SPI -//! devices). -//! * Provide access to control functions on a device (for example, on Linux you can send -//! commands like pause, resume, and eject to the CDROM device. -//! * Do whatever else the device driver creator thought made most sense. -//! -//! `ioctl`s are synchronous system calls and are similar to read and write calls in that regard. -//! They operate on file descriptors and have an identifier that specifies what the ioctl is. -//! Additionally they may read or write data and therefore need to pass along a data pointer. -//! Besides the semantics of the ioctls being confusing, the generation of this identifer can also -//! be difficult. -//! -//! Historically `ioctl` numbers were arbitrary hard-coded values. In Linux (before 2.6) and some -//! unices this has changed to a more-ordered system where the ioctl numbers are partitioned into -//! subcomponents (For linux this is documented in -//! [`Documentation/ioctl/ioctl-number.rst`](https://elixir.bootlin.com/linux/latest/source/Documentation/userspace-api/ioctl/ioctl-number.rst)): -//! -//! * Number: The actual ioctl ID -//! * Type: A grouping of ioctls for a common purpose or driver -//! * Size: The size in bytes of the data that will be transferred -//! * Direction: Whether there is any data and if it's read, write, or both -//! -//! Newer drivers should not generate complete integer identifiers for their `ioctl`s instead -//! preferring to use the 4 components above to generate the final ioctl identifier. Because of -//! how old `ioctl`s are, however, there are many hard-coded `ioctl` identifiers. These are -//! commonly referred to as "bad" in `ioctl` documentation. -//! -//! Defining `ioctl`s -//! ================= -//! -//! This library provides several `ioctl_*!` macros for binding `ioctl`s. These generate public -//! unsafe functions that can then be used for calling the ioctl. This macro has a few different -//! ways it can be used depending on the specific ioctl you're working with. -//! -//! A simple `ioctl` is `SPI_IOC_RD_MODE`. This ioctl works with the SPI interface on Linux. This -//! specific `ioctl` reads the mode of the SPI device as a `u8`. It's declared in -//! `/include/uapi/linux/spi/spidev.h` as `_IOR(SPI_IOC_MAGIC, 1, __u8)`. Since it uses the `_IOR` -//! macro, we know it's a `read` ioctl and can use the `ioctl_read!` macro as follows: -//! -//! ``` -//! # #[macro_use] extern crate nix; -//! const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h -//! const SPI_IOC_TYPE_MODE: u8 = 1; -//! ioctl_read!(spi_read_mode, SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, u8); -//! # fn main() {} -//! ``` -//! -//! This generates the function: -//! -//! ``` -//! # #[macro_use] extern crate nix; -//! # use std::mem; -//! # use nix::{libc, Result}; -//! # use nix::errno::Errno; -//! # use nix::libc::c_int as c_int; -//! # const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h -//! # const SPI_IOC_TYPE_MODE: u8 = 1; -//! pub unsafe fn spi_read_mode(fd: c_int, data: *mut u8) -> Result { -//! let res = libc::ioctl(fd, request_code_read!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, mem::size_of::()), data); -//! Errno::result(res) -//! } -//! # fn main() {} -//! ``` -//! -//! The return value for the wrapper functions generated by the `ioctl_*!` macros are `nix::Error`s. -//! These are generated by assuming the return value of the ioctl is `-1` on error and everything -//! else is a valid return value. If this is not the case, `Result::map` can be used to map some -//! of the range of "good" values (-Inf..-2, 0..Inf) into a smaller range in a helper function. -//! -//! Writing `ioctl`s generally use pointers as their data source and these should use the -//! `ioctl_write_ptr!`. But in some cases an `int` is passed directly. For these `ioctl`s use the -//! `ioctl_write_int!` macro. This variant does not take a type as the last argument: -//! -//! ``` -//! # #[macro_use] extern crate nix; -//! const HCI_IOC_MAGIC: u8 = b'k'; -//! const HCI_IOC_HCIDEVUP: u8 = 1; -//! ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP); -//! # fn main() {} -//! ``` -//! -//! Some `ioctl`s don't transfer any data, and those should use `ioctl_none!`. This macro -//! doesn't take a type and so it is declared similar to the `write_int` variant shown above. -//! -//! The mode for a given `ioctl` should be clear from the documentation if it has good -//! documentation. Otherwise it will be clear based on the macro used to generate the `ioctl` -//! number where `_IO`, `_IOR`, `_IOW`, and `_IOWR` map to "none", "read", "write_*", and "readwrite" -//! respectively. To determine the specific `write_` variant to use you'll need to find -//! what the argument type is supposed to be. If it's an `int`, then `write_int` should be used, -//! otherwise it should be a pointer and `write_ptr` should be used. On Linux the -//! [`ioctl_list` man page](https://man7.org/linux/man-pages/man2/ioctl_list.2.html) describes a -//! large number of `ioctl`s and describes their argument data type. -//! -//! Using "bad" `ioctl`s -//! -------------------- -//! -//! As mentioned earlier, there are many old `ioctl`s that do not use the newer method of -//! generating `ioctl` numbers and instead use hardcoded values. These can be used with the -//! `ioctl_*_bad!` macros. This naming comes from the Linux kernel which refers to these -//! `ioctl`s as "bad". These are a different variant as they bypass calling the macro that generates -//! the ioctl number and instead use the defined value directly. -//! -//! For example the `TCGETS` `ioctl` reads a `termios` data structure for a given file descriptor. -//! It's defined as `0x5401` in `ioctls.h` on Linux and can be implemented as: -//! -//! ``` -//! # #[macro_use] extern crate nix; -//! # #[cfg(any(target_os = "android", target_os = "linux"))] -//! # use nix::libc::TCGETS as TCGETS; -//! # #[cfg(any(target_os = "android", target_os = "linux"))] -//! # use nix::libc::termios as termios; -//! # #[cfg(any(target_os = "android", target_os = "linux"))] -//! ioctl_read_bad!(tcgets, TCGETS, termios); -//! # fn main() {} -//! ``` -//! -//! The generated function has the same form as that generated by `ioctl_read!`: -//! -//! ```text -//! pub unsafe fn tcgets(fd: c_int, data: *mut termios) -> Result; -//! ``` -//! -//! Working with Arrays -//! ------------------- -//! -//! Some `ioctl`s work with entire arrays of elements. These are supported by the `ioctl_*_buf` -//! family of macros: `ioctl_read_buf`, `ioctl_write_buf`, and `ioctl_readwrite_buf`. Note that -//! there are no "bad" versions for working with buffers. The generated functions include a `len` -//! argument to specify the number of elements (where the type of each element is specified in the -//! macro). -//! -//! Again looking to the SPI `ioctl`s on Linux for an example, there is a `SPI_IOC_MESSAGE` `ioctl` -//! that queues up multiple SPI messages by writing an entire array of `spi_ioc_transfer` structs. -//! `linux/spi/spidev.h` defines a macro to calculate the `ioctl` number like: -//! -//! ```C -//! #define SPI_IOC_MAGIC 'k' -//! #define SPI_MSGSIZE(N) ... -//! #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)]) -//! ``` -//! -//! The `SPI_MSGSIZE(N)` calculation is already handled by the `ioctl_*!` macros, so all that's -//! needed to define this `ioctl` is: -//! -//! ``` -//! # #[macro_use] extern crate nix; -//! const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h -//! const SPI_IOC_TYPE_MESSAGE: u8 = 0; -//! # pub struct spi_ioc_transfer(u64); -//! ioctl_write_buf!(spi_transfer, SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, spi_ioc_transfer); -//! # fn main() {} -//! ``` -//! -//! This generates a function like: -//! -//! ``` -//! # #[macro_use] extern crate nix; -//! # use std::mem; -//! # use nix::{libc, Result}; -//! # use nix::errno::Errno; -//! # use nix::libc::c_int as c_int; -//! # const SPI_IOC_MAGIC: u8 = b'k'; -//! # const SPI_IOC_TYPE_MESSAGE: u8 = 0; -//! # pub struct spi_ioc_transfer(u64); -//! pub unsafe fn spi_message(fd: c_int, data: &mut [spi_ioc_transfer]) -> Result { -//! let res = libc::ioctl(fd, -//! request_code_write!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, data.len() * mem::size_of::()), -//! data); -//! Errno::result(res) -//! } -//! # fn main() {} -//! ``` -//! -//! Finding `ioctl` Documentation -//! ----------------------------- -//! -//! For Linux, look at your system's headers. For example, `/usr/include/linux/input.h` has a lot -//! of lines defining macros which use `_IO`, `_IOR`, `_IOW`, `_IOC`, and `_IOWR`. Some `ioctl`s are -//! documented directly in the headers defining their constants, but others have more extensive -//! documentation in man pages (like termios' `ioctl`s which are in `tty_ioctl(4)`). -//! -//! Documenting the Generated Functions -//! =================================== -//! -//! In many cases, users will wish for the functions generated by the `ioctl` -//! macro to be public and documented. For this reason, the generated functions -//! are public by default. If you wish to hide the ioctl, you will need to put -//! them in a private module. -//! -//! For documentation, it is possible to use doc comments inside the `ioctl_*!` macros. Here is an -//! example : -//! -//! ``` -//! # #[macro_use] extern crate nix; -//! # use nix::libc::c_int; -//! ioctl_read! { -//! /// Make the given terminal the controlling terminal of the calling process. The calling -//! /// process must be a session leader and not have a controlling terminal already. If the -//! /// terminal is already the controlling terminal of a different session group then the -//! /// ioctl will fail with **EPERM**, unless the caller is root (more precisely: has the -//! /// **CAP_SYS_ADMIN** capability) and arg equals 1, in which case the terminal is stolen -//! /// and all processes that had it as controlling terminal lose it. -//! tiocsctty, b't', 19, c_int -//! } -//! -//! # fn main() {} -//! ``` -use cfg_if::cfg_if; - -#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))] -#[macro_use] -mod linux; - -#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))] -pub use self::linux::*; - -#[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "illumos", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] -#[macro_use] -mod bsd; - -#[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "illumos", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] -pub use self::bsd::*; - -/// Convert raw ioctl return value to a Nix result -#[macro_export] -#[doc(hidden)] -macro_rules! convert_ioctl_res { - ($w:expr) => ( - { - $crate::errno::Errno::result($w) - } - ); -} - -/// Generates a wrapper function for an ioctl that passes no data to the kernel. -/// -/// The arguments to this macro are: -/// -/// * The function name -/// * The ioctl identifier -/// * The ioctl sequence number -/// -/// The generated function has the following signature: -/// -/// ```rust,ignore -/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int) -> Result -/// ``` -/// -/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). -/// -/// # Example -/// -/// The `videodev2` driver on Linux defines the `log_status` `ioctl` as: -/// -/// ```C -/// #define VIDIOC_LOG_STATUS _IO('V', 70) -/// ``` -/// -/// This can be implemented in Rust like: -/// -/// ```no_run -/// # #[macro_use] extern crate nix; -/// ioctl_none!(log_status, b'V', 70); -/// fn main() {} -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! ioctl_none { - ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => ( - $(#[$attr])* - pub unsafe fn $name(fd: $crate::libc::c_int) - -> $crate::Result<$crate::libc::c_int> { - convert_ioctl_res!($crate::libc::ioctl(fd, request_code_none!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type)) - } - ) -} - -/// Generates a wrapper function for a "bad" ioctl that passes no data to the kernel. -/// -/// The arguments to this macro are: -/// -/// * The function name -/// * The ioctl request code -/// -/// The generated function has the following signature: -/// -/// ```rust,ignore -/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int) -> Result -/// ``` -/// -/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). -/// -/// # Example -/// -/// ```no_run -/// # #[macro_use] extern crate nix; -/// # use libc::TIOCNXCL; -/// # use std::fs::File; -/// # use std::os::unix::io::AsRawFd; -/// ioctl_none_bad!(tiocnxcl, TIOCNXCL); -/// fn main() { -/// let file = File::open("/dev/ttyUSB0").unwrap(); -/// unsafe { tiocnxcl(file.as_raw_fd()) }.unwrap(); -/// } -/// ``` -// TODO: add an example using request_code_*!() -#[macro_export(local_inner_macros)] -macro_rules! ioctl_none_bad { - ($(#[$attr:meta])* $name:ident, $nr:expr) => ( - $(#[$attr])* - pub unsafe fn $name(fd: $crate::libc::c_int) - -> $crate::Result<$crate::libc::c_int> { - convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type)) - } - ) -} - -/// Generates a wrapper function for an ioctl that reads data from the kernel. -/// -/// The arguments to this macro are: -/// -/// * The function name -/// * The ioctl identifier -/// * The ioctl sequence number -/// * The data type passed by this ioctl -/// -/// The generated function has the following signature: -/// -/// ```rust,ignore -/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result -/// ``` -/// -/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). -/// -/// # Example -/// -/// ``` -/// # #[macro_use] extern crate nix; -/// const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h -/// const SPI_IOC_TYPE_MODE: u8 = 1; -/// ioctl_read!(spi_read_mode, SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, u8); -/// # fn main() {} -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! ioctl_read { - ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => ( - $(#[$attr])* - pub unsafe fn $name(fd: $crate::libc::c_int, - data: *mut $ty) - -> $crate::Result<$crate::libc::c_int> { - convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data)) - } - ) -} - -/// Generates a wrapper function for a "bad" ioctl that reads data from the kernel. -/// -/// The arguments to this macro are: -/// -/// * The function name -/// * The ioctl request code -/// * The data type passed by this ioctl -/// -/// The generated function has the following signature: -/// -/// ```rust,ignore -/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result -/// ``` -/// -/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). -/// -/// # Example -/// -/// ``` -/// # #[macro_use] extern crate nix; -/// # #[cfg(any(target_os = "android", target_os = "linux"))] -/// ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios); -/// # fn main() {} -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! ioctl_read_bad { - ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => ( - $(#[$attr])* - pub unsafe fn $name(fd: $crate::libc::c_int, - data: *mut $ty) - -> $crate::Result<$crate::libc::c_int> { - convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data)) - } - ) -} - -/// Generates a wrapper function for an ioctl that writes data through a pointer to the kernel. -/// -/// The arguments to this macro are: -/// -/// * The function name -/// * The ioctl identifier -/// * The ioctl sequence number -/// * The data type passed by this ioctl -/// -/// The generated function has the following signature: -/// -/// ```rust,ignore -/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *const DATA_TYPE) -> Result -/// ``` -/// -/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). -/// -/// # Example -/// -/// ``` -/// # #[macro_use] extern crate nix; -/// # pub struct v4l2_audio {} -/// ioctl_write_ptr!(s_audio, b'V', 34, v4l2_audio); -/// # fn main() {} -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! ioctl_write_ptr { - ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => ( - $(#[$attr])* - pub unsafe fn $name(fd: $crate::libc::c_int, - data: *const $ty) - -> $crate::Result<$crate::libc::c_int> { - convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data)) - } - ) -} - -/// Generates a wrapper function for a "bad" ioctl that writes data through a pointer to the kernel. -/// -/// The arguments to this macro are: -/// -/// * The function name -/// * The ioctl request code -/// * The data type passed by this ioctl -/// -/// The generated function has the following signature: -/// -/// ```rust,ignore -/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *const DATA_TYPE) -> Result -/// ``` -/// -/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). -/// -/// # Example -/// -/// ``` -/// # #[macro_use] extern crate nix; -/// # #[cfg(any(target_os = "android", target_os = "linux"))] -/// ioctl_write_ptr_bad!(tcsets, libc::TCSETS, libc::termios); -/// # fn main() {} -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! ioctl_write_ptr_bad { - ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => ( - $(#[$attr])* - pub unsafe fn $name(fd: $crate::libc::c_int, - data: *const $ty) - -> $crate::Result<$crate::libc::c_int> { - convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data)) - } - ) -} - -cfg_if!{ - if #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] { - /// Generates a wrapper function for a ioctl that writes an integer to the kernel. - /// - /// The arguments to this macro are: - /// - /// * The function name - /// * The ioctl identifier - /// * The ioctl sequence number - /// - /// The generated function has the following signature: - /// - /// ```rust,ignore - /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: nix::sys::ioctl::ioctl_param_type) -> Result - /// ``` - /// - /// `nix::sys::ioctl::ioctl_param_type` depends on the OS: - /// * BSD - `libc::c_int` - /// * Linux - `libc::c_ulong` - /// - /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). - /// - /// # Example - /// - /// ``` - /// # #[macro_use] extern crate nix; - /// ioctl_write_int!(vt_activate, b'v', 4); - /// # fn main() {} - /// ``` - #[macro_export(local_inner_macros)] - macro_rules! ioctl_write_int { - ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => ( - $(#[$attr])* - pub unsafe fn $name(fd: $crate::libc::c_int, - data: $crate::sys::ioctl::ioctl_param_type) - -> $crate::Result<$crate::libc::c_int> { - convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write_int!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type, data)) - } - ) - } - } else { - /// Generates a wrapper function for a ioctl that writes an integer to the kernel. - /// - /// The arguments to this macro are: - /// - /// * The function name - /// * The ioctl identifier - /// * The ioctl sequence number - /// - /// The generated function has the following signature: - /// - /// ```rust,ignore - /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: nix::sys::ioctl::ioctl_param_type) -> Result - /// ``` - /// - /// `nix::sys::ioctl::ioctl_param_type` depends on the OS: - /// * BSD - `libc::c_int` - /// * Linux - `libc::c_ulong` - /// - /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). - /// - /// # Example - /// - /// ``` - /// # #[macro_use] extern crate nix; - /// const HCI_IOC_MAGIC: u8 = b'k'; - /// const HCI_IOC_HCIDEVUP: u8 = 1; - /// ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP); - /// # fn main() {} - /// ``` - #[macro_export(local_inner_macros)] - macro_rules! ioctl_write_int { - ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => ( - $(#[$attr])* - pub unsafe fn $name(fd: $crate::libc::c_int, - data: $crate::sys::ioctl::ioctl_param_type) - -> $crate::Result<$crate::libc::c_int> { - convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$crate::libc::c_int>()) as $crate::sys::ioctl::ioctl_num_type, data)) - } - ) - } - } -} - -/// Generates a wrapper function for a "bad" ioctl that writes an integer to the kernel. -/// -/// The arguments to this macro are: -/// -/// * The function name -/// * The ioctl request code -/// -/// The generated function has the following signature: -/// -/// ```rust,ignore -/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: libc::c_int) -> Result -/// ``` -/// -/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). -/// -/// # Examples -/// -/// ``` -/// # #[macro_use] extern crate nix; -/// # #[cfg(any(target_os = "android", target_os = "linux"))] -/// ioctl_write_int_bad!(tcsbrk, libc::TCSBRK); -/// # fn main() {} -/// ``` -/// -/// ```rust -/// # #[macro_use] extern crate nix; -/// const KVMIO: u8 = 0xAE; -/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03)); -/// # fn main() {} -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! ioctl_write_int_bad { - ($(#[$attr:meta])* $name:ident, $nr:expr) => ( - $(#[$attr])* - pub unsafe fn $name(fd: $crate::libc::c_int, - data: $crate::libc::c_int) - -> $crate::Result<$crate::libc::c_int> { - convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data)) - } - ) -} - -/// Generates a wrapper function for an ioctl that reads and writes data to the kernel. -/// -/// The arguments to this macro are: -/// -/// * The function name -/// * The ioctl identifier -/// * The ioctl sequence number -/// * The data type passed by this ioctl -/// -/// The generated function has the following signature: -/// -/// ```rust,ignore -/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result -/// ``` -/// -/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). -/// -/// # Example -/// -/// ``` -/// # #[macro_use] extern crate nix; -/// # pub struct v4l2_audio {} -/// ioctl_readwrite!(enum_audio, b'V', 65, v4l2_audio); -/// # fn main() {} -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! ioctl_readwrite { - ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => ( - $(#[$attr])* - pub unsafe fn $name(fd: $crate::libc::c_int, - data: *mut $ty) - -> $crate::Result<$crate::libc::c_int> { - convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data)) - } - ) -} - -/// Generates a wrapper function for a "bad" ioctl that reads and writes data to the kernel. -/// -/// The arguments to this macro are: -/// -/// * The function name -/// * The ioctl request code -/// * The data type passed by this ioctl -/// -/// The generated function has the following signature: -/// -/// ```rust,ignore -/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result -/// ``` -/// -/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). -// TODO: Find an example for ioctl_readwrite_bad -#[macro_export(local_inner_macros)] -macro_rules! ioctl_readwrite_bad { - ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => ( - $(#[$attr])* - pub unsafe fn $name(fd: $crate::libc::c_int, - data: *mut $ty) - -> $crate::Result<$crate::libc::c_int> { - convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data)) - } - ) -} - -/// Generates a wrapper function for an ioctl that reads an array of elements from the kernel. -/// -/// The arguments to this macro are: -/// -/// * The function name -/// * The ioctl identifier -/// * The ioctl sequence number -/// * The data type passed by this ioctl -/// -/// The generated function has the following signature: -/// -/// ```rust,ignore -/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &mut [DATA_TYPE]) -> Result -/// ``` -/// -/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). -// TODO: Find an example for ioctl_read_buf -#[macro_export(local_inner_macros)] -macro_rules! ioctl_read_buf { - ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => ( - $(#[$attr])* - pub unsafe fn $name(fd: $crate::libc::c_int, - data: &mut [$ty]) - -> $crate::Result<$crate::libc::c_int> { - convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data)) - } - ) -} - -/// Generates a wrapper function for an ioctl that writes an array of elements to the kernel. -/// -/// The arguments to this macro are: -/// -/// * The function name -/// * The ioctl identifier -/// * The ioctl sequence number -/// * The data type passed by this ioctl -/// -/// The generated function has the following signature: -/// -/// ```rust,ignore -/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &[DATA_TYPE]) -> Result -/// ``` -/// -/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). -/// -/// # Examples -/// -/// ``` -/// # #[macro_use] extern crate nix; -/// const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h -/// const SPI_IOC_TYPE_MESSAGE: u8 = 0; -/// # pub struct spi_ioc_transfer(u64); -/// ioctl_write_buf!(spi_transfer, SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, spi_ioc_transfer); -/// # fn main() {} -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! ioctl_write_buf { - ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => ( - $(#[$attr])* - pub unsafe fn $name(fd: $crate::libc::c_int, - data: &[$ty]) - -> $crate::Result<$crate::libc::c_int> { - convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data)) - } - ) -} - -/// Generates a wrapper function for an ioctl that reads and writes an array of elements to the kernel. -/// -/// The arguments to this macro are: -/// -/// * The function name -/// * The ioctl identifier -/// * The ioctl sequence number -/// * The data type passed by this ioctl -/// -/// The generated function has the following signature: -/// -/// ```rust,ignore -/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &mut [DATA_TYPE]) -> Result -/// ``` -/// -/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). -// TODO: Find an example for readwrite_buf -#[macro_export(local_inner_macros)] -macro_rules! ioctl_readwrite_buf { - ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => ( - $(#[$attr])* - pub unsafe fn $name(fd: $crate::libc::c_int, - data: &mut [$ty]) - -> $crate::Result<$crate::libc::c_int> { - convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data)) - } - ) -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/memfd.rs b/vendor/nix-v0.23.1-patched/src/sys/memfd.rs deleted file mode 100644 index 0236eef63..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/memfd.rs +++ /dev/null @@ -1,19 +0,0 @@ -use std::os::unix::io::RawFd; -use crate::Result; -use crate::errno::Errno; -use std::ffi::CStr; - -libc_bitflags!( - pub struct MemFdCreateFlag: libc::c_uint { - MFD_CLOEXEC; - MFD_ALLOW_SEALING; - } -); - -pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result { - let res = unsafe { - libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags.bits()) - }; - - Errno::result(res).map(|r| r as RawFd) -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/mman.rs b/vendor/nix-v0.23.1-patched/src/sys/mman.rs deleted file mode 100644 index 882a2b944..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/mman.rs +++ /dev/null @@ -1,464 +0,0 @@ -use crate::Result; -#[cfg(not(target_os = "android"))] -use crate::NixPath; -use crate::errno::Errno; -#[cfg(not(target_os = "android"))] -use crate::fcntl::OFlag; -use libc::{self, c_int, c_void, size_t, off_t}; -#[cfg(not(target_os = "android"))] -use crate::sys::stat::Mode; -use std::os::unix::io::RawFd; - -libc_bitflags!{ - /// Desired memory protection of a memory mapping. - pub struct ProtFlags: c_int { - /// Pages cannot be accessed. - PROT_NONE; - /// Pages can be read. - PROT_READ; - /// Pages can be written. - PROT_WRITE; - /// Pages can be executed - PROT_EXEC; - /// Apply protection up to the end of a mapping that grows upwards. - #[cfg(any(target_os = "android", target_os = "linux"))] - PROT_GROWSDOWN; - /// Apply protection down to the beginning of a mapping that grows downwards. - #[cfg(any(target_os = "android", target_os = "linux"))] - PROT_GROWSUP; - } -} - -libc_bitflags!{ - /// Additional parameters for `mmap()`. - pub struct MapFlags: c_int { - /// Compatibility flag. Ignored. - MAP_FILE; - /// Share this mapping. Mutually exclusive with `MAP_PRIVATE`. - MAP_SHARED; - /// Create a private copy-on-write mapping. Mutually exclusive with `MAP_SHARED`. - MAP_PRIVATE; - /// Place the mapping at exactly the address specified in `addr`. - MAP_FIXED; - /// To be used with `MAP_FIXED`, to forbid the system - /// to select a different address than the one specified. - #[cfg(target_os = "freebsd")] - MAP_EXCL; - /// Synonym for `MAP_ANONYMOUS`. - MAP_ANON; - /// The mapping is not backed by any file. - MAP_ANONYMOUS; - /// Put the mapping into the first 2GB of the process address space. - #[cfg(any(all(any(target_os = "android", target_os = "linux"), - any(target_arch = "x86", target_arch = "x86_64")), - all(target_os = "linux", target_env = "musl", any(target_arch = "x86", target_arch = "x86_64")), - all(target_os = "freebsd", target_pointer_width = "64")))] - MAP_32BIT; - /// Used for stacks; indicates to the kernel that the mapping should extend downward in memory. - #[cfg(any(target_os = "android", target_os = "linux"))] - MAP_GROWSDOWN; - /// Compatibility flag. Ignored. - #[cfg(any(target_os = "android", target_os = "linux"))] - MAP_DENYWRITE; - /// Compatibility flag. Ignored. - #[cfg(any(target_os = "android", target_os = "linux"))] - MAP_EXECUTABLE; - /// Mark the mmaped region to be locked in the same way as `mlock(2)`. - #[cfg(any(target_os = "android", target_os = "linux"))] - MAP_LOCKED; - /// Do not reserve swap space for this mapping. - /// - /// This was removed in FreeBSD 11 and is unused in DragonFlyBSD. - #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd")))] - MAP_NORESERVE; - /// Populate page tables for a mapping. - #[cfg(any(target_os = "android", target_os = "linux"))] - MAP_POPULATE; - /// Only meaningful when used with `MAP_POPULATE`. Don't perform read-ahead. - #[cfg(any(target_os = "android", target_os = "linux"))] - MAP_NONBLOCK; - /// Allocate the mapping using "huge pages." - #[cfg(any(target_os = "android", target_os = "linux"))] - MAP_HUGETLB; - /// Make use of 64KB huge page (must be supported by the system) - #[cfg(target_os = "linux")] - MAP_HUGE_64KB; - /// Make use of 512KB huge page (must be supported by the system) - #[cfg(target_os = "linux")] - MAP_HUGE_512KB; - /// Make use of 1MB huge page (must be supported by the system) - #[cfg(target_os = "linux")] - MAP_HUGE_1MB; - /// Make use of 2MB huge page (must be supported by the system) - #[cfg(target_os = "linux")] - MAP_HUGE_2MB; - /// Make use of 8MB huge page (must be supported by the system) - #[cfg(target_os = "linux")] - MAP_HUGE_8MB; - /// Make use of 16MB huge page (must be supported by the system) - #[cfg(target_os = "linux")] - MAP_HUGE_16MB; - /// Make use of 32MB huge page (must be supported by the system) - #[cfg(target_os = "linux")] - MAP_HUGE_32MB; - /// Make use of 256MB huge page (must be supported by the system) - #[cfg(target_os = "linux")] - MAP_HUGE_256MB; - /// Make use of 512MB huge page (must be supported by the system) - #[cfg(target_os = "linux")] - MAP_HUGE_512MB; - /// Make use of 1GB huge page (must be supported by the system) - #[cfg(target_os = "linux")] - MAP_HUGE_1GB; - /// Make use of 2GB huge page (must be supported by the system) - #[cfg(target_os = "linux")] - MAP_HUGE_2GB; - /// Make use of 16GB huge page (must be supported by the system) - #[cfg(target_os = "linux")] - MAP_HUGE_16GB; - - /// Lock the mapped region into memory as with `mlock(2)`. - #[cfg(target_os = "netbsd")] - MAP_WIRED; - /// Causes dirtied data in the specified range to be flushed to disk only when necessary. - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - MAP_NOSYNC; - /// Rename private pages to a file. - /// - /// This was removed in FreeBSD 11 and is unused in DragonFlyBSD. - #[cfg(any(target_os = "netbsd", target_os = "openbsd"))] - MAP_RENAME; - /// Region may contain semaphores. - #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))] - MAP_HASSEMAPHORE; - /// Region grows down, like a stack. - #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux", target_os = "openbsd"))] - MAP_STACK; - /// Pages in this mapping are not retained in the kernel's memory cache. - #[cfg(any(target_os = "ios", target_os = "macos"))] - MAP_NOCACHE; - /// Allows the W/X bit on the page, it's necessary on aarch64 architecture. - #[cfg(any(target_os = "ios", target_os = "macos"))] - MAP_JIT; - /// Allows to use large pages, underlying alignment based on size. - #[cfg(target_os = "freesd")] - MAP_ALIGNED_SUPER; - /// Pages will be discarded in the core dumps. - #[cfg(target_os = "openbsd")] - MAP_CONCEAL; - } -} - -#[cfg(any(target_os = "linux", target_os = "netbsd"))] -libc_bitflags!{ - /// Options for `mremap()`. - pub struct MRemapFlags: c_int { - /// Permit the kernel to relocate the mapping to a new virtual address, if necessary. - #[cfg(target_os = "linux")] - MREMAP_MAYMOVE; - /// Place the mapping at exactly the address specified in `new_address`. - #[cfg(target_os = "linux")] - MREMAP_FIXED; - /// Permits to use the old and new address as hints to relocate the mapping. - #[cfg(target_os = "netbsd")] - MAP_FIXED; - /// Allows to duplicate the mapping to be able to apply different flags on the copy. - #[cfg(target_os = "netbsd")] - MAP_REMAPDUP; - } -} - -libc_enum!{ - /// Usage information for a range of memory to allow for performance optimizations by the kernel. - /// - /// Used by [`madvise`](./fn.madvise.html). - #[repr(i32)] - #[non_exhaustive] - pub enum MmapAdvise { - /// No further special treatment. This is the default. - MADV_NORMAL, - /// Expect random page references. - MADV_RANDOM, - /// Expect sequential page references. - MADV_SEQUENTIAL, - /// Expect access in the near future. - MADV_WILLNEED, - /// Do not expect access in the near future. - MADV_DONTNEED, - /// Free up a given range of pages and its associated backing store. - #[cfg(any(target_os = "android", target_os = "linux"))] - MADV_REMOVE, - /// Do not make pages in this range available to the child after a `fork(2)`. - #[cfg(any(target_os = "android", target_os = "linux"))] - MADV_DONTFORK, - /// Undo the effect of `MADV_DONTFORK`. - #[cfg(any(target_os = "android", target_os = "linux"))] - MADV_DOFORK, - /// Poison the given pages. - /// - /// Subsequent references to those pages are treated like hardware memory corruption. - #[cfg(any(target_os = "android", target_os = "linux"))] - MADV_HWPOISON, - /// Enable Kernel Samepage Merging (KSM) for the given pages. - #[cfg(any(target_os = "android", target_os = "linux"))] - MADV_MERGEABLE, - /// Undo the effect of `MADV_MERGEABLE` - #[cfg(any(target_os = "android", target_os = "linux"))] - MADV_UNMERGEABLE, - /// Preserve the memory of each page but offline the original page. - #[cfg(any(target_os = "android", - all(target_os = "linux", any( - target_arch = "aarch64", - target_arch = "arm", - target_arch = "powerpc", - target_arch = "powerpc64", - target_arch = "s390x", - target_arch = "x86", - target_arch = "x86_64", - target_arch = "sparc64"))))] - MADV_SOFT_OFFLINE, - /// Enable Transparent Huge Pages (THP) for pages in the given range. - #[cfg(any(target_os = "android", target_os = "linux"))] - MADV_HUGEPAGE, - /// Undo the effect of `MADV_HUGEPAGE`. - #[cfg(any(target_os = "android", target_os = "linux"))] - MADV_NOHUGEPAGE, - /// Exclude the given range from a core dump. - #[cfg(any(target_os = "android", target_os = "linux"))] - MADV_DONTDUMP, - /// Undo the effect of an earlier `MADV_DONTDUMP`. - #[cfg(any(target_os = "android", target_os = "linux"))] - MADV_DODUMP, - /// Specify that the application no longer needs the pages in the given range. - MADV_FREE, - /// Request that the system not flush the current range to disk unless it needs to. - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - MADV_NOSYNC, - /// Undoes the effects of `MADV_NOSYNC` for any future pages dirtied within the given range. - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - MADV_AUTOSYNC, - /// Region is not included in a core file. - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - MADV_NOCORE, - /// Include region in a core file - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - MADV_CORE, - #[cfg(any(target_os = "freebsd"))] - MADV_PROTECT, - /// Invalidate the hardware page table for the given region. - #[cfg(target_os = "dragonfly")] - MADV_INVAL, - /// Set the offset of the page directory page to `value` for the virtual page table. - #[cfg(target_os = "dragonfly")] - MADV_SETMAP, - /// Indicates that the application will not need the data in the given range. - #[cfg(any(target_os = "ios", target_os = "macos"))] - MADV_ZERO_WIRED_PAGES, - #[cfg(any(target_os = "ios", target_os = "macos"))] - MADV_FREE_REUSABLE, - #[cfg(any(target_os = "ios", target_os = "macos"))] - MADV_FREE_REUSE, - #[cfg(any(target_os = "ios", target_os = "macos"))] - MADV_CAN_REUSE, - } -} - -libc_bitflags!{ - /// Configuration flags for `msync`. - pub struct MsFlags: c_int { - /// Schedule an update but return immediately. - MS_ASYNC; - /// Invalidate all cached data. - MS_INVALIDATE; - /// Invalidate pages, but leave them mapped. - #[cfg(any(target_os = "ios", target_os = "macos"))] - MS_KILLPAGES; - /// Deactivate pages, but leave them mapped. - #[cfg(any(target_os = "ios", target_os = "macos"))] - MS_DEACTIVATE; - /// Perform an update and wait for it to complete. - MS_SYNC; - } -} - -libc_bitflags!{ - /// Flags for `mlockall`. - pub struct MlockAllFlags: c_int { - /// Lock pages that are currently mapped into the address space of the process. - MCL_CURRENT; - /// Lock pages which will become mapped into the address space of the process in the future. - MCL_FUTURE; - } -} - -/// Locks all memory pages that contain part of the address range with `length` -/// bytes starting at `addr`. -/// -/// Locked pages never move to the swap area. -/// -/// # Safety -/// -/// `addr` must meet all the requirements described in the `mlock(2)` man page. -pub unsafe fn mlock(addr: *const c_void, length: size_t) -> Result<()> { - Errno::result(libc::mlock(addr, length)).map(drop) -} - -/// Unlocks all memory pages that contain part of the address range with -/// `length` bytes starting at `addr`. -/// -/// # Safety -/// -/// `addr` must meet all the requirements described in the `munlock(2)` man -/// page. -pub unsafe fn munlock(addr: *const c_void, length: size_t) -> Result<()> { - Errno::result(libc::munlock(addr, length)).map(drop) -} - -/// Locks all memory pages mapped into this process' address space. -/// -/// Locked pages never move to the swap area. -/// -/// # Safety -/// -/// `addr` must meet all the requirements described in the `mlockall(2)` man -/// page. -pub fn mlockall(flags: MlockAllFlags) -> Result<()> { - unsafe { Errno::result(libc::mlockall(flags.bits())) }.map(drop) -} - -/// Unlocks all memory pages mapped into this process' address space. -pub fn munlockall() -> Result<()> { - unsafe { Errno::result(libc::munlockall()) }.map(drop) -} - -/// allocate memory, or map files or devices into memory -/// -/// # Safety -/// -/// See the `mmap(2)` man page for detailed requirements. -pub unsafe fn mmap(addr: *mut c_void, length: size_t, prot: ProtFlags, flags: MapFlags, fd: RawFd, offset: off_t) -> Result<*mut c_void> { - let ret = libc::mmap(addr, length, prot.bits(), flags.bits(), fd, offset); - - if ret == libc::MAP_FAILED { - Err(Errno::last()) - } else { - Ok(ret) - } -} - -/// Expands (or shrinks) an existing memory mapping, potentially moving it at -/// the same time. -/// -/// # Safety -/// -/// See the `mremap(2)` [man page](https://man7.org/linux/man-pages/man2/mremap.2.html) for -/// detailed requirements. -#[cfg(any(target_os = "linux", target_os = "netbsd"))] -pub unsafe fn mremap( - addr: *mut c_void, - old_size: size_t, - new_size: size_t, - flags: MRemapFlags, - new_address: Option<* mut c_void>, -) -> Result<*mut c_void> { - #[cfg(target_os = "linux")] - let ret = libc::mremap(addr, old_size, new_size, flags.bits(), new_address.unwrap_or(std::ptr::null_mut())); - #[cfg(target_os = "netbsd")] - let ret = libc::mremap( - addr, - old_size, - new_address.unwrap_or(std::ptr::null_mut()), - new_size, - flags.bits(), - ); - - if ret == libc::MAP_FAILED { - Err(Errno::last()) - } else { - Ok(ret) - } -} - -/// remove a mapping -/// -/// # Safety -/// -/// `addr` must meet all the requirements described in the `munmap(2)` man -/// page. -pub unsafe fn munmap(addr: *mut c_void, len: size_t) -> Result<()> { - Errno::result(libc::munmap(addr, len)).map(drop) -} - -/// give advice about use of memory -/// -/// # Safety -/// -/// See the `madvise(2)` man page. Take special care when using -/// `MmapAdvise::MADV_FREE`. -pub unsafe fn madvise(addr: *mut c_void, length: size_t, advise: MmapAdvise) -> Result<()> { - Errno::result(libc::madvise(addr, length, advise as i32)).map(drop) -} - -/// Set protection of memory mapping. -/// -/// See [`mprotect(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html) for -/// details. -/// -/// # Safety -/// -/// Calls to `mprotect` are inherently unsafe, as changes to memory protections can lead to -/// SIGSEGVs. -/// -/// ``` -/// # use nix::libc::size_t; -/// # use nix::sys::mman::{mmap, mprotect, MapFlags, ProtFlags}; -/// # use std::ptr; -/// const ONE_K: size_t = 1024; -/// let mut slice: &mut [u8] = unsafe { -/// let mem = mmap(ptr::null_mut(), ONE_K, ProtFlags::PROT_NONE, -/// MapFlags::MAP_ANON | MapFlags::MAP_PRIVATE, -1, 0).unwrap(); -/// mprotect(mem, ONE_K, ProtFlags::PROT_READ | ProtFlags::PROT_WRITE).unwrap(); -/// std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K) -/// }; -/// assert_eq!(slice[0], 0x00); -/// slice[0] = 0xFF; -/// assert_eq!(slice[0], 0xFF); -/// ``` -pub unsafe fn mprotect(addr: *mut c_void, length: size_t, prot: ProtFlags) -> Result<()> { - Errno::result(libc::mprotect(addr, length, prot.bits())).map(drop) -} - -/// synchronize a mapped region -/// -/// # Safety -/// -/// `addr` must meet all the requirements described in the `msync(2)` man -/// page. -pub unsafe fn msync(addr: *mut c_void, length: size_t, flags: MsFlags) -> Result<()> { - Errno::result(libc::msync(addr, length, flags.bits())).map(drop) -} - -#[cfg(not(target_os = "android"))] -pub fn shm_open(name: &P, flag: OFlag, mode: Mode) -> Result { - let ret = name.with_nix_path(|cstr| { - #[cfg(any(target_os = "macos", target_os = "ios"))] - unsafe { - libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::c_uint) - } - #[cfg(not(any(target_os = "macos", target_os = "ios")))] - unsafe { - libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::mode_t) - } - })?; - - Errno::result(ret) -} - -#[cfg(not(target_os = "android"))] -pub fn shm_unlink(name: &P) -> Result<()> { - let ret = name.with_nix_path(|cstr| { - unsafe { libc::shm_unlink(cstr.as_ptr()) } - })?; - - Errno::result(ret).map(drop) -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/mod.rs b/vendor/nix-v0.23.1-patched/src/sys/mod.rs deleted file mode 100644 index a87de55b3..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/mod.rs +++ /dev/null @@ -1,131 +0,0 @@ -//! Mostly platform-specific functionality -#[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd"))] -pub mod aio; - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[allow(missing_docs)] -pub mod epoll; - -#[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] -#[allow(missing_docs)] -pub mod event; - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[allow(missing_docs)] -pub mod eventfd; - -#[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "redox", - target_os = "macos", - target_os = "netbsd", - target_os = "illumos", - target_os = "openbsd"))] -#[macro_use] -pub mod ioctl; - -#[cfg(target_os = "linux")] -#[allow(missing_docs)] -pub mod memfd; - -#[cfg(not(target_os = "redox"))] -#[allow(missing_docs)] -pub mod mman; - -#[cfg(target_os = "linux")] -#[allow(missing_docs)] -pub mod personality; - -pub mod pthread; - -#[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] -#[allow(missing_docs)] -pub mod ptrace; - -#[cfg(target_os = "linux")] -pub mod quota; - -#[cfg(any(target_os = "linux"))] -#[allow(missing_docs)] -pub mod reboot; - -#[cfg(not(any(target_os = "redox", target_os = "fuchsia", target_os = "illumos")))] -pub mod resource; - -#[cfg(not(target_os = "redox"))] -pub mod select; - -#[cfg(any(target_os = "android", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] -pub mod sendfile; - -pub mod signal; - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[allow(missing_docs)] -pub mod signalfd; - -#[cfg(not(target_os = "redox"))] -#[allow(missing_docs)] -pub mod socket; - -#[allow(missing_docs)] -pub mod stat; - -#[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "openbsd" -))] -pub mod statfs; - -pub mod statvfs; - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[allow(missing_docs)] -pub mod sysinfo; - -#[allow(missing_docs)] -pub mod termios; - -#[allow(missing_docs)] -pub mod time; - -pub mod uio; - -pub mod utsname; - -pub mod wait; - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[allow(missing_docs)] -pub mod inotify; - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[allow(missing_docs)] -pub mod timerfd; diff --git a/vendor/nix-v0.23.1-patched/src/sys/personality.rs b/vendor/nix-v0.23.1-patched/src/sys/personality.rs deleted file mode 100644 index b15956c46..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/personality.rs +++ /dev/null @@ -1,70 +0,0 @@ -use crate::Result; -use crate::errno::Errno; - -use libc::{self, c_int, c_ulong}; - -libc_bitflags! { - /// Flags used and returned by [`get()`](fn.get.html) and - /// [`set()`](fn.set.html). - pub struct Persona: c_int { - ADDR_COMPAT_LAYOUT; - ADDR_NO_RANDOMIZE; - ADDR_LIMIT_32BIT; - ADDR_LIMIT_3GB; - #[cfg(not(target_env = "musl"))] - FDPIC_FUNCPTRS; - MMAP_PAGE_ZERO; - READ_IMPLIES_EXEC; - SHORT_INODE; - STICKY_TIMEOUTS; - #[cfg(not(target_env = "musl"))] - UNAME26; - WHOLE_SECONDS; - } -} - -/// Retrieve the current process personality. -/// -/// Returns a Result containing a Persona instance. -/// -/// Example: -/// -/// ``` -/// # use nix::sys::personality::{self, Persona}; -/// let pers = personality::get().unwrap(); -/// assert!(!pers.contains(Persona::WHOLE_SECONDS)); -/// ``` -pub fn get() -> Result { - let res = unsafe { - libc::personality(0xFFFFFFFF) - }; - - Errno::result(res).map(Persona::from_bits_truncate) -} - -/// Set the current process personality. -/// -/// Returns a Result containing the *previous* personality for the -/// process, as a Persona. -/// -/// For more information, see [personality(2)](https://man7.org/linux/man-pages/man2/personality.2.html) -/// -/// **NOTE**: This call **replaces** the current personality entirely. -/// To **update** the personality, first call `get()` and then `set()` -/// with the modified persona. -/// -/// Example: -/// -/// ``` -/// # use nix::sys::personality::{self, Persona}; -/// let mut pers = personality::get().unwrap(); -/// assert!(!pers.contains(Persona::ADDR_NO_RANDOMIZE)); -/// personality::set(pers | Persona::ADDR_NO_RANDOMIZE); -/// ``` -pub fn set(persona: Persona) -> Result { - let res = unsafe { - libc::personality(persona.bits() as c_ulong) - }; - - Errno::result(res).map(Persona::from_bits_truncate) -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/pthread.rs b/vendor/nix-v0.23.1-patched/src/sys/pthread.rs deleted file mode 100644 index d42e45d13..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/pthread.rs +++ /dev/null @@ -1,38 +0,0 @@ -//! Low level threading primitives - -#[cfg(not(target_os = "redox"))] -use crate::errno::Errno; -#[cfg(not(target_os = "redox"))] -use crate::Result; -#[cfg(not(target_os = "redox"))] -use crate::sys::signal::Signal; -use libc::{self, pthread_t}; - -/// Identifies an individual thread. -pub type Pthread = pthread_t; - -/// Obtain ID of the calling thread (see -/// [`pthread_self(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_self.html) -/// -/// The thread ID returned by `pthread_self()` is not the same thing as -/// the kernel thread ID returned by a call to `gettid(2)`. -#[inline] -pub fn pthread_self() -> Pthread { - unsafe { libc::pthread_self() } -} - -/// Send a signal to a thread (see [`pthread_kill(3)`]). -/// -/// If `signal` is `None`, `pthread_kill` will only preform error checking and -/// won't send any signal. -/// -/// [`pthread_kill(3)`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html -#[cfg(not(target_os = "redox"))] -pub fn pthread_kill>>(thread: Pthread, signal: T) -> Result<()> { - let sig = match signal.into() { - Some(s) => s as libc::c_int, - None => 0, - }; - let res = unsafe { libc::pthread_kill(thread, sig) }; - Errno::result(res).map(drop) -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/ptrace/bsd.rs b/vendor/nix-v0.23.1-patched/src/sys/ptrace/bsd.rs deleted file mode 100644 index a62881ef3..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/ptrace/bsd.rs +++ /dev/null @@ -1,176 +0,0 @@ -use cfg_if::cfg_if; -use crate::errno::Errno; -use libc::{self, c_int}; -use std::ptr; -use crate::sys::signal::Signal; -use crate::unistd::Pid; -use crate::Result; - -pub type RequestType = c_int; - -cfg_if! { - if #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "openbsd"))] { - #[doc(hidden)] - pub type AddressType = *mut ::libc::c_char; - } else { - #[doc(hidden)] - pub type AddressType = *mut ::libc::c_void; - } -} - -libc_enum! { - #[repr(i32)] - /// Ptrace Request enum defining the action to be taken. - #[non_exhaustive] - pub enum Request { - PT_TRACE_ME, - PT_READ_I, - PT_READ_D, - #[cfg(target_os = "macos")] - PT_READ_U, - PT_WRITE_I, - PT_WRITE_D, - #[cfg(target_os = "macos")] - PT_WRITE_U, - PT_CONTINUE, - PT_KILL, - #[cfg(any(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos"), - all(target_os = "openbsd", target_arch = "x86_64"), - all(target_os = "netbsd", any(target_arch = "x86_64", - target_arch = "powerpc"))))] - PT_STEP, - PT_ATTACH, - PT_DETACH, - #[cfg(target_os = "macos")] - PT_SIGEXC, - #[cfg(target_os = "macos")] - PT_THUPDATE, - #[cfg(target_os = "macos")] - PT_ATTACHEXC - } -} - -unsafe fn ptrace_other( - request: Request, - pid: Pid, - addr: AddressType, - data: c_int, -) -> Result { - Errno::result(libc::ptrace( - request as RequestType, - libc::pid_t::from(pid), - addr, - data, - )).map(|_| 0) -} - -/// Sets the process as traceable, as with `ptrace(PT_TRACEME, ...)` -/// -/// Indicates that this process is to be traced by its parent. -/// This is the only ptrace request to be issued by the tracee. -pub fn traceme() -> Result<()> { - unsafe { ptrace_other(Request::PT_TRACE_ME, Pid::from_raw(0), ptr::null_mut(), 0).map(drop) } -} - -/// Attach to a running process, as with `ptrace(PT_ATTACH, ...)` -/// -/// Attaches to the process specified by `pid`, making it a tracee of the calling process. -pub fn attach(pid: Pid) -> Result<()> { - unsafe { ptrace_other(Request::PT_ATTACH, pid, ptr::null_mut(), 0).map(drop) } -} - -/// Detaches the current running process, as with `ptrace(PT_DETACH, ...)` -/// -/// Detaches from the process specified by `pid` allowing it to run freely, optionally delivering a -/// signal specified by `sig`. -pub fn detach>>(pid: Pid, sig: T) -> Result<()> { - let data = match sig.into() { - Some(s) => s as c_int, - None => 0, - }; - unsafe { - ptrace_other(Request::PT_DETACH, pid, ptr::null_mut(), data).map(drop) - } -} - -/// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)` -/// -/// Continues the execution of the process with PID `pid`, optionally -/// delivering a signal specified by `sig`. -pub fn cont>>(pid: Pid, sig: T) -> Result<()> { - let data = match sig.into() { - Some(s) => s as c_int, - None => 0, - }; - unsafe { - // Ignore the useless return value - ptrace_other(Request::PT_CONTINUE, pid, 1 as AddressType, data).map(drop) - } -} - -/// Issues a kill request as with `ptrace(PT_KILL, ...)` -/// -/// This request is equivalent to `ptrace(PT_CONTINUE, ..., SIGKILL);` -pub fn kill(pid: Pid) -> Result<()> { - unsafe { - ptrace_other(Request::PT_KILL, pid, 0 as AddressType, 0).map(drop) - } -} - -/// Move the stopped tracee process forward by a single step as with -/// `ptrace(PT_STEP, ...)` -/// -/// Advances the execution of the process with PID `pid` by a single step optionally delivering a -/// signal specified by `sig`. -/// -/// # Example -/// ```rust -/// use nix::sys::ptrace::step; -/// use nix::unistd::Pid; -/// use nix::sys::signal::Signal; -/// use nix::sys::wait::*; -/// // If a process changes state to the stopped state because of a SIGUSR1 -/// // signal, this will step the process forward and forward the user -/// // signal to the stopped process -/// match waitpid(Pid::from_raw(-1), None) { -/// Ok(WaitStatus::Stopped(pid, Signal::SIGUSR1)) => { -/// let _ = step(pid, Signal::SIGUSR1); -/// } -/// _ => {}, -/// } -/// ``` -#[cfg( - any( - any(target_os = "dragonfly", target_os = "freebsd", target_os = "macos"), - all(target_os = "openbsd", target_arch = "x86_64"), - all(target_os = "netbsd", - any(target_arch = "x86_64", target_arch = "powerpc") - ) - ) -)] -pub fn step>>(pid: Pid, sig: T) -> Result<()> { - let data = match sig.into() { - Some(s) => s as c_int, - None => 0, - }; - unsafe { ptrace_other(Request::PT_STEP, pid, ptr::null_mut(), data).map(drop) } -} - -/// Reads a word from a processes memory at the given address -pub fn read(pid: Pid, addr: AddressType) -> Result { - unsafe { - // Traditionally there was a difference between reading data or - // instruction memory but not in modern systems. - ptrace_other(Request::PT_READ_D, pid, addr, 0) - } -} - -/// Writes a word into the processes memory at the given address -pub fn write(pid: Pid, addr: AddressType, data: c_int) -> Result<()> { - unsafe { ptrace_other(Request::PT_WRITE_D, pid, addr, data).map(drop) } -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/ptrace/linux.rs b/vendor/nix-v0.23.1-patched/src/sys/ptrace/linux.rs deleted file mode 100644 index 37236790b..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/ptrace/linux.rs +++ /dev/null @@ -1,479 +0,0 @@ -//! For detailed description of the ptrace requests, consult `man ptrace`. - -use cfg_if::cfg_if; -use std::{mem, ptr}; -use crate::Result; -use crate::errno::Errno; -use libc::{self, c_void, c_long, siginfo_t}; -use crate::unistd::Pid; -use crate::sys::signal::Signal; - -pub type AddressType = *mut ::libc::c_void; - -#[cfg(all( - target_os = "linux", - any(all(target_arch = "x86_64", - any(target_env = "gnu", target_env = "musl")), - all(target_arch = "x86", target_env = "gnu")) -))] -use libc::user_regs_struct; - -cfg_if! { - if #[cfg(any(all(target_os = "linux", target_arch = "s390x"), - all(target_os = "linux", target_env = "gnu")))] { - #[doc(hidden)] - pub type RequestType = ::libc::c_uint; - } else { - #[doc(hidden)] - pub type RequestType = ::libc::c_int; - } -} - -libc_enum!{ - #[cfg_attr(not(any(target_env = "musl", target_os = "android")), repr(u32))] - #[cfg_attr(any(target_env = "musl", target_os = "android"), repr(i32))] - /// Ptrace Request enum defining the action to be taken. - #[non_exhaustive] - pub enum Request { - PTRACE_TRACEME, - PTRACE_PEEKTEXT, - PTRACE_PEEKDATA, - PTRACE_PEEKUSER, - PTRACE_POKETEXT, - PTRACE_POKEDATA, - PTRACE_POKEUSER, - PTRACE_CONT, - PTRACE_KILL, - PTRACE_SINGLESTEP, - #[cfg(any(all(target_os = "android", target_pointer_width = "32"), - all(target_os = "linux", any(target_env = "musl", - target_arch = "mips", - target_arch = "mips64", - target_arch = "x86_64", - target_pointer_width = "32"))))] - PTRACE_GETREGS, - #[cfg(any(all(target_os = "android", target_pointer_width = "32"), - all(target_os = "linux", any(target_env = "musl", - target_arch = "mips", - target_arch = "mips64", - target_arch = "x86_64", - target_pointer_width = "32"))))] - PTRACE_SETREGS, - #[cfg(any(all(target_os = "android", target_pointer_width = "32"), - all(target_os = "linux", any(target_env = "musl", - target_arch = "mips", - target_arch = "mips64", - target_arch = "x86_64", - target_pointer_width = "32"))))] - PTRACE_GETFPREGS, - #[cfg(any(all(target_os = "android", target_pointer_width = "32"), - all(target_os = "linux", any(target_env = "musl", - target_arch = "mips", - target_arch = "mips64", - target_arch = "x86_64", - target_pointer_width = "32"))))] - PTRACE_SETFPREGS, - PTRACE_ATTACH, - PTRACE_DETACH, - #[cfg(all(target_os = "linux", any(target_env = "musl", - target_arch = "mips", - target_arch = "mips64", - target_arch = "x86", - target_arch = "x86_64")))] - PTRACE_GETFPXREGS, - #[cfg(all(target_os = "linux", any(target_env = "musl", - target_arch = "mips", - target_arch = "mips64", - target_arch = "x86", - target_arch = "x86_64")))] - PTRACE_SETFPXREGS, - PTRACE_SYSCALL, - PTRACE_SETOPTIONS, - PTRACE_GETEVENTMSG, - PTRACE_GETSIGINFO, - PTRACE_SETSIGINFO, - #[cfg(all(target_os = "linux", not(any(target_arch = "mips", - target_arch = "mips64"))))] - PTRACE_GETREGSET, - #[cfg(all(target_os = "linux", not(any(target_arch = "mips", - target_arch = "mips64"))))] - PTRACE_SETREGSET, - #[cfg(target_os = "linux")] - PTRACE_SEIZE, - #[cfg(target_os = "linux")] - PTRACE_INTERRUPT, - #[cfg(all(target_os = "linux", not(any(target_arch = "mips", - target_arch = "mips64"))))] - PTRACE_LISTEN, - #[cfg(all(target_os = "linux", not(any(target_arch = "mips", - target_arch = "mips64"))))] - PTRACE_PEEKSIGINFO, - #[cfg(all(target_os = "linux", target_env = "gnu", - any(target_arch = "x86", target_arch = "x86_64")))] - PTRACE_SYSEMU, - #[cfg(all(target_os = "linux", target_env = "gnu", - any(target_arch = "x86", target_arch = "x86_64")))] - PTRACE_SYSEMU_SINGLESTEP, - } -} - -libc_enum!{ - #[repr(i32)] - /// Using the ptrace options the tracer can configure the tracee to stop - /// at certain events. This enum is used to define those events as defined - /// in `man ptrace`. - #[non_exhaustive] - pub enum Event { - /// Event that stops before a return from fork or clone. - PTRACE_EVENT_FORK, - /// Event that stops before a return from vfork or clone. - PTRACE_EVENT_VFORK, - /// Event that stops before a return from clone. - PTRACE_EVENT_CLONE, - /// Event that stops before a return from execve. - PTRACE_EVENT_EXEC, - /// Event for a return from vfork. - PTRACE_EVENT_VFORK_DONE, - /// Event for a stop before an exit. Unlike the waitpid Exit status program. - /// registers can still be examined - PTRACE_EVENT_EXIT, - /// Stop triggered by a seccomp rule on a tracee. - PTRACE_EVENT_SECCOMP, - /// Stop triggered by the `INTERRUPT` syscall, or a group stop, - /// or when a new child is attached. - PTRACE_EVENT_STOP, - } -} - -libc_bitflags! { - /// Ptrace options used in conjunction with the PTRACE_SETOPTIONS request. - /// See `man ptrace` for more details. - pub struct Options: libc::c_int { - /// When delivering system call traps set a bit to allow tracer to - /// distinguish between normal stops or syscall stops. May not work on - /// all systems. - PTRACE_O_TRACESYSGOOD; - /// Stop tracee at next fork and start tracing the forked process. - PTRACE_O_TRACEFORK; - /// Stop tracee at next vfork call and trace the vforked process. - PTRACE_O_TRACEVFORK; - /// Stop tracee at next clone call and trace the cloned process. - PTRACE_O_TRACECLONE; - /// Stop tracee at next execve call. - PTRACE_O_TRACEEXEC; - /// Stop tracee at vfork completion. - PTRACE_O_TRACEVFORKDONE; - /// Stop tracee at next exit call. Stops before exit commences allowing - /// tracer to see location of exit and register states. - PTRACE_O_TRACEEXIT; - /// Stop tracee when a SECCOMP_RET_TRACE rule is triggered. See `man seccomp` for more - /// details. - PTRACE_O_TRACESECCOMP; - /// Send a SIGKILL to the tracee if the tracer exits. This is useful - /// for ptrace jailers to prevent tracees from escaping their control. - #[cfg(any(target_os = "android", target_os = "linux"))] - PTRACE_O_EXITKILL; - } -} - -fn ptrace_peek(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result { - let ret = unsafe { - Errno::clear(); - libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data) - }; - match Errno::result(ret) { - Ok(..) | Err(Errno::UnknownErrno) => Ok(ret), - err @ Err(..) => err, - } -} - -/// Get user registers, as with `ptrace(PTRACE_GETREGS, ...)` -#[cfg(all( - target_os = "linux", - any(all(target_arch = "x86_64", - any(target_env = "gnu", target_env = "musl")), - all(target_arch = "x86", target_env = "gnu")) -))] -pub fn getregs(pid: Pid) -> Result { - ptrace_get_data::(Request::PTRACE_GETREGS, pid) -} - -/// Set user registers, as with `ptrace(PTRACE_SETREGS, ...)` -#[cfg(all( - target_os = "linux", - any(all(target_arch = "x86_64", - any(target_env = "gnu", target_env = "musl")), - all(target_arch = "x86", target_env = "gnu")) -))] -pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> { - let res = unsafe { - libc::ptrace(Request::PTRACE_SETREGS as RequestType, - libc::pid_t::from(pid), - ptr::null_mut::(), - ®s as *const _ as *const c_void) - }; - Errno::result(res).map(drop) -} - -/// Function for ptrace requests that return values from the data field. -/// Some ptrace get requests populate structs or larger elements than `c_long` -/// and therefore use the data field to return values. This function handles these -/// requests. -fn ptrace_get_data(request: Request, pid: Pid) -> Result { - let mut data = mem::MaybeUninit::uninit(); - let res = unsafe { - libc::ptrace(request as RequestType, - libc::pid_t::from(pid), - ptr::null_mut::(), - data.as_mut_ptr() as *const _ as *const c_void) - }; - Errno::result(res)?; - Ok(unsafe{ data.assume_init() }) -} - -unsafe fn ptrace_other(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result { - Errno::result(libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)).map(|_| 0) -} - -/// Set options, as with `ptrace(PTRACE_SETOPTIONS,...)`. -pub fn setoptions(pid: Pid, options: Options) -> Result<()> { - let res = unsafe { - libc::ptrace(Request::PTRACE_SETOPTIONS as RequestType, - libc::pid_t::from(pid), - ptr::null_mut::(), - options.bits() as *mut c_void) - }; - Errno::result(res).map(drop) -} - -/// Gets a ptrace event as described by `ptrace(PTRACE_GETEVENTMSG,...)` -pub fn getevent(pid: Pid) -> Result { - ptrace_get_data::(Request::PTRACE_GETEVENTMSG, pid) -} - -/// Get siginfo as with `ptrace(PTRACE_GETSIGINFO,...)` -pub fn getsiginfo(pid: Pid) -> Result { - ptrace_get_data::(Request::PTRACE_GETSIGINFO, pid) -} - -/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO,...)` -pub fn setsiginfo(pid: Pid, sig: &siginfo_t) -> Result<()> { - let ret = unsafe{ - Errno::clear(); - libc::ptrace(Request::PTRACE_SETSIGINFO as RequestType, - libc::pid_t::from(pid), - ptr::null_mut::(), - sig as *const _ as *const c_void) - }; - match Errno::result(ret) { - Ok(_) => Ok(()), - Err(e) => Err(e), - } -} - -/// Sets the process as traceable, as with `ptrace(PTRACE_TRACEME, ...)` -/// -/// Indicates that this process is to be traced by its parent. -/// This is the only ptrace request to be issued by the tracee. -pub fn traceme() -> Result<()> { - unsafe { - ptrace_other( - Request::PTRACE_TRACEME, - Pid::from_raw(0), - ptr::null_mut(), - ptr::null_mut(), - ).map(drop) // ignore the useless return value - } -} - -/// Continue execution until the next syscall, as with `ptrace(PTRACE_SYSCALL, ...)` -/// -/// Arranges for the tracee to be stopped at the next entry to or exit from a system call, -/// optionally delivering a signal specified by `sig`. -pub fn syscall>>(pid: Pid, sig: T) -> Result<()> { - let data = match sig.into() { - Some(s) => s as i32 as *mut c_void, - None => ptr::null_mut(), - }; - unsafe { - ptrace_other( - Request::PTRACE_SYSCALL, - pid, - ptr::null_mut(), - data, - ).map(drop) // ignore the useless return value - } -} - -/// Continue execution until the next syscall, as with `ptrace(PTRACE_SYSEMU, ...)` -/// -/// In contrast to the `syscall` function, the syscall stopped at will not be executed. -/// Thus the the tracee will only be stopped once per syscall, -/// optionally delivering a signal specified by `sig`. -#[cfg(all(target_os = "linux", target_env = "gnu", any(target_arch = "x86", target_arch = "x86_64")))] -pub fn sysemu>>(pid: Pid, sig: T) -> Result<()> { - let data = match sig.into() { - Some(s) => s as i32 as *mut c_void, - None => ptr::null_mut(), - }; - unsafe { - ptrace_other(Request::PTRACE_SYSEMU, pid, ptr::null_mut(), data).map(drop) - // ignore the useless return value - } -} - -/// Attach to a running process, as with `ptrace(PTRACE_ATTACH, ...)` -/// -/// Attaches to the process specified by `pid`, making it a tracee of the calling process. -pub fn attach(pid: Pid) -> Result<()> { - unsafe { - ptrace_other( - Request::PTRACE_ATTACH, - pid, - ptr::null_mut(), - ptr::null_mut(), - ).map(drop) // ignore the useless return value - } -} - -/// Attach to a running process, as with `ptrace(PTRACE_SEIZE, ...)` -/// -/// Attaches to the process specified in pid, making it a tracee of the calling process. -#[cfg(target_os = "linux")] -pub fn seize(pid: Pid, options: Options) -> Result<()> { - unsafe { - ptrace_other( - Request::PTRACE_SEIZE, - pid, - ptr::null_mut(), - options.bits() as *mut c_void, - ).map(drop) // ignore the useless return value - } -} - -/// Detaches the current running process, as with `ptrace(PTRACE_DETACH, ...)` -/// -/// Detaches from the process specified by `pid` allowing it to run freely, optionally delivering a -/// signal specified by `sig`. -pub fn detach>>(pid: Pid, sig: T) -> Result<()> { - let data = match sig.into() { - Some(s) => s as i32 as *mut c_void, - None => ptr::null_mut(), - }; - unsafe { - ptrace_other( - Request::PTRACE_DETACH, - pid, - ptr::null_mut(), - data - ).map(drop) - } -} - -/// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)` -/// -/// Continues the execution of the process with PID `pid`, optionally -/// delivering a signal specified by `sig`. -pub fn cont>>(pid: Pid, sig: T) -> Result<()> { - let data = match sig.into() { - Some(s) => s as i32 as *mut c_void, - None => ptr::null_mut(), - }; - unsafe { - ptrace_other(Request::PTRACE_CONT, pid, ptr::null_mut(), data).map(drop) // ignore the useless return value - } -} - -/// Stop a tracee, as with `ptrace(PTRACE_INTERRUPT, ...)` -/// -/// This request is equivalent to `ptrace(PTRACE_INTERRUPT, ...)` -#[cfg(target_os = "linux")] -pub fn interrupt(pid: Pid) -> Result<()> { - unsafe { - ptrace_other(Request::PTRACE_INTERRUPT, pid, ptr::null_mut(), ptr::null_mut()).map(drop) - } -} - -/// Issues a kill request as with `ptrace(PTRACE_KILL, ...)` -/// -/// This request is equivalent to `ptrace(PTRACE_CONT, ..., SIGKILL);` -pub fn kill(pid: Pid) -> Result<()> { - unsafe { - ptrace_other(Request::PTRACE_KILL, pid, ptr::null_mut(), ptr::null_mut()).map(drop) - } -} - -/// Move the stopped tracee process forward by a single step as with -/// `ptrace(PTRACE_SINGLESTEP, ...)` -/// -/// Advances the execution of the process with PID `pid` by a single step optionally delivering a -/// signal specified by `sig`. -/// -/// # Example -/// ```rust -/// use nix::sys::ptrace::step; -/// use nix::unistd::Pid; -/// use nix::sys::signal::Signal; -/// use nix::sys::wait::*; -/// -/// // If a process changes state to the stopped state because of a SIGUSR1 -/// // signal, this will step the process forward and forward the user -/// // signal to the stopped process -/// match waitpid(Pid::from_raw(-1), None) { -/// Ok(WaitStatus::Stopped(pid, Signal::SIGUSR1)) => { -/// let _ = step(pid, Signal::SIGUSR1); -/// } -/// _ => {}, -/// } -/// ``` -pub fn step>>(pid: Pid, sig: T) -> Result<()> { - let data = match sig.into() { - Some(s) => s as i32 as *mut c_void, - None => ptr::null_mut(), - }; - unsafe { - ptrace_other(Request::PTRACE_SINGLESTEP, pid, ptr::null_mut(), data).map(drop) - } -} - -/// Move the stopped tracee process forward by a single step or stop at the next syscall -/// as with `ptrace(PTRACE_SYSEMU_SINGLESTEP, ...)` -/// -/// Advances the execution by a single step or until the next syscall. -/// In case the tracee is stopped at a syscall, the syscall will not be executed. -/// Optionally, the signal specified by `sig` is delivered to the tracee upon continuation. -#[cfg(all(target_os = "linux", target_env = "gnu", any(target_arch = "x86", target_arch = "x86_64")))] -pub fn sysemu_step>>(pid: Pid, sig: T) -> Result<()> { - let data = match sig.into() { - Some(s) => s as i32 as *mut c_void, - None => ptr::null_mut(), - }; - unsafe { - ptrace_other( - Request::PTRACE_SYSEMU_SINGLESTEP, - pid, - ptr::null_mut(), - data, - ) - .map(drop) // ignore the useless return value - } -} - -/// Reads a word from a processes memory at the given address -pub fn read(pid: Pid, addr: AddressType) -> Result { - ptrace_peek(Request::PTRACE_PEEKDATA, pid, addr, ptr::null_mut()) -} - -/// Writes a word into the processes memory at the given address -/// -/// # Safety -/// -/// The `data` argument is passed directly to `ptrace(2)`. Read that man page -/// for guidance. -pub unsafe fn write( - pid: Pid, - addr: AddressType, - data: *mut c_void) -> Result<()> -{ - ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data).map(drop) -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/ptrace/mod.rs b/vendor/nix-v0.23.1-patched/src/sys/ptrace/mod.rs deleted file mode 100644 index 782c30409..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/ptrace/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -///! Provides helpers for making ptrace system calls - -#[cfg(any(target_os = "android", target_os = "linux"))] -mod linux; - -#[cfg(any(target_os = "android", target_os = "linux"))] -pub use self::linux::*; - -#[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] -mod bsd; - -#[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd" - ))] -pub use self::bsd::*; diff --git a/vendor/nix-v0.23.1-patched/src/sys/quota.rs b/vendor/nix-v0.23.1-patched/src/sys/quota.rs deleted file mode 100644 index 6e34e38d2..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/quota.rs +++ /dev/null @@ -1,277 +0,0 @@ -//! Set and configure disk quotas for users, groups, or projects. -//! -//! # Examples -//! -//! Enabling and setting a quota: -//! -//! ```rust,no_run -//! # use nix::sys::quota::{Dqblk, quotactl_on, quotactl_set, QuotaFmt, QuotaType, QuotaValidFlags}; -//! quotactl_on(QuotaType::USRQUOTA, "/dev/sda1", QuotaFmt::QFMT_VFS_V1, "aquota.user"); -//! let mut dqblk: Dqblk = Default::default(); -//! dqblk.set_blocks_hard_limit(10000); -//! dqblk.set_blocks_soft_limit(8000); -//! quotactl_set(QuotaType::USRQUOTA, "/dev/sda1", 50, &dqblk, QuotaValidFlags::QIF_BLIMITS); -//! ``` -use std::default::Default; -use std::{mem, ptr}; -use libc::{self, c_int, c_char}; -use crate::{Result, NixPath}; -use crate::errno::Errno; - -struct QuotaCmd(QuotaSubCmd, QuotaType); - -impl QuotaCmd { - #[allow(unused_unsafe)] - fn as_int(&self) -> c_int { - unsafe { libc::QCMD(self.0 as i32, self.1 as i32) } - } -} - -// linux quota version >= 2 -libc_enum!{ - #[repr(i32)] - enum QuotaSubCmd { - Q_SYNC, - Q_QUOTAON, - Q_QUOTAOFF, - Q_GETQUOTA, - Q_SETQUOTA, - } -} - -libc_enum!{ - /// The scope of the quota. - #[repr(i32)] - #[non_exhaustive] - pub enum QuotaType { - /// Specify a user quota - USRQUOTA, - /// Specify a group quota - GRPQUOTA, - } -} - -libc_enum!{ - /// The type of quota format to use. - #[repr(i32)] - #[non_exhaustive] - pub enum QuotaFmt { - /// Use the original quota format. - QFMT_VFS_OLD, - /// Use the standard VFS v0 quota format. - /// - /// Handles 32-bit UIDs/GIDs and quota limits up to 232 bytes/232 inodes. - QFMT_VFS_V0, - /// Use the VFS v1 quota format. - /// - /// Handles 32-bit UIDs/GIDs and quota limits of 264 bytes/264 inodes. - QFMT_VFS_V1, - } -} - -libc_bitflags!( - /// Indicates the quota fields that are valid to read from. - #[derive(Default)] - pub struct QuotaValidFlags: u32 { - /// The block hard & soft limit fields. - QIF_BLIMITS; - /// The current space field. - QIF_SPACE; - /// The inode hard & soft limit fields. - QIF_ILIMITS; - /// The current inodes field. - QIF_INODES; - /// The disk use time limit field. - QIF_BTIME; - /// The file quote time limit field. - QIF_ITIME; - /// All block & inode limits. - QIF_LIMITS; - /// The space & inodes usage fields. - QIF_USAGE; - /// The time limit fields. - QIF_TIMES; - /// All fields. - QIF_ALL; - } -); - -/// Wrapper type for `if_dqblk` -#[repr(transparent)] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct Dqblk(libc::dqblk); - -impl Default for Dqblk { - fn default() -> Dqblk { - Dqblk(libc::dqblk { - dqb_bhardlimit: 0, - dqb_bsoftlimit: 0, - dqb_curspace: 0, - dqb_ihardlimit: 0, - dqb_isoftlimit: 0, - dqb_curinodes: 0, - dqb_btime: 0, - dqb_itime: 0, - dqb_valid: 0, - }) - } -} - -impl Dqblk { - /// The absolute limit on disk quota blocks allocated. - pub fn blocks_hard_limit(&self) -> Option { - let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid); - if valid_fields.contains(QuotaValidFlags::QIF_BLIMITS) { - Some(self.0.dqb_bhardlimit) - } else { - None - } - } - - /// Set the absolute limit on disk quota blocks allocated. - pub fn set_blocks_hard_limit(&mut self, limit: u64) { - self.0.dqb_bhardlimit = limit; - } - - /// Preferred limit on disk quota blocks - pub fn blocks_soft_limit(&self) -> Option { - let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid); - if valid_fields.contains(QuotaValidFlags::QIF_BLIMITS) { - Some(self.0.dqb_bsoftlimit) - } else { - None - } - } - - /// Set the preferred limit on disk quota blocks allocated. - pub fn set_blocks_soft_limit(&mut self, limit: u64) { - self.0.dqb_bsoftlimit = limit; - } - - /// Current occupied space (bytes). - pub fn occupied_space(&self) -> Option { - let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid); - if valid_fields.contains(QuotaValidFlags::QIF_SPACE) { - Some(self.0.dqb_curspace) - } else { - None - } - } - - /// Maximum number of allocated inodes. - pub fn inodes_hard_limit(&self) -> Option { - let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid); - if valid_fields.contains(QuotaValidFlags::QIF_ILIMITS) { - Some(self.0.dqb_ihardlimit) - } else { - None - } - } - - /// Set the maximum number of allocated inodes. - pub fn set_inodes_hard_limit(&mut self, limit: u64) { - self.0.dqb_ihardlimit = limit; - } - - /// Preferred inode limit - pub fn inodes_soft_limit(&self) -> Option { - let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid); - if valid_fields.contains(QuotaValidFlags::QIF_ILIMITS) { - Some(self.0.dqb_isoftlimit) - } else { - None - } - } - - /// Set the preferred limit of allocated inodes. - pub fn set_inodes_soft_limit(&mut self, limit: u64) { - self.0.dqb_isoftlimit = limit; - } - - /// Current number of allocated inodes. - pub fn allocated_inodes(&self) -> Option { - let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid); - if valid_fields.contains(QuotaValidFlags::QIF_INODES) { - Some(self.0.dqb_curinodes) - } else { - None - } - } - - /// Time limit for excessive disk use. - pub fn block_time_limit(&self) -> Option { - let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid); - if valid_fields.contains(QuotaValidFlags::QIF_BTIME) { - Some(self.0.dqb_btime) - } else { - None - } - } - - /// Set the time limit for excessive disk use. - pub fn set_block_time_limit(&mut self, limit: u64) { - self.0.dqb_btime = limit; - } - - /// Time limit for excessive files. - pub fn inode_time_limit(&self) -> Option { - let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid); - if valid_fields.contains(QuotaValidFlags::QIF_ITIME) { - Some(self.0.dqb_itime) - } else { - None - } - } - - /// Set the time limit for excessive files. - pub fn set_inode_time_limit(&mut self, limit: u64) { - self.0.dqb_itime = limit; - } -} - -fn quotactl(cmd: QuotaCmd, special: Option<&P>, id: c_int, addr: *mut c_char) -> Result<()> { - unsafe { - Errno::clear(); - let res = match special { - Some(dev) => dev.with_nix_path(|path| libc::quotactl(cmd.as_int(), path.as_ptr(), id, addr)), - None => Ok(libc::quotactl(cmd.as_int(), ptr::null(), id, addr)), - }?; - - Errno::result(res).map(drop) - } -} - -/// Turn on disk quotas for a block device. -pub fn quotactl_on(which: QuotaType, special: &P, format: QuotaFmt, quota_file: &P) -> Result<()> { - quota_file.with_nix_path(|path| { - let mut path_copy = path.to_bytes_with_nul().to_owned(); - let p: *mut c_char = path_copy.as_mut_ptr() as *mut c_char; - quotactl(QuotaCmd(QuotaSubCmd::Q_QUOTAON, which), Some(special), format as c_int, p) - })? -} - -/// Disable disk quotas for a block device. -pub fn quotactl_off(which: QuotaType, special: &P) -> Result<()> { - quotactl(QuotaCmd(QuotaSubCmd::Q_QUOTAOFF, which), Some(special), 0, ptr::null_mut()) -} - -/// Update the on-disk copy of quota usages for a filesystem. -/// -/// If `special` is `None`, then all file systems with active quotas are sync'd. -pub fn quotactl_sync(which: QuotaType, special: Option<&P>) -> Result<()> { - quotactl(QuotaCmd(QuotaSubCmd::Q_SYNC, which), special, 0, ptr::null_mut()) -} - -/// Get disk quota limits and current usage for the given user/group id. -pub fn quotactl_get(which: QuotaType, special: &P, id: c_int) -> Result { - let mut dqblk = mem::MaybeUninit::uninit(); - quotactl(QuotaCmd(QuotaSubCmd::Q_GETQUOTA, which), Some(special), id, dqblk.as_mut_ptr() as *mut c_char)?; - Ok(unsafe{ Dqblk(dqblk.assume_init())}) -} - -/// Configure quota values for the specified fields for a given user/group id. -pub fn quotactl_set(which: QuotaType, special: &P, id: c_int, dqblk: &Dqblk, fields: QuotaValidFlags) -> Result<()> { - let mut dqblk_copy = *dqblk; - dqblk_copy.0.dqb_valid = fields.bits(); - quotactl(QuotaCmd(QuotaSubCmd::Q_SETQUOTA, which), Some(special), id, &mut dqblk_copy as *mut _ as *mut c_char) -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/reboot.rs b/vendor/nix-v0.23.1-patched/src/sys/reboot.rs deleted file mode 100644 index 46ab68b63..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/reboot.rs +++ /dev/null @@ -1,45 +0,0 @@ -//! Reboot/shutdown or enable/disable Ctrl-Alt-Delete. - -use crate::Result; -use crate::errno::Errno; -use std::convert::Infallible; -use std::mem::drop; - -libc_enum! { - /// How exactly should the system be rebooted. - /// - /// See [`set_cad_enabled()`](fn.set_cad_enabled.html) for - /// enabling/disabling Ctrl-Alt-Delete. - #[repr(i32)] - #[non_exhaustive] - pub enum RebootMode { - RB_HALT_SYSTEM, - RB_KEXEC, - RB_POWER_OFF, - RB_AUTOBOOT, - // we do not support Restart2, - RB_SW_SUSPEND, - } -} - -pub fn reboot(how: RebootMode) -> Result { - unsafe { - libc::reboot(how as libc::c_int) - }; - Err(Errno::last()) -} - -/// Enable or disable the reboot keystroke (Ctrl-Alt-Delete). -/// -/// Corresponds to calling `reboot(RB_ENABLE_CAD)` or `reboot(RB_DISABLE_CAD)` in C. -pub fn set_cad_enabled(enable: bool) -> Result<()> { - let cmd = if enable { - libc::RB_ENABLE_CAD - } else { - libc::RB_DISABLE_CAD - }; - let res = unsafe { - libc::reboot(cmd) - }; - Errno::result(res).map(drop) -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/resource.rs b/vendor/nix-v0.23.1-patched/src/sys/resource.rs deleted file mode 100644 index f3bfb6719..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/resource.rs +++ /dev/null @@ -1,233 +0,0 @@ -//! Configure the process resource limits. -use cfg_if::cfg_if; - -use crate::errno::Errno; -use crate::Result; -pub use libc::rlim_t; -use std::mem; - -cfg_if! { - if #[cfg(all(target_os = "linux", target_env = "gnu"))]{ - use libc::{__rlimit_resource_t, rlimit, RLIM_INFINITY}; - }else if #[cfg(any( - target_os = "freebsd", - target_os = "openbsd", - target_os = "netbsd", - target_os = "macos", - target_os = "ios", - target_os = "android", - target_os = "dragonfly", - all(target_os = "linux", not(target_env = "gnu")) - ))]{ - use libc::{c_int, rlimit, RLIM_INFINITY}; - } -} - -libc_enum! { - /// The Resource enum is platform dependent. Check different platform - /// manuals for more details. Some platform links has been provided for - /// earier reference (non-exhaustive). - /// - /// * [Linux](https://man7.org/linux/man-pages/man2/getrlimit.2.html) - /// * [FreeBSD](https://www.freebsd.org/cgi/man.cgi?query=setrlimit) - - // linux-gnu uses u_int as resource enum, which is implemented in libc as - // well. - // - // https://gcc.gnu.org/legacy-ml/gcc/2015-08/msg00441.html - // https://github.com/rust-lang/libc/blob/master/src/unix/linux_like/linux/gnu/mod.rs - #[cfg_attr(all(target_os = "linux", target_env = "gnu"), repr(u32))] - #[cfg_attr(any( - target_os = "freebsd", - target_os = "openbsd", - target_os = "netbsd", - target_os = "macos", - target_os = "ios", - target_os = "android", - target_os = "dragonfly", - all(target_os = "linux", not(target_env = "gnu")) - ), repr(i32))] - #[non_exhaustive] - pub enum Resource { - #[cfg(not(any( - target_os = "freebsd", - target_os = "netbsd", - target_os = "openbsd" - )))] - /// The maximum amount (in bytes) of virtual memory the process is - /// allowed to map. - RLIMIT_AS, - /// The largest size (in bytes) core(5) file that may be created. - RLIMIT_CORE, - /// The maximum amount of cpu time (in seconds) to be used by each - /// process. - RLIMIT_CPU, - /// The maximum size (in bytes) of the data segment for a process - RLIMIT_DATA, - /// The largest size (in bytes) file that may be created. - RLIMIT_FSIZE, - /// The maximum number of open files for this process. - RLIMIT_NOFILE, - /// The maximum size (in bytes) of the stack segment for a process. - RLIMIT_STACK, - - #[cfg(target_os = "freebsd")] - /// The maximum number of kqueues this user id is allowed to create. - RLIMIT_KQUEUES, - - #[cfg(any(target_os = "android", target_os = "linux"))] - /// A limit on the combined number of flock locks and fcntl leases that - /// this process may establish. - RLIMIT_LOCKS, - - #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "openbsd", target_os = "linux"))] - /// The maximum size (in bytes) which a process may lock into memory - /// using the mlock(2) system call. - RLIMIT_MEMLOCK, - - #[cfg(any(target_os = "android", target_os = "linux"))] - /// A limit on the number of bytes that can be allocated for POSIX - /// message queues for the real user ID of the calling process. - RLIMIT_MSGQUEUE, - - #[cfg(any(target_os = "android", target_os = "linux"))] - /// A ceiling to which the process's nice value can be raised using - /// setpriority or nice. - RLIMIT_NICE, - - #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "openbsd", target_os = "linux"))] - /// The maximum number of simultaneous processes for this user id. - RLIMIT_NPROC, - - #[cfg(target_os = "freebsd")] - /// The maximum number of pseudo-terminals this user id is allowed to - /// create. - RLIMIT_NPTS, - - #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "openbsd", target_os = "linux"))] - /// When there is memory pressure and swap is available, prioritize - /// eviction of a process' resident pages beyond this amount (in bytes). - RLIMIT_RSS, - - #[cfg(any(target_os = "android", target_os = "linux"))] - /// A ceiling on the real-time priority that may be set for this process - /// using sched_setscheduler and sched_set‐ param. - RLIMIT_RTPRIO, - - #[cfg(any(target_os = "linux"))] - /// A limit (in microseconds) on the amount of CPU time that a process - /// scheduled under a real-time scheduling policy may con‐ sume without - /// making a blocking system call. - RLIMIT_RTTIME, - - #[cfg(any(target_os = "android", target_os = "linux"))] - /// A limit on the number of signals that may be queued for the real - /// user ID of the calling process. - RLIMIT_SIGPENDING, - - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - /// The maximum size (in bytes) of socket buffer usage for this user. - RLIMIT_SBSIZE, - - #[cfg(target_os = "freebsd")] - /// The maximum size (in bytes) of the swap space that may be reserved - /// or used by all of this user id's processes. - RLIMIT_SWAP, - - #[cfg(target_os = "freebsd")] - /// An alias for RLIMIT_AS. - RLIMIT_VMEM, - } -} - -/// Get the current processes resource limits -/// -/// A value of `None` indicates the value equals to `RLIM_INFINITY` which means -/// there is no limit. -/// -/// # Parameters -/// -/// * `resource`: The [`Resource`] that we want to get the limits of. -/// -/// # Examples -/// -/// ``` -/// # use nix::sys::resource::{getrlimit, Resource}; -/// -/// let (soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); -/// println!("current soft_limit: {:?}", soft_limit); -/// println!("current hard_limit: {:?}", hard_limit); -/// ``` -/// -/// # References -/// -/// [getrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215) -/// -/// [`Resource`]: enum.Resource.html -pub fn getrlimit(resource: Resource) -> Result<(Option, Option)> { - let mut old_rlim = mem::MaybeUninit::::uninit(); - - cfg_if! { - if #[cfg(all(target_os = "linux", target_env = "gnu"))]{ - let res = unsafe { libc::getrlimit(resource as __rlimit_resource_t, old_rlim.as_mut_ptr()) }; - }else{ - let res = unsafe { libc::getrlimit(resource as c_int, old_rlim.as_mut_ptr()) }; - } - } - - Errno::result(res).map(|_| { - let rlimit { rlim_cur, rlim_max } = unsafe { old_rlim.assume_init() }; - (Some(rlim_cur), Some(rlim_max)) - }) -} - -/// Set the current processes resource limits -/// -/// # Parameters -/// -/// * `resource`: The [`Resource`] that we want to set the limits of. -/// * `soft_limit`: The value that the kernel enforces for the corresponding -/// resource. Note: `None` input will be replaced by constant `RLIM_INFINITY`. -/// * `hard_limit`: The ceiling for the soft limit. Must be lower or equal to -/// the current hard limit for non-root users. Note: `None` input will be -/// replaced by constant `RLIM_INFINITY`. -/// -/// > Note: for some os (linux_gnu), setting hard_limit to `RLIM_INFINITY` can -/// > results `EPERM` Error. So you will need to set the number explicitly. -/// -/// # Examples -/// -/// ``` -/// # use nix::sys::resource::{setrlimit, Resource}; -/// -/// let soft_limit = Some(512); -/// let hard_limit = Some(1024); -/// setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap(); -/// ``` -/// -/// # References -/// -/// [setrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215) -/// -/// [`Resource`]: enum.Resource.html -/// -/// Note: `setrlimit` provides a safe wrapper to libc's `setrlimit`. -pub fn setrlimit( - resource: Resource, - soft_limit: Option, - hard_limit: Option, -) -> Result<()> { - let new_rlim = rlimit { - rlim_cur: soft_limit.unwrap_or(RLIM_INFINITY), - rlim_max: hard_limit.unwrap_or(RLIM_INFINITY), - }; - cfg_if! { - if #[cfg(all(target_os = "linux", target_env = "gnu"))]{ - let res = unsafe { libc::setrlimit(resource as __rlimit_resource_t, &new_rlim as *const rlimit) }; - }else{ - let res = unsafe { libc::setrlimit(resource as c_int, &new_rlim as *const rlimit) }; - } - } - - Errno::result(res).map(drop) -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/select.rs b/vendor/nix-v0.23.1-patched/src/sys/select.rs deleted file mode 100644 index 4d7576a58..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/select.rs +++ /dev/null @@ -1,430 +0,0 @@ -//! Portably monitor a group of file descriptors for readiness. -use std::convert::TryFrom; -use std::iter::FusedIterator; -use std::mem; -use std::ops::Range; -use std::os::unix::io::RawFd; -use std::ptr::{null, null_mut}; -use libc::{self, c_int}; -use crate::Result; -use crate::errno::Errno; -use crate::sys::signal::SigSet; -use crate::sys::time::{TimeSpec, TimeVal}; - -pub use libc::FD_SETSIZE; - -/// Contains a set of file descriptors used by [`select`] -#[repr(transparent)] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct FdSet(libc::fd_set); - -fn assert_fd_valid(fd: RawFd) { - assert!( - usize::try_from(fd).map_or(false, |fd| fd < FD_SETSIZE), - "fd must be in the range 0..FD_SETSIZE", - ); -} - -impl FdSet { - /// Create an empty `FdSet` - pub fn new() -> FdSet { - let mut fdset = mem::MaybeUninit::uninit(); - unsafe { - libc::FD_ZERO(fdset.as_mut_ptr()); - FdSet(fdset.assume_init()) - } - } - - /// Add a file descriptor to an `FdSet` - pub fn insert(&mut self, fd: RawFd) { - assert_fd_valid(fd); - unsafe { libc::FD_SET(fd, &mut self.0) }; - } - - /// Remove a file descriptor from an `FdSet` - pub fn remove(&mut self, fd: RawFd) { - assert_fd_valid(fd); - unsafe { libc::FD_CLR(fd, &mut self.0) }; - } - - /// Test an `FdSet` for the presence of a certain file descriptor. - pub fn contains(&self, fd: RawFd) -> bool { - assert_fd_valid(fd); - unsafe { libc::FD_ISSET(fd, &self.0) } - } - - /// Remove all file descriptors from this `FdSet`. - pub fn clear(&mut self) { - unsafe { libc::FD_ZERO(&mut self.0) }; - } - - /// Finds the highest file descriptor in the set. - /// - /// Returns `None` if the set is empty. - /// - /// This can be used to calculate the `nfds` parameter of the [`select`] function. - /// - /// # Example - /// - /// ``` - /// # use nix::sys::select::FdSet; - /// let mut set = FdSet::new(); - /// set.insert(4); - /// set.insert(9); - /// assert_eq!(set.highest(), Some(9)); - /// ``` - /// - /// [`select`]: fn.select.html - pub fn highest(&self) -> Option { - self.fds(None).next_back() - } - - /// Returns an iterator over the file descriptors in the set. - /// - /// For performance, it takes an optional higher bound: the iterator will - /// not return any elements of the set greater than the given file - /// descriptor. - /// - /// # Examples - /// - /// ``` - /// # use nix::sys::select::FdSet; - /// # use std::os::unix::io::RawFd; - /// let mut set = FdSet::new(); - /// set.insert(4); - /// set.insert(9); - /// let fds: Vec = set.fds(None).collect(); - /// assert_eq!(fds, vec![4, 9]); - /// ``` - #[inline] - pub fn fds(&self, highest: Option) -> Fds { - Fds { - set: self, - range: 0..highest.map(|h| h as usize + 1).unwrap_or(FD_SETSIZE), - } - } -} - -impl Default for FdSet { - fn default() -> Self { - Self::new() - } -} - -/// Iterator over `FdSet`. -#[derive(Debug)] -pub struct Fds<'a> { - set: &'a FdSet, - range: Range, -} - -impl<'a> Iterator for Fds<'a> { - type Item = RawFd; - - fn next(&mut self) -> Option { - for i in &mut self.range { - if self.set.contains(i as RawFd) { - return Some(i as RawFd); - } - } - None - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let (_, upper) = self.range.size_hint(); - (0, upper) - } -} - -impl<'a> DoubleEndedIterator for Fds<'a> { - #[inline] - fn next_back(&mut self) -> Option { - while let Some(i) = self.range.next_back() { - if self.set.contains(i as RawFd) { - return Some(i as RawFd); - } - } - None - } -} - -impl<'a> FusedIterator for Fds<'a> {} - -/// Monitors file descriptors for readiness -/// -/// Returns the total number of ready file descriptors in all sets. The sets are changed so that all -/// file descriptors that are ready for the given operation are set. -/// -/// When this function returns, `timeout` has an implementation-defined value. -/// -/// # Parameters -/// -/// * `nfds`: The highest file descriptor set in any of the passed `FdSet`s, plus 1. If `None`, this -/// is calculated automatically by calling [`FdSet::highest`] on all descriptor sets and adding 1 -/// to the maximum of that. -/// * `readfds`: File descriptors to check for being ready to read. -/// * `writefds`: File descriptors to check for being ready to write. -/// * `errorfds`: File descriptors to check for pending error conditions. -/// * `timeout`: Maximum time to wait for descriptors to become ready (`None` to block -/// indefinitely). -/// -/// # References -/// -/// [select(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html) -/// -/// [`FdSet::highest`]: struct.FdSet.html#method.highest -pub fn select<'a, N, R, W, E, T>(nfds: N, - readfds: R, - writefds: W, - errorfds: E, - timeout: T) -> Result -where - N: Into>, - R: Into>, - W: Into>, - E: Into>, - T: Into>, -{ - let mut readfds = readfds.into(); - let mut writefds = writefds.into(); - let mut errorfds = errorfds.into(); - let timeout = timeout.into(); - - let nfds = nfds.into().unwrap_or_else(|| { - readfds.iter_mut() - .chain(writefds.iter_mut()) - .chain(errorfds.iter_mut()) - .map(|set| set.highest().unwrap_or(-1)) - .max() - .unwrap_or(-1) + 1 - }); - - let readfds = readfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut()); - let writefds = writefds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut()); - let errorfds = errorfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut()); - let timeout = timeout.map(|tv| tv as *mut _ as *mut libc::timeval) - .unwrap_or(null_mut()); - - let res = unsafe { - libc::select(nfds, readfds, writefds, errorfds, timeout) - }; - - Errno::result(res) -} - -/// Monitors file descriptors for readiness with an altered signal mask. -/// -/// Returns the total number of ready file descriptors in all sets. The sets are changed so that all -/// file descriptors that are ready for the given operation are set. -/// -/// When this function returns, the original signal mask is restored. -/// -/// Unlike [`select`](#fn.select), `pselect` does not mutate the `timeout` value. -/// -/// # Parameters -/// -/// * `nfds`: The highest file descriptor set in any of the passed `FdSet`s, plus 1. If `None`, this -/// is calculated automatically by calling [`FdSet::highest`] on all descriptor sets and adding 1 -/// to the maximum of that. -/// * `readfds`: File descriptors to check for read readiness -/// * `writefds`: File descriptors to check for write readiness -/// * `errorfds`: File descriptors to check for pending error conditions. -/// * `timeout`: Maximum time to wait for descriptors to become ready (`None` to block -/// indefinitely). -/// * `sigmask`: Signal mask to activate while waiting for file descriptors to turn -/// ready (`None` to set no alternative signal mask). -/// -/// # References -/// -/// [pselect(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html) -/// -/// [The new pselect() system call](https://lwn.net/Articles/176911/) -/// -/// [`FdSet::highest`]: struct.FdSet.html#method.highest -pub fn pselect<'a, N, R, W, E, T, S>(nfds: N, - readfds: R, - writefds: W, - errorfds: E, - timeout: T, - sigmask: S) -> Result -where - N: Into>, - R: Into>, - W: Into>, - E: Into>, - T: Into>, - S: Into>, -{ - let mut readfds = readfds.into(); - let mut writefds = writefds.into(); - let mut errorfds = errorfds.into(); - let sigmask = sigmask.into(); - let timeout = timeout.into(); - - let nfds = nfds.into().unwrap_or_else(|| { - readfds.iter_mut() - .chain(writefds.iter_mut()) - .chain(errorfds.iter_mut()) - .map(|set| set.highest().unwrap_or(-1)) - .max() - .unwrap_or(-1) + 1 - }); - - let readfds = readfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut()); - let writefds = writefds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut()); - let errorfds = errorfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut()); - let timeout = timeout.map(|ts| ts.as_ref() as *const libc::timespec).unwrap_or(null()); - let sigmask = sigmask.map(|sm| sm.as_ref() as *const libc::sigset_t).unwrap_or(null()); - - let res = unsafe { - libc::pselect(nfds, readfds, writefds, errorfds, timeout, sigmask) - }; - - Errno::result(res) -} - - -#[cfg(test)] -mod tests { - use super::*; - use std::os::unix::io::RawFd; - use crate::sys::time::{TimeVal, TimeValLike}; - use crate::unistd::{write, pipe}; - - #[test] - fn fdset_insert() { - let mut fd_set = FdSet::new(); - - for i in 0..FD_SETSIZE { - assert!(!fd_set.contains(i as RawFd)); - } - - fd_set.insert(7); - - assert!(fd_set.contains(7)); - } - - #[test] - fn fdset_remove() { - let mut fd_set = FdSet::new(); - - for i in 0..FD_SETSIZE { - assert!(!fd_set.contains(i as RawFd)); - } - - fd_set.insert(7); - fd_set.remove(7); - - for i in 0..FD_SETSIZE { - assert!(!fd_set.contains(i as RawFd)); - } - } - - #[test] - fn fdset_clear() { - let mut fd_set = FdSet::new(); - fd_set.insert(1); - fd_set.insert((FD_SETSIZE / 2) as RawFd); - fd_set.insert((FD_SETSIZE - 1) as RawFd); - - fd_set.clear(); - - for i in 0..FD_SETSIZE { - assert!(!fd_set.contains(i as RawFd)); - } - } - - #[test] - fn fdset_highest() { - let mut set = FdSet::new(); - assert_eq!(set.highest(), None); - set.insert(0); - assert_eq!(set.highest(), Some(0)); - set.insert(90); - assert_eq!(set.highest(), Some(90)); - set.remove(0); - assert_eq!(set.highest(), Some(90)); - set.remove(90); - assert_eq!(set.highest(), None); - - set.insert(4); - set.insert(5); - set.insert(7); - assert_eq!(set.highest(), Some(7)); - } - - #[test] - fn fdset_fds() { - let mut set = FdSet::new(); - assert_eq!(set.fds(None).collect::>(), vec![]); - set.insert(0); - assert_eq!(set.fds(None).collect::>(), vec![0]); - set.insert(90); - assert_eq!(set.fds(None).collect::>(), vec![0, 90]); - - // highest limit - assert_eq!(set.fds(Some(89)).collect::>(), vec![0]); - assert_eq!(set.fds(Some(90)).collect::>(), vec![0, 90]); - } - - #[test] - fn test_select() { - let (r1, w1) = pipe().unwrap(); - write(w1, b"hi!").unwrap(); - let (r2, _w2) = pipe().unwrap(); - - let mut fd_set = FdSet::new(); - fd_set.insert(r1); - fd_set.insert(r2); - - let mut timeout = TimeVal::seconds(10); - assert_eq!(1, select(None, - &mut fd_set, - None, - None, - &mut timeout).unwrap()); - assert!(fd_set.contains(r1)); - assert!(!fd_set.contains(r2)); - } - - #[test] - fn test_select_nfds() { - let (r1, w1) = pipe().unwrap(); - write(w1, b"hi!").unwrap(); - let (r2, _w2) = pipe().unwrap(); - - let mut fd_set = FdSet::new(); - fd_set.insert(r1); - fd_set.insert(r2); - - let mut timeout = TimeVal::seconds(10); - assert_eq!(1, select(Some(fd_set.highest().unwrap() + 1), - &mut fd_set, - None, - None, - &mut timeout).unwrap()); - assert!(fd_set.contains(r1)); - assert!(!fd_set.contains(r2)); - } - - #[test] - fn test_select_nfds2() { - let (r1, w1) = pipe().unwrap(); - write(w1, b"hi!").unwrap(); - let (r2, _w2) = pipe().unwrap(); - - let mut fd_set = FdSet::new(); - fd_set.insert(r1); - fd_set.insert(r2); - - let mut timeout = TimeVal::seconds(10); - assert_eq!(1, select(::std::cmp::max(r1, r2) + 1, - &mut fd_set, - None, - None, - &mut timeout).unwrap()); - assert!(fd_set.contains(r1)); - assert!(!fd_set.contains(r2)); - } -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/sendfile.rs b/vendor/nix-v0.23.1-patched/src/sys/sendfile.rs deleted file mode 100644 index 7a210c6fc..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/sendfile.rs +++ /dev/null @@ -1,231 +0,0 @@ -//! Send data from a file to a socket, bypassing userland. - -use cfg_if::cfg_if; -use std::os::unix::io::RawFd; -use std::ptr; - -use libc::{self, off_t}; - -use crate::Result; -use crate::errno::Errno; - -/// Copy up to `count` bytes to `out_fd` from `in_fd` starting at `offset`. -/// -/// Returns a `Result` with the number of bytes written. -/// -/// If `offset` is `None`, `sendfile` will begin reading at the current offset of `in_fd`and will -/// update the offset of `in_fd`. If `offset` is `Some`, `sendfile` will begin at the specified -/// offset and will not update the offset of `in_fd`. Instead, it will mutate `offset` to point to -/// the byte after the last byte copied. -/// -/// `in_fd` must support `mmap`-like operations and therefore cannot be a socket. -/// -/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html) -#[cfg(any(target_os = "android", target_os = "linux"))] -pub fn sendfile( - out_fd: RawFd, - in_fd: RawFd, - offset: Option<&mut off_t>, - count: usize, -) -> Result { - let offset = offset - .map(|offset| offset as *mut _) - .unwrap_or(ptr::null_mut()); - let ret = unsafe { libc::sendfile(out_fd, in_fd, offset, count) }; - Errno::result(ret).map(|r| r as usize) -} - -/// Copy up to `count` bytes to `out_fd` from `in_fd` starting at `offset`. -/// -/// Returns a `Result` with the number of bytes written. -/// -/// If `offset` is `None`, `sendfile` will begin reading at the current offset of `in_fd`and will -/// update the offset of `in_fd`. If `offset` is `Some`, `sendfile` will begin at the specified -/// offset and will not update the offset of `in_fd`. Instead, it will mutate `offset` to point to -/// the byte after the last byte copied. -/// -/// `in_fd` must support `mmap`-like operations and therefore cannot be a socket. -/// -/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html) -#[cfg(target_os = "linux")] -pub fn sendfile64( - out_fd: RawFd, - in_fd: RawFd, - offset: Option<&mut libc::off64_t>, - count: usize, -) -> Result { - let offset = offset - .map(|offset| offset as *mut _) - .unwrap_or(ptr::null_mut()); - let ret = unsafe { libc::sendfile64(out_fd, in_fd, offset, count) }; - Errno::result(ret).map(|r| r as usize) -} - -cfg_if! { - if #[cfg(any(target_os = "freebsd", - target_os = "ios", - target_os = "macos"))] { - use crate::sys::uio::IoVec; - - #[derive(Clone, Debug, Eq, Hash, PartialEq)] - struct SendfileHeaderTrailer<'a>( - libc::sf_hdtr, - Option>>, - Option>>, - ); - - impl<'a> SendfileHeaderTrailer<'a> { - fn new( - headers: Option<&'a [&'a [u8]]>, - trailers: Option<&'a [&'a [u8]]> - ) -> SendfileHeaderTrailer<'a> { - let header_iovecs: Option>> = - headers.map(|s| s.iter().map(|b| IoVec::from_slice(b)).collect()); - let trailer_iovecs: Option>> = - trailers.map(|s| s.iter().map(|b| IoVec::from_slice(b)).collect()); - SendfileHeaderTrailer( - libc::sf_hdtr { - headers: { - header_iovecs - .as_ref() - .map_or(ptr::null(), |v| v.as_ptr()) as *mut libc::iovec - }, - hdr_cnt: header_iovecs.as_ref().map(|v| v.len()).unwrap_or(0) as i32, - trailers: { - trailer_iovecs - .as_ref() - .map_or(ptr::null(), |v| v.as_ptr()) as *mut libc::iovec - }, - trl_cnt: trailer_iovecs.as_ref().map(|v| v.len()).unwrap_or(0) as i32 - }, - header_iovecs, - trailer_iovecs, - ) - } - } - } -} - -cfg_if! { - if #[cfg(target_os = "freebsd")] { - use libc::c_int; - - libc_bitflags!{ - /// Configuration options for [`sendfile`.](fn.sendfile.html) - pub struct SfFlags: c_int { - /// Causes `sendfile` to return EBUSY instead of blocking when attempting to read a - /// busy page. - SF_NODISKIO; - /// Causes `sendfile` to sleep until the network stack releases its reference to the - /// VM pages read. When `sendfile` returns, the data is not guaranteed to have been - /// sent, but it is safe to modify the file. - SF_SYNC; - /// Causes `sendfile` to cache exactly the number of pages specified in the - /// `readahead` parameter, disabling caching heuristics. - SF_USER_READAHEAD; - /// Causes `sendfile` not to cache the data read. - SF_NOCACHE; - } - } - - /// Read up to `count` bytes from `in_fd` starting at `offset` and write to `out_sock`. - /// - /// Returns a `Result` and a count of bytes written. Bytes written may be non-zero even if - /// an error occurs. - /// - /// `in_fd` must describe a regular file or shared memory object. `out_sock` must describe a - /// stream socket. - /// - /// If `offset` falls past the end of the file, the function returns success and zero bytes - /// written. - /// - /// If `count` is `None` or 0, bytes will be read from `in_fd` until reaching the end of - /// file (EOF). - /// - /// `headers` and `trailers` specify optional slices of byte slices to be sent before and - /// after the data read from `in_fd`, respectively. The length of headers and trailers sent - /// is included in the returned count of bytes written. The values of `offset` and `count` - /// do not apply to headers or trailers. - /// - /// `readahead` specifies the minimum number of pages to cache in memory ahead of the page - /// currently being sent. - /// - /// For more information, see - /// [the sendfile(2) man page.](https://www.freebsd.org/cgi/man.cgi?query=sendfile&sektion=2) - #[allow(clippy::too_many_arguments)] - pub fn sendfile( - in_fd: RawFd, - out_sock: RawFd, - offset: off_t, - count: Option, - headers: Option<&[&[u8]]>, - trailers: Option<&[&[u8]]>, - flags: SfFlags, - readahead: u16 - ) -> (Result<()>, off_t) { - // Readahead goes in upper 16 bits - // Flags goes in lower 16 bits - // see `man 2 sendfile` - let ra32 = u32::from(readahead); - let flags: u32 = (ra32 << 16) | (flags.bits() as u32); - let mut bytes_sent: off_t = 0; - let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers)); - let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr); - let return_code = unsafe { - libc::sendfile(in_fd, - out_sock, - offset, - count.unwrap_or(0), - hdtr_ptr as *mut libc::sf_hdtr, - &mut bytes_sent as *mut off_t, - flags as c_int) - }; - (Errno::result(return_code).and(Ok(())), bytes_sent) - } - } else if #[cfg(any(target_os = "ios", target_os = "macos"))] { - /// Read bytes from `in_fd` starting at `offset` and write up to `count` bytes to - /// `out_sock`. - /// - /// Returns a `Result` and a count of bytes written. Bytes written may be non-zero even if - /// an error occurs. - /// - /// `in_fd` must describe a regular file. `out_sock` must describe a stream socket. - /// - /// If `offset` falls past the end of the file, the function returns success and zero bytes - /// written. - /// - /// If `count` is `None` or 0, bytes will be read from `in_fd` until reaching the end of - /// file (EOF). - /// - /// `hdtr` specifies an optional list of headers and trailers to be sent before and after - /// the data read from `in_fd`, respectively. The length of headers and trailers sent is - /// included in the returned count of bytes written. If any headers are specified and - /// `count` is non-zero, the length of the headers will be counted in the limit of total - /// bytes sent. Trailers do not count toward the limit of bytes sent and will always be sent - /// regardless. The value of `offset` does not affect headers or trailers. - /// - /// For more information, see - /// [the sendfile(2) man page.](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man2/sendfile.2.html) - pub fn sendfile( - in_fd: RawFd, - out_sock: RawFd, - offset: off_t, - count: Option, - headers: Option<&[&[u8]]>, - trailers: Option<&[&[u8]]> - ) -> (Result<()>, off_t) { - let mut len = count.unwrap_or(0); - let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers)); - let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr); - let return_code = unsafe { - libc::sendfile(in_fd, - out_sock, - offset, - &mut len as *mut off_t, - hdtr_ptr as *mut libc::sf_hdtr, - 0) - }; - (Errno::result(return_code).and(Ok(())), len) - } - } -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/signal.rs b/vendor/nix-v0.23.1-patched/src/sys/signal.rs deleted file mode 100644 index e8c79d336..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/signal.rs +++ /dev/null @@ -1,1234 +0,0 @@ -// Portions of this file are Copyright 2014 The Rust Project Developers. -// See https://www.rust-lang.org/policies/licenses. - -//! Operating system signals. - -use crate::{Error, Result}; -use crate::errno::Errno; -use crate::unistd::Pid; -use std::mem; -use std::fmt; -use std::str::FromStr; -#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] -use std::os::unix::io::RawFd; -use std::ptr; - -#[cfg(not(any(target_os = "openbsd", target_os = "redox")))] -pub use self::sigevent::*; - -libc_enum!{ - /// Types of operating system signals - // Currently there is only one definition of c_int in libc, as well as only one - // type for signal constants. - // We would prefer to use the libc::c_int alias in the repr attribute. Unfortunately - // this is not (yet) possible. - #[repr(i32)] - #[non_exhaustive] - pub enum Signal { - /// Hangup - SIGHUP, - /// Interrupt - SIGINT, - /// Quit - SIGQUIT, - /// Illegal instruction (not reset when caught) - SIGILL, - /// Trace trap (not reset when caught) - SIGTRAP, - /// Abort - SIGABRT, - /// Bus error - SIGBUS, - /// Floating point exception - SIGFPE, - /// Kill (cannot be caught or ignored) - SIGKILL, - /// User defined signal 1 - SIGUSR1, - /// Segmentation violation - SIGSEGV, - /// User defined signal 2 - SIGUSR2, - /// Write on a pipe with no one to read it - SIGPIPE, - /// Alarm clock - SIGALRM, - /// Software termination signal from kill - SIGTERM, - /// Stack fault (obsolete) - #[cfg(all(any(target_os = "android", target_os = "emscripten", - target_os = "fuchsia", target_os = "linux"), - not(any(target_arch = "mips", target_arch = "mips64", - target_arch = "sparc64"))))] - SIGSTKFLT, - /// To parent on child stop or exit - SIGCHLD, - /// Continue a stopped process - SIGCONT, - /// Sendable stop signal not from tty - SIGSTOP, - /// Stop signal from tty - SIGTSTP, - /// To readers pgrp upon background tty read - SIGTTIN, - /// Like TTIN if (tp->t_local<OSTOP) - SIGTTOU, - /// Urgent condition on IO channel - SIGURG, - /// Exceeded CPU time limit - SIGXCPU, - /// Exceeded file size limit - SIGXFSZ, - /// Virtual time alarm - SIGVTALRM, - /// Profiling time alarm - SIGPROF, - /// Window size changes - SIGWINCH, - /// Input/output possible signal - SIGIO, - #[cfg(any(target_os = "android", target_os = "emscripten", - target_os = "fuchsia", target_os = "linux"))] - /// Power failure imminent. - SIGPWR, - /// Bad system call - SIGSYS, - #[cfg(not(any(target_os = "android", target_os = "emscripten", - target_os = "fuchsia", target_os = "linux", - target_os = "redox")))] - /// Emulator trap - SIGEMT, - #[cfg(not(any(target_os = "android", target_os = "emscripten", - target_os = "fuchsia", target_os = "linux", - target_os = "redox")))] - /// Information request - SIGINFO, - } - impl TryFrom -} - -impl FromStr for Signal { - type Err = Error; - fn from_str(s: &str) -> Result { - Ok(match s { - "SIGHUP" => Signal::SIGHUP, - "SIGINT" => Signal::SIGINT, - "SIGQUIT" => Signal::SIGQUIT, - "SIGILL" => Signal::SIGILL, - "SIGTRAP" => Signal::SIGTRAP, - "SIGABRT" => Signal::SIGABRT, - "SIGBUS" => Signal::SIGBUS, - "SIGFPE" => Signal::SIGFPE, - "SIGKILL" => Signal::SIGKILL, - "SIGUSR1" => Signal::SIGUSR1, - "SIGSEGV" => Signal::SIGSEGV, - "SIGUSR2" => Signal::SIGUSR2, - "SIGPIPE" => Signal::SIGPIPE, - "SIGALRM" => Signal::SIGALRM, - "SIGTERM" => Signal::SIGTERM, - #[cfg(all(any(target_os = "android", target_os = "emscripten", - target_os = "fuchsia", target_os = "linux"), - not(any(target_arch = "mips", target_arch = "mips64", - target_arch = "sparc64"))))] - "SIGSTKFLT" => Signal::SIGSTKFLT, - "SIGCHLD" => Signal::SIGCHLD, - "SIGCONT" => Signal::SIGCONT, - "SIGSTOP" => Signal::SIGSTOP, - "SIGTSTP" => Signal::SIGTSTP, - "SIGTTIN" => Signal::SIGTTIN, - "SIGTTOU" => Signal::SIGTTOU, - "SIGURG" => Signal::SIGURG, - "SIGXCPU" => Signal::SIGXCPU, - "SIGXFSZ" => Signal::SIGXFSZ, - "SIGVTALRM" => Signal::SIGVTALRM, - "SIGPROF" => Signal::SIGPROF, - "SIGWINCH" => Signal::SIGWINCH, - "SIGIO" => Signal::SIGIO, - #[cfg(any(target_os = "android", target_os = "emscripten", - target_os = "fuchsia", target_os = "linux"))] - "SIGPWR" => Signal::SIGPWR, - "SIGSYS" => Signal::SIGSYS, - #[cfg(not(any(target_os = "android", target_os = "emscripten", - target_os = "fuchsia", target_os = "linux", - target_os = "redox")))] - "SIGEMT" => Signal::SIGEMT, - #[cfg(not(any(target_os = "android", target_os = "emscripten", - target_os = "fuchsia", target_os = "linux", - target_os = "redox")))] - "SIGINFO" => Signal::SIGINFO, - _ => return Err(Errno::EINVAL), - }) - } -} - -impl Signal { - /// Returns name of signal. - /// - /// This function is equivalent to `>::as_ref()`, - /// with difference that returned string is `'static` - /// and not bound to `self`'s lifetime. - pub const fn as_str(self) -> &'static str { - match self { - Signal::SIGHUP => "SIGHUP", - Signal::SIGINT => "SIGINT", - Signal::SIGQUIT => "SIGQUIT", - Signal::SIGILL => "SIGILL", - Signal::SIGTRAP => "SIGTRAP", - Signal::SIGABRT => "SIGABRT", - Signal::SIGBUS => "SIGBUS", - Signal::SIGFPE => "SIGFPE", - Signal::SIGKILL => "SIGKILL", - Signal::SIGUSR1 => "SIGUSR1", - Signal::SIGSEGV => "SIGSEGV", - Signal::SIGUSR2 => "SIGUSR2", - Signal::SIGPIPE => "SIGPIPE", - Signal::SIGALRM => "SIGALRM", - Signal::SIGTERM => "SIGTERM", - #[cfg(all(any(target_os = "android", target_os = "emscripten", - target_os = "fuchsia", target_os = "linux"), - not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))] - Signal::SIGSTKFLT => "SIGSTKFLT", - Signal::SIGCHLD => "SIGCHLD", - Signal::SIGCONT => "SIGCONT", - Signal::SIGSTOP => "SIGSTOP", - Signal::SIGTSTP => "SIGTSTP", - Signal::SIGTTIN => "SIGTTIN", - Signal::SIGTTOU => "SIGTTOU", - Signal::SIGURG => "SIGURG", - Signal::SIGXCPU => "SIGXCPU", - Signal::SIGXFSZ => "SIGXFSZ", - Signal::SIGVTALRM => "SIGVTALRM", - Signal::SIGPROF => "SIGPROF", - Signal::SIGWINCH => "SIGWINCH", - Signal::SIGIO => "SIGIO", - #[cfg(any(target_os = "android", target_os = "emscripten", - target_os = "fuchsia", target_os = "linux"))] - Signal::SIGPWR => "SIGPWR", - Signal::SIGSYS => "SIGSYS", - #[cfg(not(any(target_os = "android", target_os = "emscripten", - target_os = "fuchsia", target_os = "linux", - target_os = "redox")))] - Signal::SIGEMT => "SIGEMT", - #[cfg(not(any(target_os = "android", target_os = "emscripten", - target_os = "fuchsia", target_os = "linux", - target_os = "redox")))] - Signal::SIGINFO => "SIGINFO", - } - } -} - -impl AsRef for Signal { - fn as_ref(&self) -> &str { - self.as_str() - } -} - -impl fmt::Display for Signal { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(self.as_ref()) - } -} - -pub use self::Signal::*; - -#[cfg(target_os = "redox")] -const SIGNALS: [Signal; 29] = [ - SIGHUP, - SIGINT, - SIGQUIT, - SIGILL, - SIGTRAP, - SIGABRT, - SIGBUS, - SIGFPE, - SIGKILL, - SIGUSR1, - SIGSEGV, - SIGUSR2, - SIGPIPE, - SIGALRM, - SIGTERM, - SIGCHLD, - SIGCONT, - SIGSTOP, - SIGTSTP, - SIGTTIN, - SIGTTOU, - SIGURG, - SIGXCPU, - SIGXFSZ, - SIGVTALRM, - SIGPROF, - SIGWINCH, - SIGIO, - SIGSYS]; -#[cfg(all(any(target_os = "linux", target_os = "android", - target_os = "emscripten", target_os = "fuchsia"), - not(any(target_arch = "mips", target_arch = "mips64", - target_arch = "sparc64"))))] -const SIGNALS: [Signal; 31] = [ - SIGHUP, - SIGINT, - SIGQUIT, - SIGILL, - SIGTRAP, - SIGABRT, - SIGBUS, - SIGFPE, - SIGKILL, - SIGUSR1, - SIGSEGV, - SIGUSR2, - SIGPIPE, - SIGALRM, - SIGTERM, - SIGSTKFLT, - SIGCHLD, - SIGCONT, - SIGSTOP, - SIGTSTP, - SIGTTIN, - SIGTTOU, - SIGURG, - SIGXCPU, - SIGXFSZ, - SIGVTALRM, - SIGPROF, - SIGWINCH, - SIGIO, - SIGPWR, - SIGSYS]; -#[cfg(all(any(target_os = "linux", target_os = "android", - target_os = "emscripten", target_os = "fuchsia"), - any(target_arch = "mips", target_arch = "mips64", - target_arch = "sparc64")))] -const SIGNALS: [Signal; 30] = [ - SIGHUP, - SIGINT, - SIGQUIT, - SIGILL, - SIGTRAP, - SIGABRT, - SIGBUS, - SIGFPE, - SIGKILL, - SIGUSR1, - SIGSEGV, - SIGUSR2, - SIGPIPE, - SIGALRM, - SIGTERM, - SIGCHLD, - SIGCONT, - SIGSTOP, - SIGTSTP, - SIGTTIN, - SIGTTOU, - SIGURG, - SIGXCPU, - SIGXFSZ, - SIGVTALRM, - SIGPROF, - SIGWINCH, - SIGIO, - SIGPWR, - SIGSYS]; -#[cfg(not(any(target_os = "linux", target_os = "android", - target_os = "fuchsia", target_os = "emscripten", - target_os = "redox")))] -const SIGNALS: [Signal; 31] = [ - SIGHUP, - SIGINT, - SIGQUIT, - SIGILL, - SIGTRAP, - SIGABRT, - SIGBUS, - SIGFPE, - SIGKILL, - SIGUSR1, - SIGSEGV, - SIGUSR2, - SIGPIPE, - SIGALRM, - SIGTERM, - SIGCHLD, - SIGCONT, - SIGSTOP, - SIGTSTP, - SIGTTIN, - SIGTTOU, - SIGURG, - SIGXCPU, - SIGXFSZ, - SIGVTALRM, - SIGPROF, - SIGWINCH, - SIGIO, - SIGSYS, - SIGEMT, - SIGINFO]; - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -/// Iterate through all signals defined by this operating system -pub struct SignalIterator { - next: usize, -} - -impl Iterator for SignalIterator { - type Item = Signal; - - fn next(&mut self) -> Option { - if self.next < SIGNALS.len() { - let next_signal = SIGNALS[self.next]; - self.next += 1; - Some(next_signal) - } else { - None - } - } -} - -impl Signal { - /// Iterate through all signals defined by this OS - pub const fn iterator() -> SignalIterator { - SignalIterator{next: 0} - } -} - -/// Alias for [`SIGABRT`] -pub const SIGIOT : Signal = SIGABRT; -/// Alias for [`SIGIO`] -pub const SIGPOLL : Signal = SIGIO; -/// Alias for [`SIGSYS`] -pub const SIGUNUSED : Signal = SIGSYS; - -#[cfg(not(target_os = "redox"))] -type SaFlags_t = libc::c_int; -#[cfg(target_os = "redox")] -type SaFlags_t = libc::c_ulong; - -libc_bitflags!{ - /// Controls the behavior of a [`SigAction`] - pub struct SaFlags: SaFlags_t { - /// When catching a [`Signal::SIGCHLD`] signal, the signal will be - /// generated only when a child process exits, not when a child process - /// stops. - SA_NOCLDSTOP; - /// When catching a [`Signal::SIGCHLD`] signal, the system will not - /// create zombie processes when children of the calling process exit. - SA_NOCLDWAIT; - /// Further occurrences of the delivered signal are not masked during - /// the execution of the handler. - SA_NODEFER; - /// The system will deliver the signal to the process on a signal stack, - /// specified by each thread with sigaltstack(2). - SA_ONSTACK; - /// The handler is reset back to the default at the moment the signal is - /// delivered. - SA_RESETHAND; - /// Requests that certain system calls restart if interrupted by this - /// signal. See the man page for complete details. - SA_RESTART; - /// This flag is controlled internally by Nix. - SA_SIGINFO; - } -} - -libc_enum! { - /// Specifies how certain functions should manipulate a signal mask - #[repr(i32)] - #[non_exhaustive] - pub enum SigmaskHow { - /// The new mask is the union of the current mask and the specified set. - SIG_BLOCK, - /// The new mask is the intersection of the current mask and the - /// complement of the specified set. - SIG_UNBLOCK, - /// The current mask is replaced by the specified set. - SIG_SETMASK, - } -} - -/// Specifies a set of [`Signal`]s that may be blocked, waited for, etc. -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct SigSet { - sigset: libc::sigset_t -} - - -impl SigSet { - /// Initialize to include all signals. - pub fn all() -> SigSet { - let mut sigset = mem::MaybeUninit::uninit(); - let _ = unsafe { libc::sigfillset(sigset.as_mut_ptr()) }; - - unsafe{ SigSet { sigset: sigset.assume_init() } } - } - - /// Initialize to include nothing. - pub fn empty() -> SigSet { - let mut sigset = mem::MaybeUninit::uninit(); - let _ = unsafe { libc::sigemptyset(sigset.as_mut_ptr()) }; - - unsafe{ SigSet { sigset: sigset.assume_init() } } - } - - /// Add the specified signal to the set. - pub fn add(&mut self, signal: Signal) { - unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) }; - } - - /// Remove all signals from this set. - pub fn clear(&mut self) { - unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) }; - } - - /// Remove the specified signal from this set. - pub fn remove(&mut self, signal: Signal) { - unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) }; - } - - /// Return whether this set includes the specified signal. - pub fn contains(&self, signal: Signal) -> bool { - let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) }; - - match res { - 1 => true, - 0 => false, - _ => unreachable!("unexpected value from sigismember"), - } - } - - /// Merge all of `other`'s signals into this set. - // TODO: use libc::sigorset on supported operating systems. - pub fn extend(&mut self, other: &SigSet) { - for signal in Signal::iterator() { - if other.contains(signal) { - self.add(signal); - } - } - } - - /// Gets the currently blocked (masked) set of signals for the calling thread. - pub fn thread_get_mask() -> Result { - let mut oldmask = mem::MaybeUninit::uninit(); - do_pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(oldmask.as_mut_ptr()))?; - Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}}) - } - - /// Sets the set of signals as the signal mask for the calling thread. - pub fn thread_set_mask(&self) -> Result<()> { - pthread_sigmask(SigmaskHow::SIG_SETMASK, Some(self), None) - } - - /// Adds the set of signals to the signal mask for the calling thread. - pub fn thread_block(&self) -> Result<()> { - pthread_sigmask(SigmaskHow::SIG_BLOCK, Some(self), None) - } - - /// Removes the set of signals from the signal mask for the calling thread. - pub fn thread_unblock(&self) -> Result<()> { - pthread_sigmask(SigmaskHow::SIG_UNBLOCK, Some(self), None) - } - - /// Sets the set of signals as the signal mask, and returns the old mask. - pub fn thread_swap_mask(&self, how: SigmaskHow) -> Result { - let mut oldmask = mem::MaybeUninit::uninit(); - do_pthread_sigmask(how, Some(self), Some(oldmask.as_mut_ptr()))?; - Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}}) - } - - /// Suspends execution of the calling thread until one of the signals in the - /// signal mask becomes pending, and returns the accepted signal. - #[cfg(not(target_os = "redox"))] // RedoxFS does not yet support sigwait - pub fn wait(&self) -> Result { - use std::convert::TryFrom; - - let mut signum = mem::MaybeUninit::uninit(); - let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, signum.as_mut_ptr()) }; - - Errno::result(res).map(|_| unsafe { - Signal::try_from(signum.assume_init()).unwrap() - }) - } -} - -impl AsRef for SigSet { - fn as_ref(&self) -> &libc::sigset_t { - &self.sigset - } -} - -/// A signal handler. -#[allow(unknown_lints)] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum SigHandler { - /// Default signal handling. - SigDfl, - /// Request that the signal be ignored. - SigIgn, - /// Use the given signal-catching function, which takes in the signal. - Handler(extern fn(libc::c_int)), - /// Use the given signal-catching function, which takes in the signal, information about how - /// the signal was generated, and a pointer to the threads `ucontext_t`. - #[cfg(not(target_os = "redox"))] - SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)) -} - -/// Action to take on receipt of a signal. Corresponds to `sigaction`. -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct SigAction { - sigaction: libc::sigaction -} - -impl SigAction { - /// Creates a new action. - /// - /// The `SA_SIGINFO` bit in the `flags` argument is ignored (it will be set only if `handler` - /// is the `SigAction` variant). `mask` specifies other signals to block during execution of - /// the signal-catching function. - pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction { - #[cfg(target_os = "redox")] - unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) { - (*p).sa_handler = match handler { - SigHandler::SigDfl => libc::SIG_DFL, - SigHandler::SigIgn => libc::SIG_IGN, - SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize, - }; - } - - #[cfg(not(target_os = "redox"))] - unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) { - (*p).sa_sigaction = match handler { - SigHandler::SigDfl => libc::SIG_DFL, - SigHandler::SigIgn => libc::SIG_IGN, - SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize, - SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize, - }; - } - - let mut s = mem::MaybeUninit::::uninit(); - unsafe { - let p = s.as_mut_ptr(); - install_sig(p, handler); - (*p).sa_flags = match handler { - #[cfg(not(target_os = "redox"))] - SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(), - _ => (flags - SaFlags::SA_SIGINFO).bits(), - }; - (*p).sa_mask = mask.sigset; - - SigAction { sigaction: s.assume_init() } - } - } - - /// Returns the flags set on the action. - pub fn flags(&self) -> SaFlags { - SaFlags::from_bits_truncate(self.sigaction.sa_flags) - } - - /// Returns the set of signals that are blocked during execution of the action's - /// signal-catching function. - pub fn mask(&self) -> SigSet { - SigSet { sigset: self.sigaction.sa_mask } - } - - /// Returns the action's handler. - #[cfg(not(target_os = "redox"))] - pub fn handler(&self) -> SigHandler { - match self.sigaction.sa_sigaction { - libc::SIG_DFL => SigHandler::SigDfl, - libc::SIG_IGN => SigHandler::SigIgn, - p if self.flags().contains(SaFlags::SA_SIGINFO) => - SigHandler::SigAction( - // Safe for one of two reasons: - // * The SigHandler was created by SigHandler::new, in which - // case the pointer is correct, or - // * The SigHandler was created by signal or sigaction, which - // are unsafe functions, so the caller should've somehow - // ensured that it is correctly initialized. - unsafe{ - *(&p as *const usize - as *const extern fn(_, _, _)) - } - as extern fn(_, _, _)), - p => SigHandler::Handler( - // Safe for one of two reasons: - // * The SigHandler was created by SigHandler::new, in which - // case the pointer is correct, or - // * The SigHandler was created by signal or sigaction, which - // are unsafe functions, so the caller should've somehow - // ensured that it is correctly initialized. - unsafe{ - *(&p as *const usize - as *const extern fn(libc::c_int)) - } - as extern fn(libc::c_int)), - } - } - - /// Returns the action's handler. - #[cfg(target_os = "redox")] - pub fn handler(&self) -> SigHandler { - match self.sigaction.sa_handler { - libc::SIG_DFL => SigHandler::SigDfl, - libc::SIG_IGN => SigHandler::SigIgn, - p => SigHandler::Handler( - // Safe for one of two reasons: - // * The SigHandler was created by SigHandler::new, in which - // case the pointer is correct, or - // * The SigHandler was created by signal or sigaction, which - // are unsafe functions, so the caller should've somehow - // ensured that it is correctly initialized. - unsafe{ - *(&p as *const usize - as *const extern fn(libc::c_int)) - } - as extern fn(libc::c_int)), - } - } -} - -/// Changes the action taken by a process on receipt of a specific signal. -/// -/// `signal` can be any signal except `SIGKILL` or `SIGSTOP`. On success, it returns the previous -/// action for the given signal. If `sigaction` fails, no new signal handler is installed. -/// -/// # Safety -/// -/// * Signal handlers may be called at any point during execution, which limits -/// what is safe to do in the body of the signal-catching function. Be certain -/// to only make syscalls that are explicitly marked safe for signal handlers -/// and only share global data using atomics. -/// -/// * There is also no guarantee that the old signal handler was installed -/// correctly. If it was installed by this crate, it will be. But if it was -/// installed by, for example, C code, then there is no guarantee its function -/// pointer is valid. In that case, this function effectively dereferences a -/// raw pointer of unknown provenance. -pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result { - let mut oldact = mem::MaybeUninit::::uninit(); - - let res = libc::sigaction(signal as libc::c_int, - &sigaction.sigaction as *const libc::sigaction, - oldact.as_mut_ptr()); - - Errno::result(res).map(|_| SigAction { sigaction: oldact.assume_init() }) -} - -/// Signal management (see [signal(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html)) -/// -/// Installs `handler` for the given `signal`, returning the previous signal -/// handler. `signal` should only be used following another call to `signal` or -/// if the current handler is the default. The return value of `signal` is -/// undefined after setting the handler with [`sigaction`][SigActionFn]. -/// -/// # Safety -/// -/// If the pointer to the previous signal handler is invalid, undefined -/// behavior could be invoked when casting it back to a [`SigAction`][SigActionStruct]. -/// -/// # Examples -/// -/// Ignore `SIGINT`: -/// -/// ```no_run -/// # use nix::sys::signal::{self, Signal, SigHandler}; -/// unsafe { signal::signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap(); -/// ``` -/// -/// Use a signal handler to set a flag variable: -/// -/// ```no_run -/// # #[macro_use] extern crate lazy_static; -/// # use std::convert::TryFrom; -/// # use std::sync::atomic::{AtomicBool, Ordering}; -/// # use nix::sys::signal::{self, Signal, SigHandler}; -/// lazy_static! { -/// static ref SIGNALED: AtomicBool = AtomicBool::new(false); -/// } -/// -/// extern fn handle_sigint(signal: libc::c_int) { -/// let signal = Signal::try_from(signal).unwrap(); -/// SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed); -/// } -/// -/// fn main() { -/// let handler = SigHandler::Handler(handle_sigint); -/// unsafe { signal::signal(Signal::SIGINT, handler) }.unwrap(); -/// } -/// ``` -/// -/// # Errors -/// -/// Returns [`Error(Errno::EOPNOTSUPP)`] if `handler` is -/// [`SigAction`][SigActionStruct]. Use [`sigaction`][SigActionFn] instead. -/// -/// `signal` also returns any error from `libc::signal`, such as when an attempt -/// is made to catch a signal that cannot be caught or to ignore a signal that -/// cannot be ignored. -/// -/// [`Error::UnsupportedOperation`]: ../../enum.Error.html#variant.UnsupportedOperation -/// [SigActionStruct]: struct.SigAction.html -/// [sigactionFn]: fn.sigaction.html -pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result { - let signal = signal as libc::c_int; - let res = match handler { - SigHandler::SigDfl => libc::signal(signal, libc::SIG_DFL), - SigHandler::SigIgn => libc::signal(signal, libc::SIG_IGN), - SigHandler::Handler(handler) => libc::signal(signal, handler as libc::sighandler_t), - #[cfg(not(target_os = "redox"))] - SigHandler::SigAction(_) => return Err(Errno::ENOTSUP), - }; - Errno::result(res).map(|oldhandler| { - match oldhandler { - libc::SIG_DFL => SigHandler::SigDfl, - libc::SIG_IGN => SigHandler::SigIgn, - p => SigHandler::Handler( - *(&p as *const usize - as *const extern fn(libc::c_int)) - as extern fn(libc::c_int)), - } - }) -} - -fn do_pthread_sigmask(how: SigmaskHow, - set: Option<&SigSet>, - oldset: Option<*mut libc::sigset_t>) -> Result<()> { - if set.is_none() && oldset.is_none() { - return Ok(()) - } - - let res = unsafe { - // if set or oldset is None, pass in null pointers instead - libc::pthread_sigmask(how as libc::c_int, - set.map_or_else(ptr::null::, - |s| &s.sigset as *const libc::sigset_t), - oldset.unwrap_or(ptr::null_mut()) - ) - }; - - Errno::result(res).map(drop) -} - -/// Manages the signal mask (set of blocked signals) for the calling thread. -/// -/// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set. -/// The `how` flag decides the type of update. If `set` is `None`, `how` will be ignored, -/// and no modification will take place. -/// -/// If the 'oldset' parameter is `Some(..)` then the current signal mask will be written into it. -/// -/// If both `set` and `oldset` is `Some(..)`, the current signal mask will be written into oldset, -/// and then it will be updated with `set`. -/// -/// If both `set` and `oldset` is None, this function is a no-op. -/// -/// For more information, visit the [`pthread_sigmask`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html), -/// or [`sigprocmask`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html) man pages. -pub fn pthread_sigmask(how: SigmaskHow, - set: Option<&SigSet>, - oldset: Option<&mut SigSet>) -> Result<()> -{ - do_pthread_sigmask(how, set, oldset.map(|os| &mut os.sigset as *mut _ )) -} - -/// Examine and change blocked signals. -/// -/// For more informations see the [`sigprocmask` man -/// pages](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html). -pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut SigSet>) -> Result<()> { - if set.is_none() && oldset.is_none() { - return Ok(()) - } - - let res = unsafe { - // if set or oldset is None, pass in null pointers instead - libc::sigprocmask(how as libc::c_int, - set.map_or_else(ptr::null::, - |s| &s.sigset as *const libc::sigset_t), - oldset.map_or_else(ptr::null_mut::, - |os| &mut os.sigset as *mut libc::sigset_t)) - }; - - Errno::result(res).map(drop) -} - -/// Send a signal to a process -/// -/// # Arguments -/// -/// * `pid` - Specifies which processes should receive the signal. -/// - If positive, specifies an individual process -/// - If zero, the signal will be sent to all processes whose group -/// ID is equal to the process group ID of the sender. This is a -/// variant of [`killpg`]. -/// - If `-1` and the process has super-user privileges, the signal -/// is sent to all processes exclusing system processes. -/// - If less than `-1`, the signal is sent to all processes whose -/// process group ID is equal to the absolute value of `pid`. -/// * `signal` - Signal to send. If 0, error checking if performed but no -/// signal is actually sent. -/// -/// See Also -/// [`kill(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html) -pub fn kill>>(pid: Pid, signal: T) -> Result<()> { - let res = unsafe { libc::kill(pid.into(), - match signal.into() { - Some(s) => s as libc::c_int, - None => 0, - }) }; - - Errno::result(res).map(drop) -} - -/// Send a signal to a process group -/// -/// # Arguments -/// -/// * `pgrp` - Process group to signal. If less then or equal 1, the behavior -/// is platform-specific. -/// * `signal` - Signal to send. If `None`, `killpg` will only preform error -/// checking and won't send any signal. -/// -/// See Also [killpg(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/killpg.html). -#[cfg(not(target_os = "fuchsia"))] -pub fn killpg>>(pgrp: Pid, signal: T) -> Result<()> { - let res = unsafe { libc::killpg(pgrp.into(), - match signal.into() { - Some(s) => s as libc::c_int, - None => 0, - }) }; - - Errno::result(res).map(drop) -} - -/// Send a signal to the current thread -/// -/// See Also [raise(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/raise.html) -pub fn raise(signal: Signal) -> Result<()> { - let res = unsafe { libc::raise(signal as libc::c_int) }; - - Errno::result(res).map(drop) -} - - -/// Identifies a thread for [`SigevNotify::SigevThreadId`] -#[cfg(target_os = "freebsd")] -pub type type_of_thread_id = libc::lwpid_t; -/// Identifies a thread for [`SigevNotify::SigevThreadId`] -#[cfg(target_os = "linux")] -pub type type_of_thread_id = libc::pid_t; - -/// Specifies the notification method used by a [`SigEvent`] -// sigval is actually a union of a int and a void*. But it's never really used -// as a pointer, because neither libc nor the kernel ever dereference it. nix -// therefore presents it as an intptr_t, which is how kevent uses it. -#[cfg(not(any(target_os = "openbsd", target_os = "redox")))] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum SigevNotify { - /// No notification will be delivered - SigevNone, - /// Notify by delivering a signal to the process. - SigevSignal { - /// Signal to deliver - signal: Signal, - /// Will be present in the `si_value` field of the [`libc::siginfo_t`] - /// structure of the queued signal. - si_value: libc::intptr_t - }, - // Note: SIGEV_THREAD is not implemented because libc::sigevent does not - // expose a way to set the union members needed by SIGEV_THREAD. - /// Notify by delivering an event to a kqueue. - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - SigevKevent { - /// File descriptor of the kqueue to notify. - kq: RawFd, - /// Will be contained in the kevent's `udata` field. - udata: libc::intptr_t - }, - /// Notify by delivering a signal to a thread. - #[cfg(any(target_os = "freebsd", target_os = "linux"))] - SigevThreadId { - /// Signal to send - signal: Signal, - /// LWP ID of the thread to notify - thread_id: type_of_thread_id, - /// Will be present in the `si_value` field of the [`libc::siginfo_t`] - /// structure of the queued signal. - si_value: libc::intptr_t - }, -} - -#[cfg(not(any(target_os = "openbsd", target_os = "redox")))] -mod sigevent { - use std::mem; - use std::ptr; - use super::SigevNotify; - #[cfg(any(target_os = "freebsd", target_os = "linux"))] - use super::type_of_thread_id; - - /// Used to request asynchronous notification of the completion of certain - /// events, such as POSIX AIO and timers. - #[repr(C)] - #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] - pub struct SigEvent { - sigevent: libc::sigevent - } - - impl SigEvent { - /// **Note:** this constructor does not allow the user to set the - /// `sigev_notify_kevent_flags` field. That's considered ok because on FreeBSD - /// at least those flags don't do anything useful. That field is part of a - /// union that shares space with the more genuinely useful fields. - /// - /// **Note:** This constructor also doesn't allow the caller to set the - /// `sigev_notify_function` or `sigev_notify_attributes` fields, which are - /// required for `SIGEV_THREAD`. That's considered ok because on no operating - /// system is `SIGEV_THREAD` the most efficient way to deliver AIO - /// notification. FreeBSD and DragonFly BSD programs should prefer `SIGEV_KEVENT`. - /// Linux, Solaris, and portable programs should prefer `SIGEV_THREAD_ID` or - /// `SIGEV_SIGNAL`. That field is part of a union that shares space with the - /// more genuinely useful `sigev_notify_thread_id` - // Allow invalid_value warning on Fuchsia only. - // See https://github.com/nix-rust/nix/issues/1441 - #[cfg_attr(target_os = "fuchsia", allow(invalid_value))] - pub fn new(sigev_notify: SigevNotify) -> SigEvent { - let mut sev = unsafe { mem::MaybeUninit::::zeroed().assume_init() }; - sev.sigev_notify = match sigev_notify { - SigevNotify::SigevNone => libc::SIGEV_NONE, - SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL, - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - SigevNotify::SigevKevent{..} => libc::SIGEV_KEVENT, - #[cfg(target_os = "freebsd")] - SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID, - #[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))] - SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID, - #[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))] - SigevNotify::SigevThreadId{..} => 4 // No SIGEV_THREAD_ID defined - }; - sev.sigev_signo = match sigev_notify { - SigevNotify::SigevSignal{ signal, .. } => signal as libc::c_int, - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - SigevNotify::SigevKevent{ kq, ..} => kq, - #[cfg(any(target_os = "linux", target_os = "freebsd"))] - SigevNotify::SigevThreadId{ signal, .. } => signal as libc::c_int, - _ => 0 - }; - sev.sigev_value.sival_ptr = match sigev_notify { - SigevNotify::SigevNone => ptr::null_mut::(), - SigevNotify::SigevSignal{ si_value, .. } => si_value as *mut libc::c_void, - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - SigevNotify::SigevKevent{ udata, .. } => udata as *mut libc::c_void, - #[cfg(any(target_os = "freebsd", target_os = "linux"))] - SigevNotify::SigevThreadId{ si_value, .. } => si_value as *mut libc::c_void, - }; - SigEvent::set_tid(&mut sev, &sigev_notify); - SigEvent{sigevent: sev} - } - - #[cfg(any(target_os = "freebsd", target_os = "linux"))] - fn set_tid(sev: &mut libc::sigevent, sigev_notify: &SigevNotify) { - sev.sigev_notify_thread_id = match *sigev_notify { - SigevNotify::SigevThreadId { thread_id, .. } => thread_id, - _ => 0 as type_of_thread_id - }; - } - - #[cfg(not(any(target_os = "freebsd", target_os = "linux")))] - fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) { - } - - /// Return a copy of the inner structure - pub fn sigevent(&self) -> libc::sigevent { - self.sigevent - } - } - - impl<'a> From<&'a libc::sigevent> for SigEvent { - fn from(sigevent: &libc::sigevent) -> Self { - SigEvent{ sigevent: *sigevent } - } - } -} - -#[cfg(test)] -mod tests { - #[cfg(not(target_os = "redox"))] - use std::thread; - use super::*; - - #[test] - fn test_contains() { - let mut mask = SigSet::empty(); - mask.add(SIGUSR1); - - assert!(mask.contains(SIGUSR1)); - assert!(!mask.contains(SIGUSR2)); - - let all = SigSet::all(); - assert!(all.contains(SIGUSR1)); - assert!(all.contains(SIGUSR2)); - } - - #[test] - fn test_clear() { - let mut set = SigSet::all(); - set.clear(); - for signal in Signal::iterator() { - assert!(!set.contains(signal)); - } - } - - #[test] - fn test_from_str_round_trips() { - for signal in Signal::iterator() { - assert_eq!(signal.as_ref().parse::().unwrap(), signal); - assert_eq!(signal.to_string().parse::().unwrap(), signal); - } - } - - #[test] - fn test_from_str_invalid_value() { - let errval = Err(Errno::EINVAL); - assert_eq!("NOSIGNAL".parse::(), errval); - assert_eq!("kill".parse::(), errval); - assert_eq!("9".parse::(), errval); - } - - #[test] - fn test_extend() { - let mut one_signal = SigSet::empty(); - one_signal.add(SIGUSR1); - - let mut two_signals = SigSet::empty(); - two_signals.add(SIGUSR2); - two_signals.extend(&one_signal); - - assert!(two_signals.contains(SIGUSR1)); - assert!(two_signals.contains(SIGUSR2)); - } - - #[test] - #[cfg(not(target_os = "redox"))] - fn test_thread_signal_set_mask() { - thread::spawn(|| { - let prev_mask = SigSet::thread_get_mask() - .expect("Failed to get existing signal mask!"); - - let mut test_mask = prev_mask; - test_mask.add(SIGUSR1); - - assert!(test_mask.thread_set_mask().is_ok()); - let new_mask = SigSet::thread_get_mask() - .expect("Failed to get new mask!"); - - assert!(new_mask.contains(SIGUSR1)); - assert!(!new_mask.contains(SIGUSR2)); - - prev_mask.thread_set_mask().expect("Failed to revert signal mask!"); - }).join().unwrap(); - } - - #[test] - #[cfg(not(target_os = "redox"))] - fn test_thread_signal_block() { - thread::spawn(|| { - let mut mask = SigSet::empty(); - mask.add(SIGUSR1); - - assert!(mask.thread_block().is_ok()); - - assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1)); - }).join().unwrap(); - } - - #[test] - #[cfg(not(target_os = "redox"))] - fn test_thread_signal_unblock() { - thread::spawn(|| { - let mut mask = SigSet::empty(); - mask.add(SIGUSR1); - - assert!(mask.thread_unblock().is_ok()); - - assert!(!SigSet::thread_get_mask().unwrap().contains(SIGUSR1)); - }).join().unwrap(); - } - - #[test] - #[cfg(not(target_os = "redox"))] - fn test_thread_signal_swap() { - thread::spawn(|| { - let mut mask = SigSet::empty(); - mask.add(SIGUSR1); - mask.thread_block().unwrap(); - - assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1)); - - let mut mask2 = SigSet::empty(); - mask2.add(SIGUSR2); - - let oldmask = mask2.thread_swap_mask(SigmaskHow::SIG_SETMASK) - .unwrap(); - - assert!(oldmask.contains(SIGUSR1)); - assert!(!oldmask.contains(SIGUSR2)); - - assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR2)); - }).join().unwrap(); - } - - #[test] - #[cfg(not(target_os = "redox"))] - fn test_sigaction() { - thread::spawn(|| { - extern fn test_sigaction_handler(_: libc::c_int) {} - extern fn test_sigaction_action(_: libc::c_int, - _: *mut libc::siginfo_t, _: *mut libc::c_void) {} - - let handler_sig = SigHandler::Handler(test_sigaction_handler); - - let flags = SaFlags::SA_ONSTACK | SaFlags::SA_RESTART | - SaFlags::SA_SIGINFO; - - let mut mask = SigSet::empty(); - mask.add(SIGUSR1); - - let action_sig = SigAction::new(handler_sig, flags, mask); - - assert_eq!(action_sig.flags(), - SaFlags::SA_ONSTACK | SaFlags::SA_RESTART); - assert_eq!(action_sig.handler(), handler_sig); - - mask = action_sig.mask(); - assert!(mask.contains(SIGUSR1)); - assert!(!mask.contains(SIGUSR2)); - - let handler_act = SigHandler::SigAction(test_sigaction_action); - let action_act = SigAction::new(handler_act, flags, mask); - assert_eq!(action_act.handler(), handler_act); - - let action_dfl = SigAction::new(SigHandler::SigDfl, flags, mask); - assert_eq!(action_dfl.handler(), SigHandler::SigDfl); - - let action_ign = SigAction::new(SigHandler::SigIgn, flags, mask); - assert_eq!(action_ign.handler(), SigHandler::SigIgn); - }).join().unwrap(); - } - - #[test] - #[cfg(not(target_os = "redox"))] - fn test_sigwait() { - thread::spawn(|| { - let mut mask = SigSet::empty(); - mask.add(SIGUSR1); - mask.add(SIGUSR2); - mask.thread_block().unwrap(); - - raise(SIGUSR1).unwrap(); - assert_eq!(mask.wait().unwrap(), SIGUSR1); - }).join().unwrap(); - } -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/signalfd.rs b/vendor/nix-v0.23.1-patched/src/sys/signalfd.rs deleted file mode 100644 index bc4a45224..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/signalfd.rs +++ /dev/null @@ -1,169 +0,0 @@ -//! Interface for the `signalfd` syscall. -//! -//! # Signal discarding -//! When a signal can't be delivered to a process (or thread), it will become a pending signal. -//! Failure to deliver could happen if the signal is blocked by every thread in the process or if -//! the signal handler is still handling a previous signal. -//! -//! If a signal is sent to a process (or thread) that already has a pending signal of the same -//! type, it will be discarded. This means that if signals of the same type are received faster than -//! they are processed, some of those signals will be dropped. Because of this limitation, -//! `signalfd` in itself cannot be used for reliable communication between processes or threads. -//! -//! Once the signal is unblocked, or the signal handler is finished, and a signal is still pending -//! (ie. not consumed from a signalfd) it will be delivered to the signal handler. -//! -//! Please note that signal discarding is not specific to `signalfd`, but also happens with regular -//! signal handlers. -use crate::unistd; -use crate::Result; -use crate::errno::Errno; -pub use crate::sys::signal::{self, SigSet}; -pub use libc::signalfd_siginfo as siginfo; - -use std::os::unix::io::{RawFd, AsRawFd}; -use std::mem; - - -libc_bitflags!{ - pub struct SfdFlags: libc::c_int { - SFD_NONBLOCK; - SFD_CLOEXEC; - } -} - -pub const SIGNALFD_NEW: RawFd = -1; -#[deprecated(since = "0.23.0", note = "use mem::size_of::() instead")] -pub const SIGNALFD_SIGINFO_SIZE: usize = mem::size_of::(); - -/// Creates a new file descriptor for reading signals. -/// -/// **Important:** please read the module level documentation about signal discarding before using -/// this function! -/// -/// The `mask` parameter specifies the set of signals that can be accepted via this file descriptor. -/// -/// A signal must be blocked on every thread in a process, otherwise it won't be visible from -/// signalfd (the default handler will be invoked instead). -/// -/// See [the signalfd man page for more information](https://man7.org/linux/man-pages/man2/signalfd.2.html) -pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result { - unsafe { - Errno::result(libc::signalfd(fd as libc::c_int, mask.as_ref(), flags.bits())) - } -} - -/// A helper struct for creating, reading and closing a `signalfd` instance. -/// -/// **Important:** please read the module level documentation about signal discarding before using -/// this struct! -/// -/// # Examples -/// -/// ``` -/// # use nix::sys::signalfd::*; -/// // Set the thread to block the SIGUSR1 signal, otherwise the default handler will be used -/// let mut mask = SigSet::empty(); -/// mask.add(signal::SIGUSR1); -/// mask.thread_block().unwrap(); -/// -/// // Signals are queued up on the file descriptor -/// let mut sfd = SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap(); -/// -/// match sfd.read_signal() { -/// // we caught a signal -/// Ok(Some(sig)) => (), -/// // there were no signals waiting (only happens when the SFD_NONBLOCK flag is set, -/// // otherwise the read_signal call blocks) -/// Ok(None) => (), -/// Err(err) => (), // some error happend -/// } -/// ``` -#[derive(Debug, Eq, Hash, PartialEq)] -pub struct SignalFd(RawFd); - -impl SignalFd { - pub fn new(mask: &SigSet) -> Result { - Self::with_flags(mask, SfdFlags::empty()) - } - - pub fn with_flags(mask: &SigSet, flags: SfdFlags) -> Result { - let fd = signalfd(SIGNALFD_NEW, mask, flags)?; - - Ok(SignalFd(fd)) - } - - pub fn set_mask(&mut self, mask: &SigSet) -> Result<()> { - signalfd(self.0, mask, SfdFlags::empty()).map(drop) - } - - pub fn read_signal(&mut self) -> Result> { - let mut buffer = mem::MaybeUninit::::uninit(); - - let size = mem::size_of_val(&buffer); - let res = Errno::result(unsafe { - libc::read(self.0, buffer.as_mut_ptr() as *mut libc::c_void, size) - }).map(|r| r as usize); - match res { - Ok(x) if x == size => Ok(Some(unsafe { buffer.assume_init() })), - Ok(_) => unreachable!("partial read on signalfd"), - Err(Errno::EAGAIN) => Ok(None), - Err(error) => Err(error) - } - } -} - -impl Drop for SignalFd { - fn drop(&mut self) { - let e = unistd::close(self.0); - if !std::thread::panicking() && e == Err(Errno::EBADF) { - panic!("Closing an invalid file descriptor!"); - }; - } -} - -impl AsRawFd for SignalFd { - fn as_raw_fd(&self) -> RawFd { - self.0 - } -} - -impl Iterator for SignalFd { - type Item = siginfo; - - fn next(&mut self) -> Option { - match self.read_signal() { - Ok(Some(sig)) => Some(sig), - Ok(None) | Err(_) => None, - } - } -} - - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn create_signalfd() { - let mask = SigSet::empty(); - let fd = SignalFd::new(&mask); - assert!(fd.is_ok()); - } - - #[test] - fn create_signalfd_with_opts() { - let mask = SigSet::empty(); - let fd = SignalFd::with_flags(&mask, SfdFlags::SFD_CLOEXEC | SfdFlags::SFD_NONBLOCK); - assert!(fd.is_ok()); - } - - #[test] - fn read_empty_signalfd() { - let mask = SigSet::empty(); - let mut fd = SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap(); - - let res = fd.read_signal(); - assert!(res.unwrap().is_none()); - } -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/socket/addr.rs b/vendor/nix-v0.23.1-patched/src/sys/socket/addr.rs deleted file mode 100644 index b119642b3..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/socket/addr.rs +++ /dev/null @@ -1,1447 +0,0 @@ -use super::sa_family_t; -use crate::{Result, NixPath}; -use crate::errno::Errno; -use memoffset::offset_of; -use std::{fmt, mem, net, ptr, slice}; -use std::ffi::OsStr; -use std::hash::{Hash, Hasher}; -use std::path::Path; -use std::os::unix::ffi::OsStrExt; -#[cfg(any(target_os = "android", target_os = "linux"))] -use crate::sys::socket::addr::netlink::NetlinkAddr; -#[cfg(any(target_os = "android", target_os = "linux"))] -use crate::sys::socket::addr::alg::AlgAddr; -#[cfg(any(target_os = "ios", target_os = "macos"))] -use std::os::unix::io::RawFd; -#[cfg(any(target_os = "ios", target_os = "macos"))] -use crate::sys::socket::addr::sys_control::SysControlAddr; -#[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "illumos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "fuchsia"))] -pub use self::datalink::LinkAddr; -#[cfg(any(target_os = "android", target_os = "linux"))] -pub use self::vsock::VsockAddr; - -/// These constants specify the protocol family to be used -/// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html) -#[repr(i32)] -#[non_exhaustive] -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] -pub enum AddressFamily { - /// Local communication (see [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html)) - Unix = libc::AF_UNIX, - /// IPv4 Internet protocols (see [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html)) - Inet = libc::AF_INET, - /// IPv6 Internet protocols (see [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html)) - Inet6 = libc::AF_INET6, - /// Kernel user interface device (see [`netlink(7)`](https://man7.org/linux/man-pages/man7/netlink.7.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - Netlink = libc::AF_NETLINK, - /// Low level packet interface (see [`packet(7)`](https://man7.org/linux/man-pages/man7/packet.7.html)) - #[cfg(any(target_os = "android", - target_os = "linux", - target_os = "illumos", - target_os = "fuchsia", - target_os = "solaris"))] - Packet = libc::AF_PACKET, - /// KEXT Controls and Notifications - #[cfg(any(target_os = "ios", target_os = "macos"))] - System = libc::AF_SYSTEM, - /// Amateur radio AX.25 protocol - #[cfg(any(target_os = "android", target_os = "linux"))] - Ax25 = libc::AF_AX25, - /// IPX - Novell protocols - Ipx = libc::AF_IPX, - /// AppleTalk - AppleTalk = libc::AF_APPLETALK, - #[cfg(any(target_os = "android", target_os = "linux"))] - NetRom = libc::AF_NETROM, - #[cfg(any(target_os = "android", target_os = "linux"))] - Bridge = libc::AF_BRIDGE, - /// Access to raw ATM PVCs - #[cfg(any(target_os = "android", target_os = "linux"))] - AtmPvc = libc::AF_ATMPVC, - /// ITU-T X.25 / ISO-8208 protocol (see [`x25(7)`](https://man7.org/linux/man-pages/man7/x25.7.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - X25 = libc::AF_X25, - #[cfg(any(target_os = "android", target_os = "linux"))] - Rose = libc::AF_ROSE, - Decnet = libc::AF_DECnet, - #[cfg(any(target_os = "android", target_os = "linux"))] - NetBeui = libc::AF_NETBEUI, - #[cfg(any(target_os = "android", target_os = "linux"))] - Security = libc::AF_SECURITY, - #[cfg(any(target_os = "android", target_os = "linux"))] - Key = libc::AF_KEY, - #[cfg(any(target_os = "android", target_os = "linux"))] - Ash = libc::AF_ASH, - #[cfg(any(target_os = "android", target_os = "linux"))] - Econet = libc::AF_ECONET, - #[cfg(any(target_os = "android", target_os = "linux"))] - AtmSvc = libc::AF_ATMSVC, - #[cfg(any(target_os = "android", target_os = "linux"))] - Rds = libc::AF_RDS, - Sna = libc::AF_SNA, - #[cfg(any(target_os = "android", target_os = "linux"))] - Irda = libc::AF_IRDA, - #[cfg(any(target_os = "android", target_os = "linux"))] - Pppox = libc::AF_PPPOX, - #[cfg(any(target_os = "android", target_os = "linux"))] - Wanpipe = libc::AF_WANPIPE, - #[cfg(any(target_os = "android", target_os = "linux"))] - Llc = libc::AF_LLC, - #[cfg(target_os = "linux")] - Ib = libc::AF_IB, - #[cfg(target_os = "linux")] - Mpls = libc::AF_MPLS, - #[cfg(any(target_os = "android", target_os = "linux"))] - Can = libc::AF_CAN, - #[cfg(any(target_os = "android", target_os = "linux"))] - Tipc = libc::AF_TIPC, - #[cfg(not(any(target_os = "illumos", - target_os = "ios", - target_os = "macos", - target_os = "solaris")))] - Bluetooth = libc::AF_BLUETOOTH, - #[cfg(any(target_os = "android", target_os = "linux"))] - Iucv = libc::AF_IUCV, - #[cfg(any(target_os = "android", target_os = "linux"))] - RxRpc = libc::AF_RXRPC, - #[cfg(not(any(target_os = "illumos", target_os = "solaris")))] - Isdn = libc::AF_ISDN, - #[cfg(any(target_os = "android", target_os = "linux"))] - Phonet = libc::AF_PHONET, - #[cfg(any(target_os = "android", target_os = "linux"))] - Ieee802154 = libc::AF_IEEE802154, - #[cfg(any(target_os = "android", target_os = "linux"))] - Caif = libc::AF_CAIF, - /// Interface to kernel crypto API - #[cfg(any(target_os = "android", target_os = "linux"))] - Alg = libc::AF_ALG, - #[cfg(target_os = "linux")] - Nfc = libc::AF_NFC, - #[cfg(any(target_os = "android", target_os = "linux"))] - Vsock = libc::AF_VSOCK, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - ImpLink = libc::AF_IMPLINK, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - Pup = libc::AF_PUP, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - Chaos = libc::AF_CHAOS, - #[cfg(any(target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - Ns = libc::AF_NS, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - Iso = libc::AF_ISO, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - Datakit = libc::AF_DATAKIT, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - Ccitt = libc::AF_CCITT, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - Dli = libc::AF_DLI, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - Lat = libc::AF_LAT, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - Hylink = libc::AF_HYLINK, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "illumos", - target_os = "netbsd", - target_os = "openbsd"))] - Link = libc::AF_LINK, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - Coip = libc::AF_COIP, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - Cnt = libc::AF_CNT, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - Natm = libc::AF_NATM, - /// Unspecified address family, (see [`getaddrinfo(3)`](https://man7.org/linux/man-pages/man3/getaddrinfo.3.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - Unspec = libc::AF_UNSPEC, -} - -impl AddressFamily { - /// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from - /// the `sa_family` field of a `sockaddr`. - /// - /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet - /// and System. Returns None for unsupported or unknown address families. - pub const fn from_i32(family: i32) -> Option { - match family { - libc::AF_UNIX => Some(AddressFamily::Unix), - libc::AF_INET => Some(AddressFamily::Inet), - libc::AF_INET6 => Some(AddressFamily::Inet6), - #[cfg(any(target_os = "android", target_os = "linux"))] - libc::AF_NETLINK => Some(AddressFamily::Netlink), - #[cfg(any(target_os = "macos", target_os = "macos"))] - libc::AF_SYSTEM => Some(AddressFamily::System), - #[cfg(any(target_os = "android", target_os = "linux"))] - libc::AF_PACKET => Some(AddressFamily::Packet), - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "illumos", - target_os = "openbsd"))] - libc::AF_LINK => Some(AddressFamily::Link), - #[cfg(any(target_os = "android", target_os = "linux"))] - libc::AF_VSOCK => Some(AddressFamily::Vsock), - _ => None - } - } -} - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum InetAddr { - V4(libc::sockaddr_in), - V6(libc::sockaddr_in6), -} - -impl InetAddr { - #[allow(clippy::needless_update)] // It isn't needless on all OSes - pub fn from_std(std: &net::SocketAddr) -> InetAddr { - match *std { - net::SocketAddr::V4(ref addr) => { - InetAddr::V4(libc::sockaddr_in { - sin_family: AddressFamily::Inet as sa_family_t, - sin_port: addr.port().to_be(), // network byte order - sin_addr: Ipv4Addr::from_std(addr.ip()).0, - .. unsafe { mem::zeroed() } - }) - } - net::SocketAddr::V6(ref addr) => { - InetAddr::V6(libc::sockaddr_in6 { - sin6_family: AddressFamily::Inet6 as sa_family_t, - sin6_port: addr.port().to_be(), // network byte order - sin6_addr: Ipv6Addr::from_std(addr.ip()).0, - sin6_flowinfo: addr.flowinfo(), // host byte order - sin6_scope_id: addr.scope_id(), // host byte order - .. unsafe { mem::zeroed() } - }) - } - } - } - - #[allow(clippy::needless_update)] // It isn't needless on all OSes - pub fn new(ip: IpAddr, port: u16) -> InetAddr { - match ip { - IpAddr::V4(ref ip) => { - InetAddr::V4(libc::sockaddr_in { - sin_family: AddressFamily::Inet as sa_family_t, - sin_port: port.to_be(), - sin_addr: ip.0, - .. unsafe { mem::zeroed() } - }) - } - IpAddr::V6(ref ip) => { - InetAddr::V6(libc::sockaddr_in6 { - sin6_family: AddressFamily::Inet6 as sa_family_t, - sin6_port: port.to_be(), - sin6_addr: ip.0, - .. unsafe { mem::zeroed() } - }) - } - } - } - /// Gets the IP address associated with this socket address. - pub const fn ip(&self) -> IpAddr { - match *self { - InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)), - InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)), - } - } - - /// Gets the port number associated with this socket address - pub const fn port(&self) -> u16 { - match *self { - InetAddr::V6(ref sa) => u16::from_be(sa.sin6_port), - InetAddr::V4(ref sa) => u16::from_be(sa.sin_port), - } - } - - pub fn to_std(&self) -> net::SocketAddr { - match *self { - InetAddr::V4(ref sa) => net::SocketAddr::V4( - net::SocketAddrV4::new( - Ipv4Addr(sa.sin_addr).to_std(), - self.port())), - InetAddr::V6(ref sa) => net::SocketAddr::V6( - net::SocketAddrV6::new( - Ipv6Addr(sa.sin6_addr).to_std(), - self.port(), - sa.sin6_flowinfo, - sa.sin6_scope_id)), - } - } - - #[deprecated(since = "0.23.0", note = "use .to_string() instead")] - pub fn to_str(&self) -> String { - format!("{}", self) - } -} - -impl fmt::Display for InetAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - InetAddr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()), - InetAddr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()), - } - } -} - -/* - * - * ===== IpAddr ===== - * - */ -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum IpAddr { - V4(Ipv4Addr), - V6(Ipv6Addr), -} - -impl IpAddr { - /// Create a new IpAddr that contains an IPv4 address. - /// - /// The result will represent the IP address a.b.c.d - pub const fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr { - IpAddr::V4(Ipv4Addr::new(a, b, c, d)) - } - - /// Create a new IpAddr that contains an IPv6 address. - /// - /// The result will represent the IP address a:b:c:d:e:f - #[allow(clippy::many_single_char_names)] - #[allow(clippy::too_many_arguments)] - pub const fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr { - IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h)) - } - - pub fn from_std(std: &net::IpAddr) -> IpAddr { - match *std { - net::IpAddr::V4(ref std) => IpAddr::V4(Ipv4Addr::from_std(std)), - net::IpAddr::V6(ref std) => IpAddr::V6(Ipv6Addr::from_std(std)), - } - } - - pub const fn to_std(&self) -> net::IpAddr { - match *self { - IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()), - IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()), - } - } -} - -impl fmt::Display for IpAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - IpAddr::V4(ref v4) => v4.fmt(f), - IpAddr::V6(ref v6) => v6.fmt(f) - } - } -} - -/* - * - * ===== Ipv4Addr ===== - * - */ - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct Ipv4Addr(pub libc::in_addr); - -impl Ipv4Addr { - #[allow(clippy::identity_op)] // More readable this way - pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { - let ip = (((a as u32) << 24) | - ((b as u32) << 16) | - ((c as u32) << 8) | - ((d as u32) << 0)).to_be(); - - Ipv4Addr(libc::in_addr { s_addr: ip }) - } - - // Use pass by reference for symmetry with Ipv6Addr::from_std - #[allow(clippy::trivially_copy_pass_by_ref)] - pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr { - let bits = std.octets(); - Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3]) - } - - pub const fn any() -> Ipv4Addr { - Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY }) - } - - pub const fn octets(self) -> [u8; 4] { - let bits = u32::from_be(self.0.s_addr); - [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8] - } - - pub const fn to_std(self) -> net::Ipv4Addr { - let bits = self.octets(); - net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3]) - } -} - -impl fmt::Display for Ipv4Addr { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let octets = self.octets(); - write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]) - } -} - -/* - * - * ===== Ipv6Addr ===== - * - */ - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct Ipv6Addr(pub libc::in6_addr); - -// Note that IPv6 addresses are stored in big endian order on all architectures. -// See https://tools.ietf.org/html/rfc1700 or consult your favorite search -// engine. - -macro_rules! to_u8_array { - ($($num:ident),*) => { - [ $(($num>>8) as u8, ($num&0xff) as u8,)* ] - } -} - -macro_rules! to_u16_array { - ($slf:ident, $($first:expr, $second:expr),*) => { - [$( (($slf.0.s6_addr[$first] as u16) << 8) + $slf.0.s6_addr[$second] as u16,)*] - } -} - -impl Ipv6Addr { - #[allow(clippy::many_single_char_names)] - #[allow(clippy::too_many_arguments)] - pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { - Ipv6Addr(libc::in6_addr{s6_addr: to_u8_array!(a,b,c,d,e,f,g,h)}) - } - - pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr { - let s = std.segments(); - Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]) - } - - /// Return the eight 16-bit segments that make up this address - pub const fn segments(&self) -> [u16; 8] { - to_u16_array!(self, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15) - } - - pub const fn to_std(&self) -> net::Ipv6Addr { - let s = self.segments(); - net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7]) - } -} - -impl fmt::Display for Ipv6Addr { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - self.to_std().fmt(fmt) - } -} - -/// A wrapper around `sockaddr_un`. -#[derive(Clone, Copy, Debug)] -pub struct UnixAddr { - // INVARIANT: sun & path_len are valid as defined by docs for from_raw_parts - sun: libc::sockaddr_un, - path_len: usize, -} - -// linux man page unix(7) says there are 3 kinds of unix socket: -// pathname: addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1 -// unnamed: addrlen = sizeof(sa_family_t) -// abstract: addren > sizeof(sa_family_t), name = sun_path[..(addrlen - sizeof(sa_family_t))] -// -// what we call path_len = addrlen - offsetof(struct sockaddr_un, sun_path) -#[derive(PartialEq, Eq, Hash)] -enum UnixAddrKind<'a> { - Pathname(&'a Path), - Unnamed, - #[cfg(any(target_os = "android", target_os = "linux"))] - Abstract(&'a [u8]), -} -impl<'a> UnixAddrKind<'a> { - /// Safety: sun & path_len must be valid - unsafe fn get(sun: &'a libc::sockaddr_un, path_len: usize) -> Self { - if path_len == 0 { - return Self::Unnamed; - } - #[cfg(any(target_os = "android", target_os = "linux"))] - if sun.sun_path[0] == 0 { - let name = - slice::from_raw_parts(sun.sun_path.as_ptr().add(1) as *const u8, path_len - 1); - return Self::Abstract(name); - } - let pathname = slice::from_raw_parts(sun.sun_path.as_ptr() as *const u8, path_len - 1); - Self::Pathname(Path::new(OsStr::from_bytes(pathname))) - } -} - -impl UnixAddr { - /// Create a new sockaddr_un representing a filesystem path. - pub fn new(path: &P) -> Result { - path.with_nix_path(|cstr| { - unsafe { - let mut ret = libc::sockaddr_un { - sun_family: AddressFamily::Unix as sa_family_t, - .. mem::zeroed() - }; - - let bytes = cstr.to_bytes(); - - if bytes.len() >= ret.sun_path.len() { - return Err(Errno::ENAMETOOLONG); - } - - ptr::copy_nonoverlapping(bytes.as_ptr(), - ret.sun_path.as_mut_ptr() as *mut u8, - bytes.len()); - - Ok(UnixAddr::from_raw_parts(ret, bytes.len() + 1)) - } - })? - } - - /// Create a new `sockaddr_un` representing an address in the "abstract namespace". - /// - /// The leading null byte for the abstract namespace is automatically added; - /// thus the input `path` is expected to be the bare name, not null-prefixed. - /// This is a Linux-specific extension, primarily used to allow chrooted - /// processes to communicate with processes having a different filesystem view. - #[cfg(any(target_os = "android", target_os = "linux"))] - pub fn new_abstract(path: &[u8]) -> Result { - unsafe { - let mut ret = libc::sockaddr_un { - sun_family: AddressFamily::Unix as sa_family_t, - .. mem::zeroed() - }; - - if path.len() >= ret.sun_path.len() { - return Err(Errno::ENAMETOOLONG); - } - - // Abstract addresses are represented by sun_path[0] == - // b'\0', so copy starting one byte in. - ptr::copy_nonoverlapping(path.as_ptr(), - ret.sun_path.as_mut_ptr().offset(1) as *mut u8, - path.len()); - - Ok(UnixAddr::from_raw_parts(ret, path.len() + 1)) - } - } - - /// Create a UnixAddr from a raw `sockaddr_un` struct and a size. `path_len` is the "addrlen" - /// of this address, but minus `offsetof(struct sockaddr_un, sun_path)`. Basically the length - /// of the data in `sun_path`. - /// - /// # Safety - /// This pair of sockaddr_un & path_len must be a valid unix addr, which means: - /// - path_len <= sockaddr_un.sun_path.len() - /// - if this is a unix addr with a pathname, sun.sun_path is a nul-terminated fs path and - /// sun.sun_path[path_len - 1] == 0 || sun.sun_path[path_len] == 0 - pub(crate) unsafe fn from_raw_parts(sun: libc::sockaddr_un, mut path_len: usize) -> UnixAddr { - if let UnixAddrKind::Pathname(_) = UnixAddrKind::get(&sun, path_len) { - if sun.sun_path[path_len - 1] != 0 { - assert_eq!(sun.sun_path[path_len], 0); - path_len += 1 - } - } - UnixAddr { sun, path_len } - } - - fn kind(&self) -> UnixAddrKind<'_> { - // SAFETY: our sockaddr is always valid because of the invariant on the struct - unsafe { UnixAddrKind::get(&self.sun, self.path_len) } - } - - /// If this address represents a filesystem path, return that path. - pub fn path(&self) -> Option<&Path> { - match self.kind() { - UnixAddrKind::Pathname(path) => Some(path), - _ => None, - } - } - - /// If this address represents an abstract socket, return its name. - /// - /// For abstract sockets only the bare name is returned, without the - /// leading null byte. `None` is returned for unnamed or path-backed sockets. - #[cfg(any(target_os = "android", target_os = "linux"))] - pub fn as_abstract(&self) -> Option<&[u8]> { - match self.kind() { - UnixAddrKind::Abstract(name) => Some(name), - _ => None, - } - } - - /// Returns the addrlen of this socket - `offsetof(struct sockaddr_un, sun_path)` - #[inline] - pub fn path_len(&self) -> usize { - self.path_len - } - /// Returns a pointer to the raw `sockaddr_un` struct - #[inline] - pub fn as_ptr(&self) -> *const libc::sockaddr_un { - &self.sun - } - /// Returns a mutable pointer to the raw `sockaddr_un` struct - #[inline] - pub fn as_mut_ptr(&mut self) -> *mut libc::sockaddr_un { - &mut self.sun - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result { - use fmt::Write; - f.write_str("@\"")?; - for &b in abs { - use fmt::Display; - char::from(b).escape_default().fmt(f)?; - } - f.write_char('"')?; - Ok(()) -} - -impl fmt::Display for UnixAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.kind() { - UnixAddrKind::Pathname(path) => path.display().fmt(f), - UnixAddrKind::Unnamed => f.pad(""), - #[cfg(any(target_os = "android", target_os = "linux"))] - UnixAddrKind::Abstract(name) => fmt_abstract(name, f), - } - } -} - -impl PartialEq for UnixAddr { - fn eq(&self, other: &UnixAddr) -> bool { - self.kind() == other.kind() - } -} - -impl Eq for UnixAddr {} - -impl Hash for UnixAddr { - fn hash(&self, s: &mut H) { - self.kind().hash(s) - } -} - -/// Represents a socket address -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -#[non_exhaustive] -pub enum SockAddr { - Inet(InetAddr), - Unix(UnixAddr), - #[cfg(any(target_os = "android", target_os = "linux"))] - Netlink(NetlinkAddr), - #[cfg(any(target_os = "android", target_os = "linux"))] - Alg(AlgAddr), - #[cfg(any(target_os = "ios", target_os = "macos"))] - SysControl(SysControlAddr), - /// Datalink address (MAC) - #[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "illumos", - target_os = "netbsd", - target_os = "openbsd"))] - Link(LinkAddr), - #[cfg(any(target_os = "android", target_os = "linux"))] - Vsock(VsockAddr), -} - -impl SockAddr { - pub fn new_inet(addr: InetAddr) -> SockAddr { - SockAddr::Inet(addr) - } - - pub fn new_unix(path: &P) -> Result { - Ok(SockAddr::Unix(UnixAddr::new(path)?)) - } - - #[cfg(any(target_os = "android", target_os = "linux"))] - pub fn new_netlink(pid: u32, groups: u32) -> SockAddr { - SockAddr::Netlink(NetlinkAddr::new(pid, groups)) - } - - #[cfg(any(target_os = "android", target_os = "linux"))] - pub fn new_alg(alg_type: &str, alg_name: &str) -> SockAddr { - SockAddr::Alg(AlgAddr::new(alg_type, alg_name)) - } - - #[cfg(any(target_os = "ios", target_os = "macos"))] - pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result { - SysControlAddr::from_name(sockfd, name, unit).map(SockAddr::SysControl) - } - - #[cfg(any(target_os = "android", target_os = "linux"))] - pub fn new_vsock(cid: u32, port: u32) -> SockAddr { - SockAddr::Vsock(VsockAddr::new(cid, port)) - } - - pub fn family(&self) -> AddressFamily { - match *self { - SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet, - SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6, - SockAddr::Unix(..) => AddressFamily::Unix, - #[cfg(any(target_os = "android", target_os = "linux"))] - SockAddr::Netlink(..) => AddressFamily::Netlink, - #[cfg(any(target_os = "android", target_os = "linux"))] - SockAddr::Alg(..) => AddressFamily::Alg, - #[cfg(any(target_os = "ios", target_os = "macos"))] - SockAddr::SysControl(..) => AddressFamily::System, - #[cfg(any(target_os = "android", target_os = "linux"))] - SockAddr::Link(..) => AddressFamily::Packet, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "illumos", - target_os = "openbsd"))] - SockAddr::Link(..) => AddressFamily::Link, - #[cfg(any(target_os = "android", target_os = "linux"))] - SockAddr::Vsock(..) => AddressFamily::Vsock, - } - } - - #[deprecated(since = "0.23.0", note = "use .to_string() instead")] - pub fn to_str(&self) -> String { - format!("{}", self) - } - - /// Creates a `SockAddr` struct from libc's sockaddr. - /// - /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System. - /// Returns None for unsupported families. - /// - /// # Safety - /// - /// unsafe because it takes a raw pointer as argument. The caller must - /// ensure that the pointer is valid. - #[cfg(not(target_os = "fuchsia"))] - pub(crate) unsafe fn from_libc_sockaddr(addr: *const libc::sockaddr) -> Option { - if addr.is_null() { - None - } else { - match AddressFamily::from_i32(i32::from((*addr).sa_family)) { - Some(AddressFamily::Unix) => None, - Some(AddressFamily::Inet) => Some(SockAddr::Inet( - InetAddr::V4(*(addr as *const libc::sockaddr_in)))), - Some(AddressFamily::Inet6) => Some(SockAddr::Inet( - InetAddr::V6(*(addr as *const libc::sockaddr_in6)))), - #[cfg(any(target_os = "android", target_os = "linux"))] - Some(AddressFamily::Netlink) => Some(SockAddr::Netlink( - NetlinkAddr(*(addr as *const libc::sockaddr_nl)))), - #[cfg(any(target_os = "ios", target_os = "macos"))] - Some(AddressFamily::System) => Some(SockAddr::SysControl( - SysControlAddr(*(addr as *const libc::sockaddr_ctl)))), - #[cfg(any(target_os = "android", target_os = "linux"))] - Some(AddressFamily::Packet) => Some(SockAddr::Link( - LinkAddr(*(addr as *const libc::sockaddr_ll)))), - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "illumos", - target_os = "openbsd"))] - Some(AddressFamily::Link) => { - let ether_addr = LinkAddr(*(addr as *const libc::sockaddr_dl)); - if ether_addr.is_empty() { - None - } else { - Some(SockAddr::Link(ether_addr)) - } - }, - #[cfg(any(target_os = "android", target_os = "linux"))] - Some(AddressFamily::Vsock) => Some(SockAddr::Vsock( - VsockAddr(*(addr as *const libc::sockaddr_vm)))), - // Other address families are currently not supported and simply yield a None - // entry instead of a proper conversion to a `SockAddr`. - Some(_) | None => None, - } - } - } - - /// Conversion from nix's SockAddr type to the underlying libc sockaddr type. - /// - /// This is useful for interfacing with other libc functions that don't yet have nix wrappers. - /// Returns a reference to the underlying data type (as a sockaddr reference) along - /// with the size of the actual data type. sockaddr is commonly used as a proxy for - /// a superclass as C doesn't support inheritance, so many functions that take - /// a sockaddr * need to take the size of the underlying type as well and then internally cast it back. - pub fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) { - match *self { - SockAddr::Inet(InetAddr::V4(ref addr)) => ( - // This cast is always allowed in C - unsafe { - &*(addr as *const libc::sockaddr_in as *const libc::sockaddr) - }, - mem::size_of_val(addr) as libc::socklen_t - ), - SockAddr::Inet(InetAddr::V6(ref addr)) => ( - // This cast is always allowed in C - unsafe { - &*(addr as *const libc::sockaddr_in6 as *const libc::sockaddr) - }, - mem::size_of_val(addr) as libc::socklen_t - ), - SockAddr::Unix(UnixAddr { ref sun, path_len }) => ( - // This cast is always allowed in C - unsafe { - &*(sun as *const libc::sockaddr_un as *const libc::sockaddr) - }, - (path_len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t - ), - #[cfg(any(target_os = "android", target_os = "linux"))] - SockAddr::Netlink(NetlinkAddr(ref sa)) => ( - // This cast is always allowed in C - unsafe { - &*(sa as *const libc::sockaddr_nl as *const libc::sockaddr) - }, - mem::size_of_val(sa) as libc::socklen_t - ), - #[cfg(any(target_os = "android", target_os = "linux"))] - SockAddr::Alg(AlgAddr(ref sa)) => ( - // This cast is always allowed in C - unsafe { - &*(sa as *const libc::sockaddr_alg as *const libc::sockaddr) - }, - mem::size_of_val(sa) as libc::socklen_t - ), - #[cfg(any(target_os = "ios", target_os = "macos"))] - SockAddr::SysControl(SysControlAddr(ref sa)) => ( - // This cast is always allowed in C - unsafe { - &*(sa as *const libc::sockaddr_ctl as *const libc::sockaddr) - }, - mem::size_of_val(sa) as libc::socklen_t - - ), - #[cfg(any(target_os = "android", target_os = "linux"))] - SockAddr::Link(LinkAddr(ref addr)) => ( - // This cast is always allowed in C - unsafe { - &*(addr as *const libc::sockaddr_ll as *const libc::sockaddr) - }, - mem::size_of_val(addr) as libc::socklen_t - ), - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "illumos", - target_os = "netbsd", - target_os = "openbsd"))] - SockAddr::Link(LinkAddr(ref addr)) => ( - // This cast is always allowed in C - unsafe { - &*(addr as *const libc::sockaddr_dl as *const libc::sockaddr) - }, - mem::size_of_val(addr) as libc::socklen_t - ), - #[cfg(any(target_os = "android", target_os = "linux"))] - SockAddr::Vsock(VsockAddr(ref sa)) => ( - // This cast is always allowed in C - unsafe { - &*(sa as *const libc::sockaddr_vm as *const libc::sockaddr) - }, - mem::size_of_val(sa) as libc::socklen_t - ), - } - } -} - -impl fmt::Display for SockAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - SockAddr::Inet(ref inet) => inet.fmt(f), - SockAddr::Unix(ref unix) => unix.fmt(f), - #[cfg(any(target_os = "android", target_os = "linux"))] - SockAddr::Netlink(ref nl) => nl.fmt(f), - #[cfg(any(target_os = "android", target_os = "linux"))] - SockAddr::Alg(ref nl) => nl.fmt(f), - #[cfg(any(target_os = "ios", target_os = "macos"))] - SockAddr::SysControl(ref sc) => sc.fmt(f), - #[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "illumos", - target_os = "openbsd"))] - SockAddr::Link(ref ether_addr) => ether_addr.fmt(f), - #[cfg(any(target_os = "android", target_os = "linux"))] - SockAddr::Vsock(ref svm) => svm.fmt(f), - } - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -pub mod netlink { - use crate::sys::socket::addr::AddressFamily; - use libc::{sa_family_t, sockaddr_nl}; - use std::{fmt, mem}; - - #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] - pub struct NetlinkAddr(pub sockaddr_nl); - - impl NetlinkAddr { - pub fn new(pid: u32, groups: u32) -> NetlinkAddr { - let mut addr: sockaddr_nl = unsafe { mem::zeroed() }; - addr.nl_family = AddressFamily::Netlink as sa_family_t; - addr.nl_pid = pid; - addr.nl_groups = groups; - - NetlinkAddr(addr) - } - - pub const fn pid(&self) -> u32 { - self.0.nl_pid - } - - pub const fn groups(&self) -> u32 { - self.0.nl_groups - } - } - - impl fmt::Display for NetlinkAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "pid: {} groups: {}", self.pid(), self.groups()) - } - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -pub mod alg { - use libc::{AF_ALG, sockaddr_alg, c_char}; - use std::{fmt, mem, str}; - use std::hash::{Hash, Hasher}; - use std::ffi::CStr; - - #[derive(Copy, Clone)] - pub struct AlgAddr(pub sockaddr_alg); - - // , PartialEq, Eq, Debug, Hash - impl PartialEq for AlgAddr { - fn eq(&self, other: &Self) -> bool { - let (inner, other) = (self.0, other.0); - (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]) == - (other.salg_family, &other.salg_type[..], other.salg_feat, other.salg_mask, &other.salg_name[..]) - } - } - - impl Eq for AlgAddr {} - - impl Hash for AlgAddr { - fn hash(&self, s: &mut H) { - let inner = self.0; - (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]).hash(s); - } - } - - impl AlgAddr { - pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr { - let mut addr: sockaddr_alg = unsafe { mem::zeroed() }; - addr.salg_family = AF_ALG as u16; - addr.salg_type[..alg_type.len()].copy_from_slice(alg_type.to_string().as_bytes()); - addr.salg_name[..alg_name.len()].copy_from_slice(alg_name.to_string().as_bytes()); - - AlgAddr(addr) - } - - - pub fn alg_type(&self) -> &CStr { - unsafe { CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char) } - } - - pub fn alg_name(&self) -> &CStr { - unsafe { CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char) } - } - } - - impl fmt::Display for AlgAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "type: {} alg: {}", - self.alg_name().to_string_lossy(), - self.alg_type().to_string_lossy()) - } - } - - impl fmt::Debug for AlgAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } - } -} - -#[cfg(any(target_os = "ios", target_os = "macos"))] -pub mod sys_control { - use crate::sys::socket::addr::AddressFamily; - use libc::{self, c_uchar}; - use std::{fmt, mem}; - use std::os::unix::io::RawFd; - use crate::{Errno, Result}; - - // FIXME: Move type into `libc` - #[repr(C)] - #[derive(Clone, Copy)] - #[allow(missing_debug_implementations)] - pub struct ctl_ioc_info { - pub ctl_id: u32, - pub ctl_name: [c_uchar; MAX_KCTL_NAME], - } - - const CTL_IOC_MAGIC: u8 = b'N'; - const CTL_IOC_INFO: u8 = 3; - const MAX_KCTL_NAME: usize = 96; - - ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info); - - #[repr(C)] - #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] - pub struct SysControlAddr(pub libc::sockaddr_ctl); - - impl SysControlAddr { - pub const fn new(id: u32, unit: u32) -> SysControlAddr { - let addr = libc::sockaddr_ctl { - sc_len: mem::size_of::() as c_uchar, - sc_family: AddressFamily::System as c_uchar, - ss_sysaddr: libc::AF_SYS_CONTROL as u16, - sc_id: id, - sc_unit: unit, - sc_reserved: [0; 5] - }; - - SysControlAddr(addr) - } - - pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result { - if name.len() > MAX_KCTL_NAME { - return Err(Errno::ENAMETOOLONG); - } - - let mut ctl_name = [0; MAX_KCTL_NAME]; - ctl_name[..name.len()].clone_from_slice(name.as_bytes()); - let mut info = ctl_ioc_info { ctl_id: 0, ctl_name }; - - unsafe { ctl_info(sockfd, &mut info)?; } - - Ok(SysControlAddr::new(info.ctl_id, unit)) - } - - pub const fn id(&self) -> u32 { - self.0.sc_id - } - - pub const fn unit(&self) -> u32 { - self.0.sc_unit - } - } - - impl fmt::Display for SysControlAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(self, f) - } - } -} - - -#[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))] -mod datalink { - use super::{fmt, AddressFamily}; - - /// Hardware Address - #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] - pub struct LinkAddr(pub libc::sockaddr_ll); - - impl LinkAddr { - /// Always AF_PACKET - pub fn family(&self) -> AddressFamily { - assert_eq!(self.0.sll_family as i32, libc::AF_PACKET); - AddressFamily::Packet - } - - /// Physical-layer protocol - pub fn protocol(&self) -> u16 { - self.0.sll_protocol - } - - /// Interface number - pub fn ifindex(&self) -> usize { - self.0.sll_ifindex as usize - } - - /// ARP hardware type - pub fn hatype(&self) -> u16 { - self.0.sll_hatype - } - - /// Packet type - pub fn pkttype(&self) -> u8 { - self.0.sll_pkttype - } - - /// Length of MAC address - pub fn halen(&self) -> usize { - self.0.sll_halen as usize - } - - /// Physical-layer address (MAC) - pub fn addr(&self) -> [u8; 6] { - [ - self.0.sll_addr[0] as u8, - self.0.sll_addr[1] as u8, - self.0.sll_addr[2] as u8, - self.0.sll_addr[3] as u8, - self.0.sll_addr[4] as u8, - self.0.sll_addr[5] as u8, - ] - } - } - - impl fmt::Display for LinkAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let addr = self.addr(); - write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", - addr[0], - addr[1], - addr[2], - addr[3], - addr[4], - addr[5]) - } - } -} - -#[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "illumos", - target_os = "netbsd", - target_os = "openbsd"))] -mod datalink { - use super::{fmt, AddressFamily}; - - /// Hardware Address - #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] - pub struct LinkAddr(pub libc::sockaddr_dl); - - impl LinkAddr { - /// Total length of sockaddr - #[cfg(not(target_os = "illumos"))] - pub fn len(&self) -> usize { - self.0.sdl_len as usize - } - - /// always == AF_LINK - pub fn family(&self) -> AddressFamily { - assert_eq!(i32::from(self.0.sdl_family), libc::AF_LINK); - AddressFamily::Link - } - - /// interface index, if != 0, system given index for interface - pub fn ifindex(&self) -> usize { - self.0.sdl_index as usize - } - - /// Datalink type - pub fn datalink_type(&self) -> u8 { - self.0.sdl_type - } - - // MAC address start position - pub fn nlen(&self) -> usize { - self.0.sdl_nlen as usize - } - - /// link level address length - pub fn alen(&self) -> usize { - self.0.sdl_alen as usize - } - - /// link layer selector length - pub fn slen(&self) -> usize { - self.0.sdl_slen as usize - } - - /// if link level address length == 0, - /// or `sdl_data` not be larger. - pub fn is_empty(&self) -> bool { - let nlen = self.nlen(); - let alen = self.alen(); - let data_len = self.0.sdl_data.len(); - - alen == 0 || nlen + alen >= data_len - } - - /// Physical-layer address (MAC) - pub fn addr(&self) -> [u8; 6] { - let nlen = self.nlen(); - let data = self.0.sdl_data; - - assert!(!self.is_empty()); - - [ - data[nlen] as u8, - data[nlen + 1] as u8, - data[nlen + 2] as u8, - data[nlen + 3] as u8, - data[nlen + 4] as u8, - data[nlen + 5] as u8, - ] - } - } - - impl fmt::Display for LinkAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let addr = self.addr(); - write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", - addr[0], - addr[1], - addr[2], - addr[3], - addr[4], - addr[5]) - } - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -pub mod vsock { - use crate::sys::socket::addr::AddressFamily; - use libc::{sa_family_t, sockaddr_vm}; - use std::{fmt, mem}; - use std::hash::{Hash, Hasher}; - - #[derive(Copy, Clone)] - pub struct VsockAddr(pub sockaddr_vm); - - impl PartialEq for VsockAddr { - fn eq(&self, other: &Self) -> bool { - let (inner, other) = (self.0, other.0); - (inner.svm_family, inner.svm_cid, inner.svm_port) == - (other.svm_family, other.svm_cid, other.svm_port) - } - } - - impl Eq for VsockAddr {} - - impl Hash for VsockAddr { - fn hash(&self, s: &mut H) { - let inner = self.0; - (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s); - } - } - - /// VSOCK Address - /// - /// The address for AF_VSOCK socket is defined as a combination of a - /// 32-bit Context Identifier (CID) and a 32-bit port number. - impl VsockAddr { - pub fn new(cid: u32, port: u32) -> VsockAddr { - let mut addr: sockaddr_vm = unsafe { mem::zeroed() }; - addr.svm_family = AddressFamily::Vsock as sa_family_t; - addr.svm_cid = cid; - addr.svm_port = port; - - VsockAddr(addr) - } - - /// Context Identifier (CID) - pub fn cid(&self) -> u32 { - self.0.svm_cid - } - - /// Port number - pub fn port(&self) -> u32 { - self.0.svm_port - } - } - - impl fmt::Display for VsockAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "cid: {} port: {}", self.cid(), self.port()) - } - } - - impl fmt::Debug for VsockAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self, f) - } - } -} - -#[cfg(test)] -mod tests { - #[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "illumos", - target_os = "openbsd"))] - use super::*; - - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - #[test] - fn test_macos_loopback_datalink_addr() { - let bytes = [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0]; - let sa = bytes.as_ptr() as *const libc::sockaddr; - let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) }; - assert!(_sock_addr.is_none()); - } - - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - #[test] - fn test_macos_tap_datalink_addr() { - let bytes = [20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35, 76, -80]; - let ptr = bytes.as_ptr(); - let sa = ptr as *const libc::sockaddr; - let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) }; - - assert!(_sock_addr.is_some()); - - let sock_addr = _sock_addr.unwrap(); - - assert_eq!(sock_addr.family(), AddressFamily::Link); - - match sock_addr { - SockAddr::Link(ether_addr) => { - assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]); - }, - _ => { unreachable!() } - }; - } - - #[cfg(target_os = "illumos")] - #[test] - fn test_illumos_tap_datalink_addr() { - let bytes = [25u8, 0, 0, 0, 6, 0, 6, 0, 24, 101, 144, 221, 76, 176]; - let ptr = bytes.as_ptr(); - let sa = ptr as *const libc::sockaddr; - let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) }; - - assert!(_sock_addr.is_some()); - - let sock_addr = _sock_addr.unwrap(); - - assert_eq!(sock_addr.family(), AddressFamily::Link); - - match sock_addr { - SockAddr::Link(ether_addr) => { - assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]); - }, - _ => { unreachable!() } - }; - } - - #[cfg(any(target_os = "android", target_os = "linux"))] - #[test] - fn test_abstract_sun_path() { - let name = String::from("nix\0abstract\0test"); - let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap(); - - let sun_path1 = unsafe { &(*addr.as_ptr()).sun_path[..addr.path_len()] }; - let sun_path2 = [0, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116]; - assert_eq!(sun_path1, sun_path2); - } -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/socket/mod.rs b/vendor/nix-v0.23.1-patched/src/sys/socket/mod.rs deleted file mode 100644 index 97eea3dcb..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/socket/mod.rs +++ /dev/null @@ -1,1916 +0,0 @@ -//! Socket interface functions -//! -//! [Further reading](https://man7.org/linux/man-pages/man7/socket.7.html) -use cfg_if::cfg_if; -use crate::{Result, errno::Errno}; -use libc::{self, c_void, c_int, iovec, socklen_t, size_t, - CMSG_FIRSTHDR, CMSG_NXTHDR, CMSG_DATA, CMSG_LEN}; -use memoffset::offset_of; -use std::{mem, ptr, slice}; -use std::os::unix::io::RawFd; -#[cfg(all(target_os = "linux"))] -use crate::sys::time::TimeSpec; -use crate::sys::time::TimeVal; -use crate::sys::uio::IoVec; - -mod addr; -#[deny(missing_docs)] -pub mod sockopt; - -/* - * - * ===== Re-exports ===== - * - */ - -#[cfg(not(any(target_os = "illumos", target_os = "solaris")))] -pub use self::addr::{ - AddressFamily, - SockAddr, - InetAddr, - UnixAddr, - IpAddr, - Ipv4Addr, - Ipv6Addr, - LinkAddr, -}; -#[cfg(any(target_os = "illumos", target_os = "solaris"))] -pub use self::addr::{ - AddressFamily, - SockAddr, - InetAddr, - UnixAddr, - IpAddr, - Ipv4Addr, - Ipv6Addr, -}; - -#[cfg(any(target_os = "android", target_os = "linux"))] -pub use crate::sys::socket::addr::netlink::NetlinkAddr; -#[cfg(any(target_os = "android", target_os = "linux"))] -pub use crate::sys::socket::addr::alg::AlgAddr; -#[cfg(any(target_os = "android", target_os = "linux"))] -pub use crate::sys::socket::addr::vsock::VsockAddr; - -pub use libc::{ - cmsghdr, - msghdr, - sa_family_t, - sockaddr, - sockaddr_in, - sockaddr_in6, - sockaddr_storage, - sockaddr_un, -}; - -// Needed by the cmsg_space macro -#[doc(hidden)] -pub use libc::{c_uint, CMSG_SPACE}; - -/// These constants are used to specify the communication semantics -/// when creating a socket with [`socket()`](fn.socket.html) -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -#[repr(i32)] -#[non_exhaustive] -pub enum SockType { - /// Provides sequenced, reliable, two-way, connection- - /// based byte streams. An out-of-band data transmission - /// mechanism may be supported. - Stream = libc::SOCK_STREAM, - /// Supports datagrams (connectionless, unreliable - /// messages of a fixed maximum length). - Datagram = libc::SOCK_DGRAM, - /// Provides a sequenced, reliable, two-way connection- - /// based data transmission path for datagrams of fixed - /// maximum length; a consumer is required to read an - /// entire packet with each input system call. - SeqPacket = libc::SOCK_SEQPACKET, - /// Provides raw network protocol access. - Raw = libc::SOCK_RAW, - /// Provides a reliable datagram layer that does not - /// guarantee ordering. - Rdm = libc::SOCK_RDM, -} - -/// Constants used in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html) -/// to specify the protocol to use. -#[repr(i32)] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -#[non_exhaustive] -pub enum SockProtocol { - /// TCP protocol ([ip(7)](https://man7.org/linux/man-pages/man7/ip.7.html)) - Tcp = libc::IPPROTO_TCP, - /// UDP protocol ([ip(7)](https://man7.org/linux/man-pages/man7/ip.7.html)) - Udp = libc::IPPROTO_UDP, - /// Allows applications and other KEXTs to be notified when certain kernel events occur - /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html)) - #[cfg(any(target_os = "ios", target_os = "macos"))] - KextEvent = libc::SYSPROTO_EVENT, - /// Allows applications to configure and control a KEXT - /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html)) - #[cfg(any(target_os = "ios", target_os = "macos"))] - KextControl = libc::SYSPROTO_CONTROL, - /// Receives routing and link updates and may be used to modify the routing tables (both IPv4 and IPv6), IP addresses, link - // parameters, neighbor setups, queueing disciplines, traffic classes and packet classifiers - /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - NetlinkRoute = libc::NETLINK_ROUTE, - /// Reserved for user-mode socket protocols - /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - NetlinkUserSock = libc::NETLINK_USERSOCK, - /// Query information about sockets of various protocol families from the kernel - /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - NetlinkSockDiag = libc::NETLINK_SOCK_DIAG, - /// SELinux event notifications. - /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - NetlinkSELinux = libc::NETLINK_SELINUX, - /// Open-iSCSI - /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - NetlinkISCSI = libc::NETLINK_ISCSI, - /// Auditing - /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - NetlinkAudit = libc::NETLINK_AUDIT, - /// Access to FIB lookup from user space - /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - NetlinkFIBLookup = libc::NETLINK_FIB_LOOKUP, - /// Netfilter subsystem - /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - NetlinkNetFilter = libc::NETLINK_NETFILTER, - /// SCSI Transports - /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - NetlinkSCSITransport = libc::NETLINK_SCSITRANSPORT, - /// Infiniband RDMA - /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - NetlinkRDMA = libc::NETLINK_RDMA, - /// Transport IPv6 packets from netfilter to user space. Used by ip6_queue kernel module. - /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - NetlinkIPv6Firewall = libc::NETLINK_IP6_FW, - /// DECnet routing messages - /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - NetlinkDECNetRoutingMessage = libc::NETLINK_DNRTMSG, - /// Kernel messages to user space - /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - NetlinkKObjectUEvent = libc::NETLINK_KOBJECT_UEVENT, - /// Netlink interface to request information about ciphers registered with the kernel crypto API as well as allow - /// configuration of the kernel crypto API. - /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html)) - #[cfg(any(target_os = "android", target_os = "linux"))] - NetlinkCrypto = libc::NETLINK_CRYPTO, -} - -libc_bitflags!{ - /// Additional socket options - pub struct SockFlag: c_int { - /// Set non-blocking mode on the new socket - #[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "illumos", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd"))] - SOCK_NONBLOCK; - /// Set close-on-exec on the new descriptor - #[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "illumos", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd"))] - SOCK_CLOEXEC; - /// Return `EPIPE` instead of raising `SIGPIPE` - #[cfg(target_os = "netbsd")] - SOCK_NOSIGPIPE; - /// For domains `AF_INET(6)`, only allow `connect(2)`, `sendto(2)`, or `sendmsg(2)` - /// to the DNS port (typically 53) - #[cfg(target_os = "openbsd")] - SOCK_DNS; - } -} - -libc_bitflags!{ - /// Flags for send/recv and their relatives - pub struct MsgFlags: c_int { - /// Sends or requests out-of-band data on sockets that support this notion - /// (e.g., of type [`Stream`](enum.SockType.html)); the underlying protocol must also - /// support out-of-band data. - MSG_OOB; - /// Peeks at an incoming message. The data is treated as unread and the next - /// [`recv()`](fn.recv.html) - /// or similar function shall still return this data. - MSG_PEEK; - /// Receive operation blocks until the full amount of data can be - /// returned. The function may return smaller amount of data if a signal - /// is caught, an error or disconnect occurs. - MSG_WAITALL; - /// Enables nonblocking operation; if the operation would block, - /// `EAGAIN` or `EWOULDBLOCK` is returned. This provides similar - /// behavior to setting the `O_NONBLOCK` flag - /// (via the [`fcntl`](../../fcntl/fn.fcntl.html) - /// `F_SETFL` operation), but differs in that `MSG_DONTWAIT` is a per- - /// call option, whereas `O_NONBLOCK` is a setting on the open file - /// description (see [open(2)](https://man7.org/linux/man-pages/man2/open.2.html)), - /// which will affect all threads in - /// the calling process and as well as other processes that hold - /// file descriptors referring to the same open file description. - MSG_DONTWAIT; - /// Receive flags: Control Data was discarded (buffer too small) - MSG_CTRUNC; - /// For raw ([`Packet`](addr/enum.AddressFamily.html)), Internet datagram - /// (since Linux 2.4.27/2.6.8), - /// netlink (since Linux 2.6.22) and UNIX datagram (since Linux 3.4) - /// sockets: return the real length of the packet or datagram, even - /// when it was longer than the passed buffer. Not implemented for UNIX - /// domain ([unix(7)](https://linux.die.net/man/7/unix)) sockets. - /// - /// For use with Internet stream sockets, see [tcp(7)](https://linux.die.net/man/7/tcp). - MSG_TRUNC; - /// Terminates a record (when this notion is supported, as for - /// sockets of type [`SeqPacket`](enum.SockType.html)). - MSG_EOR; - /// This flag specifies that queued errors should be received from - /// the socket error queue. (For more details, see - /// [recvfrom(2)](https://linux.die.net/man/2/recvfrom)) - #[cfg(any(target_os = "android", target_os = "linux"))] - MSG_ERRQUEUE; - /// Set the `close-on-exec` flag for the file descriptor received via a UNIX domain - /// file descriptor using the `SCM_RIGHTS` operation (described in - /// [unix(7)](https://linux.die.net/man/7/unix)). - /// This flag is useful for the same reasons as the `O_CLOEXEC` flag of - /// [open(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html). - /// - /// Only used in [`recvmsg`](fn.recvmsg.html) function. - #[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd"))] - MSG_CMSG_CLOEXEC; - } -} - -cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { - /// Unix credentials of the sending process. - /// - /// This struct is used with the `SO_PEERCRED` ancillary message - /// and the `SCM_CREDENTIALS` control message for UNIX sockets. - #[repr(transparent)] - #[derive(Clone, Copy, Debug, Eq, PartialEq)] - pub struct UnixCredentials(libc::ucred); - - impl UnixCredentials { - /// Creates a new instance with the credentials of the current process - pub fn new() -> Self { - UnixCredentials(libc::ucred { - pid: crate::unistd::getpid().as_raw(), - uid: crate::unistd::getuid().as_raw(), - gid: crate::unistd::getgid().as_raw(), - }) - } - - /// Returns the process identifier - pub fn pid(&self) -> libc::pid_t { - self.0.pid - } - - /// Returns the user identifier - pub fn uid(&self) -> libc::uid_t { - self.0.uid - } - - /// Returns the group identifier - pub fn gid(&self) -> libc::gid_t { - self.0.gid - } - } - - impl Default for UnixCredentials { - fn default() -> Self { - Self::new() - } - } - - impl From for UnixCredentials { - fn from(cred: libc::ucred) -> Self { - UnixCredentials(cred) - } - } - - impl From for libc::ucred { - fn from(uc: UnixCredentials) -> Self { - uc.0 - } - } - } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] { - /// Unix credentials of the sending process. - /// - /// This struct is used with the `SCM_CREDS` ancillary message for UNIX sockets. - #[repr(transparent)] - #[derive(Clone, Copy, Debug, Eq, PartialEq)] - pub struct UnixCredentials(libc::cmsgcred); - - impl UnixCredentials { - /// Returns the process identifier - pub fn pid(&self) -> libc::pid_t { - self.0.cmcred_pid - } - - /// Returns the real user identifier - pub fn uid(&self) -> libc::uid_t { - self.0.cmcred_uid - } - - /// Returns the effective user identifier - pub fn euid(&self) -> libc::uid_t { - self.0.cmcred_euid - } - - /// Returns the real group identifier - pub fn gid(&self) -> libc::gid_t { - self.0.cmcred_gid - } - - /// Returns a list group identifiers (the first one being the effective GID) - pub fn groups(&self) -> &[libc::gid_t] { - unsafe { slice::from_raw_parts(self.0.cmcred_groups.as_ptr() as *const libc::gid_t, self.0.cmcred_ngroups as _) } - } - } - - impl From for UnixCredentials { - fn from(cred: libc::cmsgcred) -> Self { - UnixCredentials(cred) - } - } - } -} - -cfg_if!{ - if #[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "ios" - ))] { - /// Return type of [`LocalPeerCred`](crate::sys::socket::sockopt::LocalPeerCred) - #[repr(transparent)] - #[derive(Clone, Copy, Debug, Eq, PartialEq)] - pub struct XuCred(libc::xucred); - - impl XuCred { - /// Structure layout version - pub fn version(&self) -> u32 { - self.0.cr_version - } - - /// Effective user ID - pub fn uid(&self) -> libc::uid_t { - self.0.cr_uid - } - - /// Returns a list of group identifiers (the first one being the - /// effective GID) - pub fn groups(&self) -> &[libc::gid_t] { - &self.0.cr_groups - } - } - } -} - -/// Request for multicast socket operations -/// -/// This is a wrapper type around `ip_mreq`. -#[repr(transparent)] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct IpMembershipRequest(libc::ip_mreq); - -impl IpMembershipRequest { - /// Instantiate a new `IpMembershipRequest` - /// - /// If `interface` is `None`, then `Ipv4Addr::any()` will be used for the interface. - pub fn new(group: Ipv4Addr, interface: Option) -> Self { - IpMembershipRequest(libc::ip_mreq { - imr_multiaddr: group.0, - imr_interface: interface.unwrap_or_else(Ipv4Addr::any).0, - }) - } -} - -/// Request for ipv6 multicast socket operations -/// -/// This is a wrapper type around `ipv6_mreq`. -#[repr(transparent)] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct Ipv6MembershipRequest(libc::ipv6_mreq); - -impl Ipv6MembershipRequest { - /// Instantiate a new `Ipv6MembershipRequest` - pub const fn new(group: Ipv6Addr) -> Self { - Ipv6MembershipRequest(libc::ipv6_mreq { - ipv6mr_multiaddr: group.0, - ipv6mr_interface: 0, - }) - } -} - -/// Create a buffer large enough for storing some control messages as returned -/// by [`recvmsg`](fn.recvmsg.html). -/// -/// # Examples -/// -/// ``` -/// # #[macro_use] extern crate nix; -/// # use nix::sys::time::TimeVal; -/// # use std::os::unix::io::RawFd; -/// # fn main() { -/// // Create a buffer for a `ControlMessageOwned::ScmTimestamp` message -/// let _ = cmsg_space!(TimeVal); -/// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message -/// // with two file descriptors -/// let _ = cmsg_space!([RawFd; 2]); -/// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message -/// // and a `ControlMessageOwned::ScmTimestamp` message -/// let _ = cmsg_space!(RawFd, TimeVal); -/// # } -/// ``` -// Unfortunately, CMSG_SPACE isn't a const_fn, or else we could return a -// stack-allocated array. -#[macro_export] -macro_rules! cmsg_space { - ( $( $x:ty ),* ) => { - { - let mut space = 0; - $( - // CMSG_SPACE is always safe - space += unsafe { - $crate::sys::socket::CMSG_SPACE(::std::mem::size_of::<$x>() as $crate::sys::socket::c_uint) - } as usize; - )* - Vec::::with_capacity(space) - } - } -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct RecvMsg<'a> { - pub bytes: usize, - cmsghdr: Option<&'a cmsghdr>, - pub address: Option, - pub flags: MsgFlags, - mhdr: msghdr, -} - -impl<'a> RecvMsg<'a> { - /// Iterate over the valid control messages pointed to by this - /// msghdr. - pub fn cmsgs(&self) -> CmsgIterator { - CmsgIterator { - cmsghdr: self.cmsghdr, - mhdr: &self.mhdr - } - } -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct CmsgIterator<'a> { - /// Control message buffer to decode from. Must adhere to cmsg alignment. - cmsghdr: Option<&'a cmsghdr>, - mhdr: &'a msghdr -} - -impl<'a> Iterator for CmsgIterator<'a> { - type Item = ControlMessageOwned; - - fn next(&mut self) -> Option { - match self.cmsghdr { - None => None, // No more messages - Some(hdr) => { - // Get the data. - // Safe if cmsghdr points to valid data returned by recvmsg(2) - let cm = unsafe { Some(ControlMessageOwned::decode_from(hdr))}; - // Advance the internal pointer. Safe if mhdr and cmsghdr point - // to valid data returned by recvmsg(2) - self.cmsghdr = unsafe { - let p = CMSG_NXTHDR(self.mhdr as *const _, hdr as *const _); - p.as_ref() - }; - cm - } - } - } -} - -/// A type-safe wrapper around a single control message, as used with -/// [`recvmsg`](#fn.recvmsg). -/// -/// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html) -// Nix version 0.13.0 and earlier used ControlMessage for both recvmsg and -// sendmsg. However, on some platforms the messages returned by recvmsg may be -// unaligned. ControlMessageOwned takes those messages by copy, obviating any -// alignment issues. -// -// See https://github.com/nix-rust/nix/issues/999 -#[derive(Clone, Debug, Eq, PartialEq)] -#[non_exhaustive] -pub enum ControlMessageOwned { - /// Received version of [`ControlMessage::ScmRights`] - ScmRights(Vec), - /// Received version of [`ControlMessage::ScmCredentials`] - #[cfg(any(target_os = "android", target_os = "linux"))] - ScmCredentials(UnixCredentials), - /// Received version of [`ControlMessage::ScmCreds`] - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - ScmCreds(UnixCredentials), - /// A message of type `SCM_TIMESTAMP`, containing the time the - /// packet was received by the kernel. - /// - /// See the kernel's explanation in "SO_TIMESTAMP" of - /// [networking/timestamping](https://www.kernel.org/doc/Documentation/networking/timestamping.txt). - /// - /// # Examples - /// - /// ``` - /// # #[macro_use] extern crate nix; - /// # use nix::sys::socket::*; - /// # use nix::sys::uio::IoVec; - /// # use nix::sys::time::*; - /// # use std::time::*; - /// # fn main() { - /// // Set up - /// let message = "Ohayō!".as_bytes(); - /// let in_socket = socket( - /// AddressFamily::Inet, - /// SockType::Datagram, - /// SockFlag::empty(), - /// None).unwrap(); - /// setsockopt(in_socket, sockopt::ReceiveTimestamp, &true).unwrap(); - /// let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0); - /// bind(in_socket, &SockAddr::new_inet(localhost)).unwrap(); - /// let address = getsockname(in_socket).unwrap(); - /// // Get initial time - /// let time0 = SystemTime::now(); - /// // Send the message - /// let iov = [IoVec::from_slice(message)]; - /// let flags = MsgFlags::empty(); - /// let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap(); - /// assert_eq!(message.len(), l); - /// // Receive the message - /// let mut buffer = vec![0u8; message.len()]; - /// let mut cmsgspace = cmsg_space!(TimeVal); - /// let iov = [IoVec::from_mut_slice(&mut buffer)]; - /// let r = recvmsg(in_socket, &iov, Some(&mut cmsgspace), flags).unwrap(); - /// let rtime = match r.cmsgs().next() { - /// Some(ControlMessageOwned::ScmTimestamp(rtime)) => rtime, - /// Some(_) => panic!("Unexpected control message"), - /// None => panic!("No control message") - /// }; - /// // Check the final time - /// let time1 = SystemTime::now(); - /// // the packet's received timestamp should lie in-between the two system - /// // times, unless the system clock was adjusted in the meantime. - /// let rduration = Duration::new(rtime.tv_sec() as u64, - /// rtime.tv_usec() as u32 * 1000); - /// assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration); - /// assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap()); - /// // Close socket - /// nix::unistd::close(in_socket).unwrap(); - /// # } - /// ``` - ScmTimestamp(TimeVal), - /// Nanoseconds resolution timestamp - /// - /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html) - #[cfg(all(target_os = "linux"))] - ScmTimestampns(TimeSpec), - #[cfg(any( - target_os = "android", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - ))] - Ipv4PacketInfo(libc::in_pktinfo), - #[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "openbsd", - target_os = "netbsd", - ))] - Ipv6PacketInfo(libc::in6_pktinfo), - #[cfg(any( - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - ))] - Ipv4RecvIf(libc::sockaddr_dl), - #[cfg(any( - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - ))] - Ipv4RecvDstAddr(libc::in_addr), - - /// UDP Generic Receive Offload (GRO) allows receiving multiple UDP - /// packets from a single sender. - /// Fixed-size payloads are following one by one in a receive buffer. - /// This Control Message indicates the size of all smaller packets, - /// except, maybe, the last one. - /// - /// `UdpGroSegment` socket option should be enabled on a socket - /// to allow receiving GRO packets. - #[cfg(target_os = "linux")] - UdpGroSegments(u16), - - /// SO_RXQ_OVFL indicates that an unsigned 32 bit value - /// ancilliary msg (cmsg) should be attached to recieved - /// skbs indicating the number of packets dropped by the - /// socket between the last recieved packet and this - /// received packet. - /// - /// `RxqOvfl` socket option should be enabled on a socket - /// to allow receiving the drop counter. - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] - RxqOvfl(u32), - - /// Socket error queue control messages read with the `MSG_ERRQUEUE` flag. - #[cfg(any(target_os = "android", target_os = "linux"))] - Ipv4RecvErr(libc::sock_extended_err, Option), - /// Socket error queue control messages read with the `MSG_ERRQUEUE` flag. - #[cfg(any(target_os = "android", target_os = "linux"))] - Ipv6RecvErr(libc::sock_extended_err, Option), - - /// Catch-all variant for unimplemented cmsg types. - #[doc(hidden)] - Unknown(UnknownCmsg), -} - -impl ControlMessageOwned { - /// Decodes a `ControlMessageOwned` from raw bytes. - /// - /// This is only safe to call if the data is correct for the message type - /// specified in the header. Normally, the kernel ensures that this is the - /// case. "Correct" in this case includes correct length, alignment and - /// actual content. - // Clippy complains about the pointer alignment of `p`, not understanding - // that it's being fed to a function that can handle that. - #[allow(clippy::cast_ptr_alignment)] - unsafe fn decode_from(header: &cmsghdr) -> ControlMessageOwned - { - let p = CMSG_DATA(header); - let len = header as *const _ as usize + header.cmsg_len as usize - - p as usize; - match (header.cmsg_level, header.cmsg_type) { - (libc::SOL_SOCKET, libc::SCM_RIGHTS) => { - let n = len / mem::size_of::(); - let mut fds = Vec::with_capacity(n); - for i in 0..n { - let fdp = (p as *const RawFd).add(i); - fds.push(ptr::read_unaligned(fdp)); - } - ControlMessageOwned::ScmRights(fds) - }, - #[cfg(any(target_os = "android", target_os = "linux"))] - (libc::SOL_SOCKET, libc::SCM_CREDENTIALS) => { - let cred: libc::ucred = ptr::read_unaligned(p as *const _); - ControlMessageOwned::ScmCredentials(cred.into()) - } - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - (libc::SOL_SOCKET, libc::SCM_CREDS) => { - let cred: libc::cmsgcred = ptr::read_unaligned(p as *const _); - ControlMessageOwned::ScmCreds(cred.into()) - } - (libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => { - let tv: libc::timeval = ptr::read_unaligned(p as *const _); - ControlMessageOwned::ScmTimestamp(TimeVal::from(tv)) - }, - #[cfg(all(target_os = "linux"))] - (libc::SOL_SOCKET, libc::SCM_TIMESTAMPNS) => { - let ts: libc::timespec = ptr::read_unaligned(p as *const _); - ControlMessageOwned::ScmTimestampns(TimeSpec::from(ts)) - } - #[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos" - ))] - (libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => { - let info = ptr::read_unaligned(p as *const libc::in6_pktinfo); - ControlMessageOwned::Ipv6PacketInfo(info) - } - #[cfg(any( - target_os = "android", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - ))] - (libc::IPPROTO_IP, libc::IP_PKTINFO) => { - let info = ptr::read_unaligned(p as *const libc::in_pktinfo); - ControlMessageOwned::Ipv4PacketInfo(info) - } - #[cfg(any( - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - ))] - (libc::IPPROTO_IP, libc::IP_RECVIF) => { - let dl = ptr::read_unaligned(p as *const libc::sockaddr_dl); - ControlMessageOwned::Ipv4RecvIf(dl) - }, - #[cfg(any( - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - ))] - (libc::IPPROTO_IP, libc::IP_RECVDSTADDR) => { - let dl = ptr::read_unaligned(p as *const libc::in_addr); - ControlMessageOwned::Ipv4RecvDstAddr(dl) - }, - #[cfg(target_os = "linux")] - (libc::SOL_UDP, libc::UDP_GRO) => { - let gso_size: u16 = ptr::read_unaligned(p as *const _); - ControlMessageOwned::UdpGroSegments(gso_size) - }, - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] - (libc::SOL_SOCKET, libc::SO_RXQ_OVFL) => { - let drop_counter = ptr::read_unaligned(p as *const u32); - ControlMessageOwned::RxqOvfl(drop_counter) - }, - #[cfg(any(target_os = "android", target_os = "linux"))] - (libc::IPPROTO_IP, libc::IP_RECVERR) => { - let (err, addr) = Self::recv_err_helper::(p, len); - ControlMessageOwned::Ipv4RecvErr(err, addr) - }, - #[cfg(any(target_os = "android", target_os = "linux"))] - (libc::IPPROTO_IPV6, libc::IPV6_RECVERR) => { - let (err, addr) = Self::recv_err_helper::(p, len); - ControlMessageOwned::Ipv6RecvErr(err, addr) - }, - (_, _) => { - let sl = slice::from_raw_parts(p, len); - let ucmsg = UnknownCmsg(*header, Vec::::from(sl)); - ControlMessageOwned::Unknown(ucmsg) - } - } - } - - #[cfg(any(target_os = "android", target_os = "linux"))] - unsafe fn recv_err_helper(p: *mut libc::c_uchar, len: usize) -> (libc::sock_extended_err, Option) { - let ee = p as *const libc::sock_extended_err; - let err = ptr::read_unaligned(ee); - - // For errors originating on the network, SO_EE_OFFENDER(ee) points inside the p[..len] - // CMSG_DATA buffer. For local errors, there is no address included in the control - // message, and SO_EE_OFFENDER(ee) points beyond the end of the buffer. So, we need to - // validate that the address object is in-bounds before we attempt to copy it. - let addrp = libc::SO_EE_OFFENDER(ee) as *const T; - - if addrp.offset(1) as usize - (p as usize) > len { - (err, None) - } else { - (err, Some(ptr::read_unaligned(addrp))) - } - } -} - -/// A type-safe zero-copy wrapper around a single control message, as used wih -/// [`sendmsg`](#fn.sendmsg). More types may be added to this enum; do not -/// exhaustively pattern-match it. -/// -/// [Further reading](https://man7.org/linux/man-pages/man3/cmsg.3.html) -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[non_exhaustive] -pub enum ControlMessage<'a> { - /// A message of type `SCM_RIGHTS`, containing an array of file - /// descriptors passed between processes. - /// - /// See the description in the "Ancillary messages" section of the - /// [unix(7) man page](https://man7.org/linux/man-pages/man7/unix.7.html). - /// - /// Using multiple `ScmRights` messages for a single `sendmsg` call isn't - /// recommended since it causes platform-dependent behaviour: It might - /// swallow all but the first `ScmRights` message or fail with `EINVAL`. - /// Instead, you can put all fds to be passed into a single `ScmRights` - /// message. - ScmRights(&'a [RawFd]), - /// A message of type `SCM_CREDENTIALS`, containing the pid, uid and gid of - /// a process connected to the socket. - /// - /// This is similar to the socket option `SO_PEERCRED`, but requires a - /// process to explicitly send its credentials. A process running as root is - /// allowed to specify any credentials, while credentials sent by other - /// processes are verified by the kernel. - /// - /// For further information, please refer to the - /// [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html) man page. - #[cfg(any(target_os = "android", target_os = "linux"))] - ScmCredentials(&'a UnixCredentials), - /// A message of type `SCM_CREDS`, containing the pid, uid, euid, gid and groups of - /// a process connected to the socket. - /// - /// This is similar to the socket options `LOCAL_CREDS` and `LOCAL_PEERCRED`, but - /// requires a process to explicitly send its credentials. - /// - /// Credentials are always overwritten by the kernel, so this variant does have - /// any data, unlike the receive-side - /// [`ControlMessageOwned::ScmCreds`]. - /// - /// For further information, please refer to the - /// [`unix(4)`](https://www.freebsd.org/cgi/man.cgi?query=unix) man page. - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - ScmCreds, - - /// Set IV for `AF_ALG` crypto API. - /// - /// For further information, please refer to the - /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html) - #[cfg(any( - target_os = "android", - target_os = "linux", - ))] - AlgSetIv(&'a [u8]), - /// Set crypto operation for `AF_ALG` crypto API. It may be one of - /// `ALG_OP_ENCRYPT` or `ALG_OP_DECRYPT` - /// - /// For further information, please refer to the - /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html) - #[cfg(any( - target_os = "android", - target_os = "linux", - ))] - AlgSetOp(&'a libc::c_int), - /// Set the length of associated authentication data (AAD) (applicable only to AEAD algorithms) - /// for `AF_ALG` crypto API. - /// - /// For further information, please refer to the - /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html) - #[cfg(any( - target_os = "android", - target_os = "linux", - ))] - AlgSetAeadAssoclen(&'a u32), - - /// UDP GSO makes it possible for applications to generate network packets - /// for a virtual MTU much greater than the real one. - /// The length of the send data no longer matches the expected length on - /// the wire. - /// The size of the datagram payload as it should appear on the wire may be - /// passed through this control message. - /// Send buffer should consist of multiple fixed-size wire payloads - /// following one by one, and the last, possibly smaller one. - #[cfg(target_os = "linux")] - UdpGsoSegments(&'a u16), - - /// Configure the sending addressing and interface for v4 - /// - /// For further information, please refer to the - /// [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html) man page. - #[cfg(any(target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "android", - target_os = "ios",))] - Ipv4PacketInfo(&'a libc::in_pktinfo), - - /// Configure the sending addressing and interface for v6 - /// - /// For further information, please refer to the - /// [`ipv6(7)`](https://man7.org/linux/man-pages/man7/ipv6.7.html) man page. - #[cfg(any(target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "freebsd", - target_os = "android", - target_os = "ios",))] - Ipv6PacketInfo(&'a libc::in6_pktinfo), - - /// SO_RXQ_OVFL indicates that an unsigned 32 bit value - /// ancilliary msg (cmsg) should be attached to recieved - /// skbs indicating the number of packets dropped by the - /// socket between the last recieved packet and this - /// received packet. - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] - RxqOvfl(&'a u32), -} - -// An opaque structure used to prevent cmsghdr from being a public type -#[doc(hidden)] -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct UnknownCmsg(cmsghdr, Vec); - -impl<'a> ControlMessage<'a> { - /// The value of CMSG_SPACE on this message. - /// Safe because CMSG_SPACE is always safe - fn space(&self) -> usize { - unsafe{CMSG_SPACE(self.len() as libc::c_uint) as usize} - } - - /// The value of CMSG_LEN on this message. - /// Safe because CMSG_LEN is always safe - #[cfg(any(target_os = "android", - all(target_os = "linux", not(target_env = "musl"))))] - fn cmsg_len(&self) -> usize { - unsafe{CMSG_LEN(self.len() as libc::c_uint) as usize} - } - - #[cfg(not(any(target_os = "android", - all(target_os = "linux", not(target_env = "musl")))))] - fn cmsg_len(&self) -> libc::c_uint { - unsafe{CMSG_LEN(self.len() as libc::c_uint)} - } - - /// Return a reference to the payload data as a byte pointer - fn copy_to_cmsg_data(&self, cmsg_data: *mut u8) { - let data_ptr = match *self { - ControlMessage::ScmRights(fds) => { - fds as *const _ as *const u8 - }, - #[cfg(any(target_os = "android", target_os = "linux"))] - ControlMessage::ScmCredentials(creds) => { - &creds.0 as *const libc::ucred as *const u8 - } - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - ControlMessage::ScmCreds => { - // The kernel overwrites the data, we just zero it - // to make sure it's not uninitialized memory - unsafe { ptr::write_bytes(cmsg_data, 0, self.len()) }; - return - } - #[cfg(any(target_os = "android", target_os = "linux"))] - ControlMessage::AlgSetIv(iv) => { - #[allow(deprecated)] // https://github.com/rust-lang/libc/issues/1501 - let af_alg_iv = libc::af_alg_iv { - ivlen: iv.len() as u32, - iv: [0u8; 0], - }; - - let size = mem::size_of_val(&af_alg_iv); - - unsafe { - ptr::copy_nonoverlapping( - &af_alg_iv as *const _ as *const u8, - cmsg_data, - size, - ); - ptr::copy_nonoverlapping( - iv.as_ptr(), - cmsg_data.add(size), - iv.len() - ); - }; - - return - }, - #[cfg(any(target_os = "android", target_os = "linux"))] - ControlMessage::AlgSetOp(op) => { - op as *const _ as *const u8 - }, - #[cfg(any(target_os = "android", target_os = "linux"))] - ControlMessage::AlgSetAeadAssoclen(len) => { - len as *const _ as *const u8 - }, - #[cfg(target_os = "linux")] - ControlMessage::UdpGsoSegments(gso_size) => { - gso_size as *const _ as *const u8 - }, - #[cfg(any(target_os = "linux", target_os = "macos", - target_os = "netbsd", target_os = "android", - target_os = "ios",))] - ControlMessage::Ipv4PacketInfo(info) => info as *const _ as *const u8, - #[cfg(any(target_os = "linux", target_os = "macos", - target_os = "netbsd", target_os = "freebsd", - target_os = "android", target_os = "ios",))] - ControlMessage::Ipv6PacketInfo(info) => info as *const _ as *const u8, - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] - ControlMessage::RxqOvfl(drop_count) => { - drop_count as *const _ as *const u8 - }, - }; - unsafe { - ptr::copy_nonoverlapping( - data_ptr, - cmsg_data, - self.len() - ) - }; - } - - /// The size of the payload, excluding its cmsghdr - fn len(&self) -> usize { - match *self { - ControlMessage::ScmRights(fds) => { - mem::size_of_val(fds) - }, - #[cfg(any(target_os = "android", target_os = "linux"))] - ControlMessage::ScmCredentials(creds) => { - mem::size_of_val(creds) - } - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - ControlMessage::ScmCreds => { - mem::size_of::() - } - #[cfg(any(target_os = "android", target_os = "linux"))] - ControlMessage::AlgSetIv(iv) => { - mem::size_of_val(&iv) + iv.len() - }, - #[cfg(any(target_os = "android", target_os = "linux"))] - ControlMessage::AlgSetOp(op) => { - mem::size_of_val(op) - }, - #[cfg(any(target_os = "android", target_os = "linux"))] - ControlMessage::AlgSetAeadAssoclen(len) => { - mem::size_of_val(len) - }, - #[cfg(target_os = "linux")] - ControlMessage::UdpGsoSegments(gso_size) => { - mem::size_of_val(gso_size) - }, - #[cfg(any(target_os = "linux", target_os = "macos", - target_os = "netbsd", target_os = "android", - target_os = "ios",))] - ControlMessage::Ipv4PacketInfo(info) => mem::size_of_val(info), - #[cfg(any(target_os = "linux", target_os = "macos", - target_os = "netbsd", target_os = "freebsd", - target_os = "android", target_os = "ios",))] - ControlMessage::Ipv6PacketInfo(info) => mem::size_of_val(info), - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] - ControlMessage::RxqOvfl(drop_count) => { - mem::size_of_val(drop_count) - }, - } - } - - /// Returns the value to put into the `cmsg_level` field of the header. - fn cmsg_level(&self) -> libc::c_int { - match *self { - ControlMessage::ScmRights(_) => libc::SOL_SOCKET, - #[cfg(any(target_os = "android", target_os = "linux"))] - ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET, - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - ControlMessage::ScmCreds => libc::SOL_SOCKET, - #[cfg(any(target_os = "android", target_os = "linux"))] - ControlMessage::AlgSetIv(_) | ControlMessage::AlgSetOp(_) | - ControlMessage::AlgSetAeadAssoclen(_) => libc::SOL_ALG, - #[cfg(target_os = "linux")] - ControlMessage::UdpGsoSegments(_) => libc::SOL_UDP, - #[cfg(any(target_os = "linux", target_os = "macos", - target_os = "netbsd", target_os = "android", - target_os = "ios",))] - ControlMessage::Ipv4PacketInfo(_) => libc::IPPROTO_IP, - #[cfg(any(target_os = "linux", target_os = "macos", - target_os = "netbsd", target_os = "freebsd", - target_os = "android", target_os = "ios",))] - ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6, - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] - ControlMessage::RxqOvfl(_) => libc::SOL_SOCKET, - } - } - - /// Returns the value to put into the `cmsg_type` field of the header. - fn cmsg_type(&self) -> libc::c_int { - match *self { - ControlMessage::ScmRights(_) => libc::SCM_RIGHTS, - #[cfg(any(target_os = "android", target_os = "linux"))] - ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS, - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - ControlMessage::ScmCreds => libc::SCM_CREDS, - #[cfg(any(target_os = "android", target_os = "linux"))] - ControlMessage::AlgSetIv(_) => { - libc::ALG_SET_IV - }, - #[cfg(any(target_os = "android", target_os = "linux"))] - ControlMessage::AlgSetOp(_) => { - libc::ALG_SET_OP - }, - #[cfg(any(target_os = "android", target_os = "linux"))] - ControlMessage::AlgSetAeadAssoclen(_) => { - libc::ALG_SET_AEAD_ASSOCLEN - }, - #[cfg(target_os = "linux")] - ControlMessage::UdpGsoSegments(_) => { - libc::UDP_SEGMENT - }, - #[cfg(any(target_os = "linux", target_os = "macos", - target_os = "netbsd", target_os = "android", - target_os = "ios",))] - ControlMessage::Ipv4PacketInfo(_) => libc::IP_PKTINFO, - #[cfg(any(target_os = "linux", target_os = "macos", - target_os = "netbsd", target_os = "freebsd", - target_os = "android", target_os = "ios",))] - ControlMessage::Ipv6PacketInfo(_) => libc::IPV6_PKTINFO, - #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] - ControlMessage::RxqOvfl(_) => { - libc::SO_RXQ_OVFL - }, - } - } - - // Unsafe: cmsg must point to a valid cmsghdr with enough space to - // encode self. - unsafe fn encode_into(&self, cmsg: *mut cmsghdr) { - (*cmsg).cmsg_level = self.cmsg_level(); - (*cmsg).cmsg_type = self.cmsg_type(); - (*cmsg).cmsg_len = self.cmsg_len(); - self.copy_to_cmsg_data(CMSG_DATA(cmsg)); - } -} - - -/// Send data in scatter-gather vectors to a socket, possibly accompanied -/// by ancillary data. Optionally direct the message at the given address, -/// as with sendto. -/// -/// Allocates if cmsgs is nonempty. -pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage], - flags: MsgFlags, addr: Option<&SockAddr>) -> Result -{ - let capacity = cmsgs.iter().map(|c| c.space()).sum(); - - // First size the buffer needed to hold the cmsgs. It must be zeroed, - // because subsequent code will not clear the padding bytes. - let mut cmsg_buffer = vec![0u8; capacity]; - - let mhdr = pack_mhdr_to_send(&mut cmsg_buffer[..], &iov, &cmsgs, addr); - - let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) }; - - Errno::result(ret).map(|r| r as usize) -} - -#[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", -))] -#[derive(Debug)] -pub struct SendMmsgData<'a, I, C> - where - I: AsRef<[IoVec<&'a [u8]>]>, - C: AsRef<[ControlMessage<'a>]> -{ - pub iov: I, - pub cmsgs: C, - pub addr: Option, - pub _lt: std::marker::PhantomData<&'a I>, -} - -/// An extension of `sendmsg` that allows the caller to transmit multiple -/// messages on a socket using a single system call. This has performance -/// benefits for some applications. -/// -/// Allocations are performed for cmsgs and to build `msghdr` buffer -/// -/// # Arguments -/// -/// * `fd`: Socket file descriptor -/// * `data`: Struct that implements `IntoIterator` with `SendMmsgData` items -/// * `flags`: Optional flags passed directly to the operating system. -/// -/// # Returns -/// `Vec` with numbers of sent bytes on each sent message. -/// -/// # References -/// [`sendmsg`](fn.sendmsg.html) -#[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", -))] -pub fn sendmmsg<'a, I, C>( - fd: RawFd, - data: impl std::iter::IntoIterator>, - flags: MsgFlags -) -> Result> - where - I: AsRef<[IoVec<&'a [u8]>]> + 'a, - C: AsRef<[ControlMessage<'a>]> + 'a, -{ - let iter = data.into_iter(); - - let size_hint = iter.size_hint(); - let reserve_items = size_hint.1.unwrap_or(size_hint.0); - - let mut output = Vec::::with_capacity(reserve_items); - - let mut cmsgs_buffers = Vec::>::with_capacity(reserve_items); - - for d in iter { - let capacity: usize = d.cmsgs.as_ref().iter().map(|c| c.space()).sum(); - let mut cmsgs_buffer = vec![0u8; capacity]; - - output.push(libc::mmsghdr { - msg_hdr: pack_mhdr_to_send( - &mut cmsgs_buffer, - &d.iov, - &d.cmsgs, - d.addr.as_ref() - ), - msg_len: 0, - }); - cmsgs_buffers.push(cmsgs_buffer); - }; - - let ret = unsafe { libc::sendmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _) }; - - let sent_messages = Errno::result(ret)? as usize; - let mut sent_bytes = Vec::with_capacity(sent_messages); - - for item in &output { - sent_bytes.push(item.msg_len as usize); - } - - Ok(sent_bytes) -} - - -#[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", -))] -#[derive(Debug)] -pub struct RecvMmsgData<'a, I> - where - I: AsRef<[IoVec<&'a mut [u8]>]> + 'a, -{ - pub iov: I, - pub cmsg_buffer: Option<&'a mut Vec>, -} - -/// An extension of `recvmsg` that allows the caller to receive multiple -/// messages from a socket using a single system call. This has -/// performance benefits for some applications. -/// -/// `iov` and `cmsg_buffer` should be constructed similarly to `recvmsg` -/// -/// Multiple allocations are performed -/// -/// # Arguments -/// -/// * `fd`: Socket file descriptor -/// * `data`: Struct that implements `IntoIterator` with `RecvMmsgData` items -/// * `flags`: Optional flags passed directly to the operating system. -/// -/// # RecvMmsgData -/// -/// * `iov`: Scatter-gather list of buffers to receive the message -/// * `cmsg_buffer`: Space to receive ancillary data. Should be created by -/// [`cmsg_space!`](macro.cmsg_space.html) -/// -/// # Returns -/// A `Vec` with multiple `RecvMsg`, one per received message -/// -/// # References -/// - [`recvmsg`](fn.recvmsg.html) -/// - [`RecvMsg`](struct.RecvMsg.html) -#[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", -))] -#[allow(clippy::needless_collect)] // Complicated false positive -pub fn recvmmsg<'a, I>( - fd: RawFd, - data: impl std::iter::IntoIterator, - IntoIter=impl ExactSizeIterator + Iterator>>, - flags: MsgFlags, - timeout: Option -) -> Result>> - where - I: AsRef<[IoVec<&'a mut [u8]>]> + 'a, -{ - let iter = data.into_iter(); - - let num_messages = iter.len(); - - let mut output: Vec = Vec::with_capacity(num_messages); - - // Addresses should be pre-allocated. pack_mhdr_to_receive will store them - // as raw pointers, so we may not move them. Turn the vec into a boxed - // slice so we won't inadvertently reallocate the vec. - let mut addresses = vec![mem::MaybeUninit::uninit(); num_messages] - .into_boxed_slice(); - - let results: Vec<_> = iter.enumerate().map(|(i, d)| { - let (msg_controllen, mhdr) = unsafe { - pack_mhdr_to_receive( - d.iov.as_ref(), - &mut d.cmsg_buffer, - addresses[i].as_mut_ptr(), - ) - }; - - output.push( - libc::mmsghdr { - msg_hdr: mhdr, - msg_len: 0, - } - ); - - (msg_controllen as usize, &mut d.cmsg_buffer) - }).collect(); - - let timeout = if let Some(mut t) = timeout { - t.as_mut() as *mut libc::timespec - } else { - ptr::null_mut() - }; - - let ret = unsafe { libc::recvmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _, timeout) }; - - let _ = Errno::result(ret)?; - - Ok(output - .into_iter() - .take(ret as usize) - .zip(addresses.iter().map(|addr| unsafe{addr.assume_init()})) - .zip(results.into_iter()) - .map(|((mmsghdr, address), (msg_controllen, cmsg_buffer))| { - unsafe { - read_mhdr( - mmsghdr.msg_hdr, - mmsghdr.msg_len as isize, - msg_controllen, - address, - cmsg_buffer - ) - } - }) - .collect()) -} - -unsafe fn read_mhdr<'a, 'b>( - mhdr: msghdr, - r: isize, - msg_controllen: usize, - address: sockaddr_storage, - cmsg_buffer: &'a mut Option<&'b mut Vec> -) -> RecvMsg<'b> { - let cmsghdr = { - if mhdr.msg_controllen > 0 { - // got control message(s) - cmsg_buffer - .as_mut() - .unwrap() - .set_len(mhdr.msg_controllen as usize); - debug_assert!(!mhdr.msg_control.is_null()); - debug_assert!(msg_controllen >= mhdr.msg_controllen as usize); - CMSG_FIRSTHDR(&mhdr as *const msghdr) - } else { - ptr::null() - }.as_ref() - }; - - let address = sockaddr_storage_to_addr( - &address , - mhdr.msg_namelen as usize - ).ok(); - - RecvMsg { - bytes: r as usize, - cmsghdr, - address, - flags: MsgFlags::from_bits_truncate(mhdr.msg_flags), - mhdr, - } -} - -unsafe fn pack_mhdr_to_receive<'a, I>( - iov: I, - cmsg_buffer: &mut Option<&mut Vec>, - address: *mut sockaddr_storage, -) -> (usize, msghdr) - where - I: AsRef<[IoVec<&'a mut [u8]>]> + 'a, -{ - let (msg_control, msg_controllen) = cmsg_buffer.as_mut() - .map(|v| (v.as_mut_ptr(), v.capacity())) - .unwrap_or((ptr::null_mut(), 0)); - - let mhdr = { - // Musl's msghdr has private fields, so this is the only way to - // initialize it. - let mut mhdr = mem::MaybeUninit::::zeroed(); - let p = mhdr.as_mut_ptr(); - (*p).msg_name = address as *mut c_void; - (*p).msg_namelen = mem::size_of::() as socklen_t; - (*p).msg_iov = iov.as_ref().as_ptr() as *mut iovec; - (*p).msg_iovlen = iov.as_ref().len() as _; - (*p).msg_control = msg_control as *mut c_void; - (*p).msg_controllen = msg_controllen as _; - (*p).msg_flags = 0; - mhdr.assume_init() - }; - - (msg_controllen, mhdr) -} - -fn pack_mhdr_to_send<'a, I, C>( - cmsg_buffer: &mut [u8], - iov: I, - cmsgs: C, - addr: Option<&SockAddr> -) -> msghdr - where - I: AsRef<[IoVec<&'a [u8]>]>, - C: AsRef<[ControlMessage<'a>]> -{ - let capacity = cmsg_buffer.len(); - - // Next encode the sending address, if provided - let (name, namelen) = match addr { - Some(addr) => { - let (x, y) = addr.as_ffi_pair(); - (x as *const _, y) - }, - None => (ptr::null(), 0), - }; - - // The message header must be initialized before the individual cmsgs. - let cmsg_ptr = if capacity > 0 { - cmsg_buffer.as_ptr() as *mut c_void - } else { - ptr::null_mut() - }; - - let mhdr = unsafe { - // Musl's msghdr has private fields, so this is the only way to - // initialize it. - let mut mhdr = mem::MaybeUninit::::zeroed(); - let p = mhdr.as_mut_ptr(); - (*p).msg_name = name as *mut _; - (*p).msg_namelen = namelen; - // transmute iov into a mutable pointer. sendmsg doesn't really mutate - // the buffer, but the standard says that it takes a mutable pointer - (*p).msg_iov = iov.as_ref().as_ptr() as *mut _; - (*p).msg_iovlen = iov.as_ref().len() as _; - (*p).msg_control = cmsg_ptr; - (*p).msg_controllen = capacity as _; - (*p).msg_flags = 0; - mhdr.assume_init() - }; - - // Encode each cmsg. This must happen after initializing the header because - // CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields. - // CMSG_FIRSTHDR is always safe - let mut pmhdr: *mut cmsghdr = unsafe { CMSG_FIRSTHDR(&mhdr as *const msghdr) }; - for cmsg in cmsgs.as_ref() { - assert_ne!(pmhdr, ptr::null_mut()); - // Safe because we know that pmhdr is valid, and we initialized it with - // sufficient space - unsafe { cmsg.encode_into(pmhdr) }; - // Safe because mhdr is valid - pmhdr = unsafe { CMSG_NXTHDR(&mhdr as *const msghdr, pmhdr) }; - } - - mhdr -} - -/// Receive message in scatter-gather vectors from a socket, and -/// optionally receive ancillary data into the provided buffer. -/// If no ancillary data is desired, use () as the type parameter. -/// -/// # Arguments -/// -/// * `fd`: Socket file descriptor -/// * `iov`: Scatter-gather list of buffers to receive the message -/// * `cmsg_buffer`: Space to receive ancillary data. Should be created by -/// [`cmsg_space!`](macro.cmsg_space.html) -/// * `flags`: Optional flags passed directly to the operating system. -/// -/// # References -/// [recvmsg(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html) -pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>], - mut cmsg_buffer: Option<&'a mut Vec>, - flags: MsgFlags) -> Result> -{ - let mut address = mem::MaybeUninit::uninit(); - - let (msg_controllen, mut mhdr) = unsafe { - pack_mhdr_to_receive(&iov, &mut cmsg_buffer, address.as_mut_ptr()) - }; - - let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) }; - - let r = Errno::result(ret)?; - - Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address.assume_init(), &mut cmsg_buffer) }) -} - - -/// Create an endpoint for communication -/// -/// The `protocol` specifies a particular protocol to be used with the -/// socket. Normally only a single protocol exists to support a -/// particular socket type within a given protocol family, in which case -/// protocol can be specified as `None`. However, it is possible that many -/// protocols may exist, in which case a particular protocol must be -/// specified in this manner. -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html) -pub fn socket>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result { - let protocol = match protocol.into() { - None => 0, - Some(p) => p as c_int, - }; - - // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a - // little easier to understand by separating it out. So we have to merge these bitfields - // here. - let mut ty = ty as c_int; - ty |= flags.bits(); - - let res = unsafe { libc::socket(domain as c_int, ty, protocol) }; - - Errno::result(res) -} - -/// Create a pair of connected sockets -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html) -pub fn socketpair>>(domain: AddressFamily, ty: SockType, protocol: T, - flags: SockFlag) -> Result<(RawFd, RawFd)> { - let protocol = match protocol.into() { - None => 0, - Some(p) => p as c_int, - }; - - // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a - // little easier to understand by separating it out. So we have to merge these bitfields - // here. - let mut ty = ty as c_int; - ty |= flags.bits(); - - let mut fds = [-1, -1]; - - let res = unsafe { libc::socketpair(domain as c_int, ty, protocol, fds.as_mut_ptr()) }; - Errno::result(res)?; - - Ok((fds[0], fds[1])) -} - -/// Listen for connections on a socket -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html) -pub fn listen(sockfd: RawFd, backlog: usize) -> Result<()> { - let res = unsafe { libc::listen(sockfd, backlog as c_int) }; - - Errno::result(res).map(drop) -} - -/// Bind a name to a socket -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html) -pub fn bind(fd: RawFd, addr: &SockAddr) -> Result<()> { - let res = unsafe { - let (ptr, len) = addr.as_ffi_pair(); - libc::bind(fd, ptr, len) - }; - - Errno::result(res).map(drop) -} - -/// Accept a connection on a socket -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html) -pub fn accept(sockfd: RawFd) -> Result { - let res = unsafe { libc::accept(sockfd, ptr::null_mut(), ptr::null_mut()) }; - - Errno::result(res) -} - -/// Accept a connection on a socket -/// -/// [Further reading](https://man7.org/linux/man-pages/man2/accept.2.html) -#[cfg(any(all( - target_os = "android", - any( - target_arch = "aarch64", - target_arch = "x86", - target_arch = "x86_64" - ) - ), - target_os = "freebsd", - target_os = "linux", - target_os = "openbsd"))] -pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result { - let res = unsafe { libc::accept4(sockfd, ptr::null_mut(), ptr::null_mut(), flags.bits()) }; - - Errno::result(res) -} - -/// Initiate a connection on a socket -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html) -pub fn connect(fd: RawFd, addr: &SockAddr) -> Result<()> { - let res = unsafe { - let (ptr, len) = addr.as_ffi_pair(); - libc::connect(fd, ptr, len) - }; - - Errno::result(res).map(drop) -} - -/// Receive data from a connection-oriented socket. Returns the number of -/// bytes read -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html) -pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result { - unsafe { - let ret = libc::recv( - sockfd, - buf.as_ptr() as *mut c_void, - buf.len() as size_t, - flags.bits()); - - Errno::result(ret).map(|r| r as usize) - } -} - -/// Receive data from a connectionless or connection-oriented socket. Returns -/// the number of bytes read and, for connectionless sockets, the socket -/// address of the sender. -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html) -pub fn recvfrom(sockfd: RawFd, buf: &mut [u8]) - -> Result<(usize, Option)> -{ - unsafe { - let mut addr: sockaddr_storage = mem::zeroed(); - let mut len = mem::size_of::() as socklen_t; - - let ret = Errno::result(libc::recvfrom( - sockfd, - buf.as_ptr() as *mut c_void, - buf.len() as size_t, - 0, - &mut addr as *mut libc::sockaddr_storage as *mut libc::sockaddr, - &mut len as *mut socklen_t))? as usize; - - match sockaddr_storage_to_addr(&addr, len as usize) { - Err(Errno::ENOTCONN) => Ok((ret, None)), - Ok(addr) => Ok((ret, Some(addr))), - Err(e) => Err(e) - } - } -} - -/// Send a message to a socket -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html) -pub fn sendto(fd: RawFd, buf: &[u8], addr: &SockAddr, flags: MsgFlags) -> Result { - let ret = unsafe { - let (ptr, len) = addr.as_ffi_pair(); - libc::sendto(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits(), ptr, len) - }; - - Errno::result(ret).map(|r| r as usize) -} - -/// Send data to a connection-oriented socket. Returns the number of bytes read -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html) -pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result { - let ret = unsafe { - libc::send(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits()) - }; - - Errno::result(ret).map(|r| r as usize) -} - -/* - * - * ===== Socket Options ===== - * - */ - -/// Represents a socket option that can be retrieved. -pub trait GetSockOpt : Copy { - type Val; - - /// Look up the value of this socket option on the given socket. - fn get(&self, fd: RawFd) -> Result; -} - -/// Represents a socket option that can be set. -pub trait SetSockOpt : Clone { - type Val; - - /// Set the value of this socket option on the given socket. - fn set(&self, fd: RawFd, val: &Self::Val) -> Result<()>; -} - -/// Get the current value for the requested socket option -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html) -pub fn getsockopt(fd: RawFd, opt: O) -> Result { - opt.get(fd) -} - -/// Sets the value for the requested socket option -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html) -/// -/// # Examples -/// -/// ``` -/// use nix::sys::socket::setsockopt; -/// use nix::sys::socket::sockopt::KeepAlive; -/// use std::net::TcpListener; -/// use std::os::unix::io::AsRawFd; -/// -/// let listener = TcpListener::bind("0.0.0.0:0").unwrap(); -/// let fd = listener.as_raw_fd(); -/// let res = setsockopt(fd, KeepAlive, &true); -/// assert!(res.is_ok()); -/// ``` -pub fn setsockopt(fd: RawFd, opt: O, val: &O::Val) -> Result<()> { - opt.set(fd, val) -} - -/// Get the address of the peer connected to the socket `fd`. -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html) -pub fn getpeername(fd: RawFd) -> Result { - unsafe { - let mut addr = mem::MaybeUninit::uninit(); - let mut len = mem::size_of::() as socklen_t; - - let ret = libc::getpeername( - fd, - addr.as_mut_ptr() as *mut libc::sockaddr, - &mut len - ); - - Errno::result(ret)?; - - sockaddr_storage_to_addr(&addr.assume_init(), len as usize) - } -} - -/// Get the current address to which the socket `fd` is bound. -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html) -pub fn getsockname(fd: RawFd) -> Result { - unsafe { - let mut addr = mem::MaybeUninit::uninit(); - let mut len = mem::size_of::() as socklen_t; - - let ret = libc::getsockname( - fd, - addr.as_mut_ptr() as *mut libc::sockaddr, - &mut len - ); - - Errno::result(ret)?; - - sockaddr_storage_to_addr(&addr.assume_init(), len as usize) - } -} - -/// Return the appropriate `SockAddr` type from a `sockaddr_storage` of a -/// certain size. -/// -/// In C this would usually be done by casting. The `len` argument -/// should be the number of bytes in the `sockaddr_storage` that are actually -/// allocated and valid. It must be at least as large as all the useful parts -/// of the structure. Note that in the case of a `sockaddr_un`, `len` need not -/// include the terminating null. -pub fn sockaddr_storage_to_addr( - addr: &sockaddr_storage, - len: usize) -> Result { - - assert!(len <= mem::size_of::()); - if len < mem::size_of_val(&addr.ss_family) { - return Err(Errno::ENOTCONN); - } - - match c_int::from(addr.ss_family) { - libc::AF_INET => { - assert!(len as usize >= mem::size_of::()); - let sin = unsafe { - *(addr as *const sockaddr_storage as *const sockaddr_in) - }; - Ok(SockAddr::Inet(InetAddr::V4(sin))) - } - libc::AF_INET6 => { - assert!(len as usize >= mem::size_of::()); - let sin6 = unsafe { - *(addr as *const _ as *const sockaddr_in6) - }; - Ok(SockAddr::Inet(InetAddr::V6(sin6))) - } - libc::AF_UNIX => { - let pathlen = len - offset_of!(sockaddr_un, sun_path); - unsafe { - let sun = *(addr as *const _ as *const sockaddr_un); - Ok(SockAddr::Unix(UnixAddr::from_raw_parts(sun, pathlen))) - } - } - #[cfg(any(target_os = "android", target_os = "linux"))] - libc::AF_PACKET => { - use libc::sockaddr_ll; - // Don't assert anything about the size. - // Apparently the Linux kernel can return smaller sizes when - // the value in the last element of sockaddr_ll (`sll_addr`) is - // smaller than the declared size of that field - let sll = unsafe { - *(addr as *const _ as *const sockaddr_ll) - }; - Ok(SockAddr::Link(LinkAddr(sll))) - } - #[cfg(any(target_os = "android", target_os = "linux"))] - libc::AF_NETLINK => { - use libc::sockaddr_nl; - let snl = unsafe { - *(addr as *const _ as *const sockaddr_nl) - }; - Ok(SockAddr::Netlink(NetlinkAddr(snl))) - } - #[cfg(any(target_os = "android", target_os = "linux"))] - libc::AF_ALG => { - use libc::sockaddr_alg; - let salg = unsafe { - *(addr as *const _ as *const sockaddr_alg) - }; - Ok(SockAddr::Alg(AlgAddr(salg))) - } - #[cfg(any(target_os = "android", target_os = "linux"))] - libc::AF_VSOCK => { - use libc::sockaddr_vm; - let svm = unsafe { - *(addr as *const _ as *const sockaddr_vm) - }; - Ok(SockAddr::Vsock(VsockAddr(svm))) - } - af => panic!("unexpected address family {}", af), - } -} - - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum Shutdown { - /// Further receptions will be disallowed. - Read, - /// Further transmissions will be disallowed. - Write, - /// Further receptions and transmissions will be disallowed. - Both, -} - -/// Shut down part of a full-duplex connection. -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html) -pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> { - unsafe { - use libc::shutdown; - - let how = match how { - Shutdown::Read => libc::SHUT_RD, - Shutdown::Write => libc::SHUT_WR, - Shutdown::Both => libc::SHUT_RDWR, - }; - - Errno::result(shutdown(df, how)).map(drop) - } -} - -#[cfg(test)] -mod tests { - #[test] - fn can_use_cmsg_space() { - let _ = cmsg_space!(u8); - } -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/socket/sockopt.rs b/vendor/nix-v0.23.1-patched/src/sys/socket/sockopt.rs deleted file mode 100644 index fcb4be81b..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/socket/sockopt.rs +++ /dev/null @@ -1,930 +0,0 @@ -//! Socket options as used by `setsockopt` and `getsockopt`. -use cfg_if::cfg_if; -use super::{GetSockOpt, SetSockOpt}; -use crate::Result; -use crate::errno::Errno; -use crate::sys::time::TimeVal; -use libc::{self, c_int, c_void, socklen_t}; -use std::mem::{ - self, - MaybeUninit -}; -use std::os::unix::io::RawFd; -use std::ffi::{OsStr, OsString}; -#[cfg(target_family = "unix")] -use std::os::unix::ffi::OsStrExt; - -// Constants -// TCP_CA_NAME_MAX isn't defined in user space include files -#[cfg(any(target_os = "freebsd", target_os = "linux"))] -const TCP_CA_NAME_MAX: usize = 16; - -/// Helper for implementing `SetSockOpt` for a given socket option. See -/// [`::sys::socket::SetSockOpt`](sys/socket/trait.SetSockOpt.html). -/// -/// This macro aims to help implementing `SetSockOpt` for different socket options that accept -/// different kinds of data to be used with `setsockopt`. -/// -/// Instead of using this macro directly consider using `sockopt_impl!`, especially if the option -/// you are implementing represents a simple type. -/// -/// # Arguments -/// -/// * `$name:ident`: name of the type you want to implement `SetSockOpt` for. -/// * `$level:expr` : socket layer, or a `protocol level`: could be *raw sockets* -/// (`libc::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`), -/// and more. Please refer to your system manual for more options. Will be passed as the second -/// argument (`level`) to the `setsockopt` call. -/// * `$flag:path`: a flag name to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`, -/// `libc::IP_ADD_MEMBERSHIP` and others. Will be passed as the third argument (`option_name`) -/// to the `setsockopt` call. -/// * Type of the value that you are going to set. -/// * Type that implements the `Set` trait for the type from the previous item (like `SetBool` for -/// `bool`, `SetUsize` for `usize`, etc.). -macro_rules! setsockopt_impl { - ($name:ident, $level:expr, $flag:path, $ty:ty, $setter:ty) => { - impl SetSockOpt for $name { - type Val = $ty; - - fn set(&self, fd: RawFd, val: &$ty) -> Result<()> { - unsafe { - let setter: $setter = Set::new(val); - - let res = libc::setsockopt(fd, $level, $flag, - setter.ffi_ptr(), - setter.ffi_len()); - Errno::result(res).map(drop) - } - } - } - } -} - -/// Helper for implementing `GetSockOpt` for a given socket option. See -/// [`::sys::socket::GetSockOpt`](sys/socket/trait.GetSockOpt.html). -/// -/// This macro aims to help implementing `GetSockOpt` for different socket options that accept -/// different kinds of data to be use with `getsockopt`. -/// -/// Instead of using this macro directly consider using `sockopt_impl!`, especially if the option -/// you are implementing represents a simple type. -/// -/// # Arguments -/// -/// * Name of the type you want to implement `GetSockOpt` for. -/// * Socket layer, or a `protocol level`: could be *raw sockets* (`lic::SOL_SOCKET`), *ip -/// protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`), and more. Please refer -/// to your system manual for more options. Will be passed as the second argument (`level`) to -/// the `getsockopt` call. -/// * A flag to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`, -/// `libc::SO_ORIGINAL_DST` and others. Will be passed as the third argument (`option_name`) to -/// the `getsockopt` call. -/// * Type of the value that you are going to get. -/// * Type that implements the `Get` trait for the type from the previous item (`GetBool` for -/// `bool`, `GetUsize` for `usize`, etc.). -macro_rules! getsockopt_impl { - ($name:ident, $level:expr, $flag:path, $ty:ty, $getter:ty) => { - impl GetSockOpt for $name { - type Val = $ty; - - fn get(&self, fd: RawFd) -> Result<$ty> { - unsafe { - let mut getter: $getter = Get::uninit(); - - let res = libc::getsockopt(fd, $level, $flag, - getter.ffi_ptr(), - getter.ffi_len()); - Errno::result(res)?; - - Ok(getter.assume_init()) - } - } - } - } -} - -/// Helper to generate the sockopt accessors. See -/// [`::sys::socket::GetSockOpt`](sys/socket/trait.GetSockOpt.html) and -/// [`::sys::socket::SetSockOpt`](sys/socket/trait.SetSockOpt.html). -/// -/// This macro aims to help implementing `GetSockOpt` and `SetSockOpt` for different socket options -/// that accept different kinds of data to be use with `getsockopt` and `setsockopt` respectively. -/// -/// Basically this macro wraps up the [`getsockopt_impl!`](macro.getsockopt_impl.html) and -/// [`setsockopt_impl!`](macro.setsockopt_impl.html) macros. -/// -/// # Arguments -/// -/// * `GetOnly`, `SetOnly` or `Both`: whether you want to implement only getter, only setter or -/// both of them. -/// * `$name:ident`: name of type `GetSockOpt`/`SetSockOpt` will be implemented for. -/// * `$level:expr` : socket layer, or a `protocol level`: could be *raw sockets* -/// (`lic::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`), -/// and more. Please refer to your system manual for more options. Will be passed as the second -/// argument (`level`) to the `getsockopt`/`setsockopt` call. -/// * `$flag:path`: a flag name to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`, -/// `libc::IP_ADD_MEMBERSHIP` and others. Will be passed as the third argument (`option_name`) -/// to the `setsockopt`/`getsockopt` call. -/// * `$ty:ty`: type of the value that will be get/set. -/// * `$getter:ty`: `Get` implementation; optional; only for `GetOnly` and `Both`. -/// * `$setter:ty`: `Set` implementation; optional; only for `SetOnly` and `Both`. -macro_rules! sockopt_impl { - ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, bool) => { - sockopt_impl!($(#[$attr])* - $name, GetOnly, $level, $flag, bool, GetBool); - }; - - ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, u8) => { - sockopt_impl!($(#[$attr])* $name, GetOnly, $level, $flag, u8, GetU8); - }; - - ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, usize) => - { - sockopt_impl!($(#[$attr])* - $name, GetOnly, $level, $flag, usize, GetUsize); - }; - - ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, bool) => { - sockopt_impl!($(#[$attr])* - $name, SetOnly, $level, $flag, bool, SetBool); - }; - - ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, u8) => { - sockopt_impl!($(#[$attr])* $name, SetOnly, $level, $flag, u8, SetU8); - }; - - ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, usize) => - { - sockopt_impl!($(#[$attr])* - $name, SetOnly, $level, $flag, usize, SetUsize); - }; - - ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, bool) => { - sockopt_impl!($(#[$attr])* - $name, Both, $level, $flag, bool, GetBool, SetBool); - }; - - ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, u8) => { - sockopt_impl!($(#[$attr])* - $name, Both, $level, $flag, u8, GetU8, SetU8); - }; - - ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, usize) => { - sockopt_impl!($(#[$attr])* - $name, Both, $level, $flag, usize, GetUsize, SetUsize); - }; - - ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, - OsString<$array:ty>) => - { - sockopt_impl!($(#[$attr])* - $name, Both, $level, $flag, OsString, GetOsString<$array>, - SetOsString); - }; - - /* - * Matchers with generic getter types must be placed at the end, so - * they'll only match _after_ specialized matchers fail - */ - ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, $ty:ty) => - { - sockopt_impl!($(#[$attr])* - $name, GetOnly, $level, $flag, $ty, GetStruct<$ty>); - }; - - ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, $ty:ty, - $getter:ty) => - { - $(#[$attr])* - #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] - pub struct $name; - - getsockopt_impl!($name, $level, $flag, $ty, $getter); - }; - - ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, $ty:ty) => - { - sockopt_impl!($(#[$attr])* - $name, SetOnly, $level, $flag, $ty, SetStruct<$ty>); - }; - - ($(#[$attr:meta])* $name:ident, SetOnly, $level:expr, $flag:path, $ty:ty, - $setter:ty) => - { - $(#[$attr])* - #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] - pub struct $name; - - setsockopt_impl!($name, $level, $flag, $ty, $setter); - }; - - ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, $ty:ty, - $getter:ty, $setter:ty) => - { - $(#[$attr])* - #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] - pub struct $name; - - setsockopt_impl!($name, $level, $flag, $ty, $setter); - getsockopt_impl!($name, $level, $flag, $ty, $getter); - }; - - ($(#[$attr:meta])* $name:ident, Both, $level:expr, $flag:path, $ty:ty) => { - sockopt_impl!($(#[$attr])* - $name, Both, $level, $flag, $ty, GetStruct<$ty>, - SetStruct<$ty>); - }; -} - -/* - * - * ===== Define sockopts ===== - * - */ - -sockopt_impl!( - /// Enables local address reuse - ReuseAddr, Both, libc::SOL_SOCKET, libc::SO_REUSEADDR, bool -); -#[cfg(not(any(target_os = "illumos", target_os = "solaris")))] -sockopt_impl!( - /// Permits multiple AF_INET or AF_INET6 sockets to be bound to an - /// identical socket address. - ReusePort, Both, libc::SOL_SOCKET, libc::SO_REUSEPORT, bool); -sockopt_impl!( - /// Under most circumstances, TCP sends data when it is presented; when - /// outstanding data has not yet been acknowledged, it gathers small amounts - /// of output to be sent in a single packet once an acknowledgement is - /// received. For a small number of clients, such as window systems that - /// send a stream of mouse events which receive no replies, this - /// packetization may cause significant delays. The boolean option - /// TCP_NODELAY defeats this algorithm. - TcpNoDelay, Both, libc::IPPROTO_TCP, libc::TCP_NODELAY, bool); -sockopt_impl!( - /// When enabled, a close(2) or shutdown(2) will not return until all - /// queued messages for the socket have been successfully sent or the - /// linger timeout has been reached. - Linger, Both, libc::SOL_SOCKET, libc::SO_LINGER, libc::linger); -sockopt_impl!( - /// Join a multicast group - IpAddMembership, SetOnly, libc::IPPROTO_IP, libc::IP_ADD_MEMBERSHIP, - super::IpMembershipRequest); -sockopt_impl!( - /// Leave a multicast group. - IpDropMembership, SetOnly, libc::IPPROTO_IP, libc::IP_DROP_MEMBERSHIP, - super::IpMembershipRequest); -cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { - sockopt_impl!( - /// Join an IPv6 multicast group. - Ipv6AddMembership, SetOnly, libc::IPPROTO_IPV6, libc::IPV6_ADD_MEMBERSHIP, super::Ipv6MembershipRequest); - sockopt_impl!( - /// Leave an IPv6 multicast group. - Ipv6DropMembership, SetOnly, libc::IPPROTO_IPV6, libc::IPV6_DROP_MEMBERSHIP, super::Ipv6MembershipRequest); - } else if #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "illumos", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris"))] { - sockopt_impl!( - /// Join an IPv6 multicast group. - Ipv6AddMembership, SetOnly, libc::IPPROTO_IPV6, - libc::IPV6_JOIN_GROUP, super::Ipv6MembershipRequest); - sockopt_impl!( - /// Leave an IPv6 multicast group. - Ipv6DropMembership, SetOnly, libc::IPPROTO_IPV6, - libc::IPV6_LEAVE_GROUP, super::Ipv6MembershipRequest); - } -} -sockopt_impl!( - /// Set or read the time-to-live value of outgoing multicast packets for - /// this socket. - IpMulticastTtl, Both, libc::IPPROTO_IP, libc::IP_MULTICAST_TTL, u8); -sockopt_impl!( - /// Set or read a boolean integer argument that determines whether sent - /// multicast packets should be looped back to the local sockets. - IpMulticastLoop, Both, libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP, bool); -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] -sockopt_impl!( - /// If enabled, this boolean option allows binding to an IP address that - /// is nonlocal or does not (yet) exist. - IpFreebind, Both, libc::IPPROTO_IP, libc::IP_FREEBIND, bool); -sockopt_impl!( - /// Specify the receiving timeout until reporting an error. - ReceiveTimeout, Both, libc::SOL_SOCKET, libc::SO_RCVTIMEO, TimeVal); -sockopt_impl!( - /// Specify the sending timeout until reporting an error. - SendTimeout, Both, libc::SOL_SOCKET, libc::SO_SNDTIMEO, TimeVal); -sockopt_impl!( - /// Set or get the broadcast flag. - Broadcast, Both, libc::SOL_SOCKET, libc::SO_BROADCAST, bool); -sockopt_impl!( - /// If this option is enabled, out-of-band data is directly placed into - /// the receive data stream. - OobInline, Both, libc::SOL_SOCKET, libc::SO_OOBINLINE, bool); -sockopt_impl!( - /// Get and clear the pending socket error. - SocketError, GetOnly, libc::SOL_SOCKET, libc::SO_ERROR, i32); -sockopt_impl!( - /// Enable sending of keep-alive messages on connection-oriented sockets. - KeepAlive, Both, libc::SOL_SOCKET, libc::SO_KEEPALIVE, bool); -#[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "ios" -))] -sockopt_impl!( - /// Get the credentials of the peer process of a connected unix domain - /// socket. - LocalPeerCred, GetOnly, 0, libc::LOCAL_PEERCRED, super::XuCred); -#[cfg(any(target_os = "android", target_os = "linux"))] -sockopt_impl!( - /// Return the credentials of the foreign process connected to this socket. - PeerCredentials, GetOnly, libc::SOL_SOCKET, libc::SO_PEERCRED, super::UnixCredentials); -#[cfg(any(target_os = "ios", - target_os = "macos"))] -sockopt_impl!( - /// Specify the amount of time, in seconds, that the connection must be idle - /// before keepalive probes (if enabled) are sent. - TcpKeepAlive, Both, libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, u32); -#[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux", - target_os = "nacl"))] -sockopt_impl!( - /// The time (in seconds) the connection needs to remain idle before TCP - /// starts sending keepalive probes - TcpKeepIdle, Both, libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, u32); -cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { - sockopt_impl!( - /// The maximum segment size for outgoing TCP packets. - TcpMaxSeg, Both, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32); - } else { - sockopt_impl!( - /// The maximum segment size for outgoing TCP packets. - TcpMaxSeg, GetOnly, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32); - } -} -#[cfg(not(target_os = "openbsd"))] -sockopt_impl!( - /// The maximum number of keepalive probes TCP should send before - /// dropping the connection. - TcpKeepCount, Both, libc::IPPROTO_TCP, libc::TCP_KEEPCNT, u32); -#[cfg(any(target_os = "android", - target_os = "fuchsia", - target_os = "linux"))] -sockopt_impl!( - #[allow(missing_docs)] - // Not documented by Linux! - TcpRepair, Both, libc::IPPROTO_TCP, libc::TCP_REPAIR, u32); -#[cfg(not(target_os = "openbsd"))] -sockopt_impl!( - /// The time (in seconds) between individual keepalive probes. - TcpKeepInterval, Both, libc::IPPROTO_TCP, libc::TCP_KEEPINTVL, u32); -#[cfg(any(target_os = "fuchsia", target_os = "linux"))] -sockopt_impl!( - /// Specifies the maximum amount of time in milliseconds that transmitted - /// data may remain unacknowledged before TCP will forcibly close the - /// corresponding connection - TcpUserTimeout, Both, libc::IPPROTO_TCP, libc::TCP_USER_TIMEOUT, u32); -sockopt_impl!( - /// Sets or gets the maximum socket receive buffer in bytes. - RcvBuf, Both, libc::SOL_SOCKET, libc::SO_RCVBUF, usize); -sockopt_impl!( - /// Sets or gets the maximum socket send buffer in bytes. - SndBuf, Both, libc::SOL_SOCKET, libc::SO_SNDBUF, usize); -#[cfg(any(target_os = "android", target_os = "linux"))] -sockopt_impl!( - /// Using this socket option, a privileged (`CAP_NET_ADMIN`) process can - /// perform the same task as `SO_RCVBUF`, but the `rmem_max limit` can be - /// overridden. - RcvBufForce, SetOnly, libc::SOL_SOCKET, libc::SO_RCVBUFFORCE, usize); -#[cfg(any(target_os = "android", target_os = "linux"))] -sockopt_impl!( - /// Using this socket option, a privileged (`CAP_NET_ADMIN`) process can - /// perform the same task as `SO_SNDBUF`, but the `wmem_max` limit can be - /// overridden. - SndBufForce, SetOnly, libc::SOL_SOCKET, libc::SO_SNDBUFFORCE, usize); -sockopt_impl!( - /// Gets the socket type as an integer. - SockType, GetOnly, libc::SOL_SOCKET, libc::SO_TYPE, super::SockType); -sockopt_impl!( - /// Returns a value indicating whether or not this socket has been marked to - /// accept connections with `listen(2)`. - AcceptConn, GetOnly, libc::SOL_SOCKET, libc::SO_ACCEPTCONN, bool); -#[cfg(any(target_os = "android", target_os = "linux"))] -sockopt_impl!( - /// Bind this socket to a particular device like “eth0”. - BindToDevice, Both, libc::SOL_SOCKET, libc::SO_BINDTODEVICE, OsString<[u8; libc::IFNAMSIZ]>); -#[cfg(any(target_os = "android", target_os = "linux"))] -sockopt_impl!( - #[allow(missing_docs)] - // Not documented by Linux! - OriginalDst, GetOnly, libc::SOL_IP, libc::SO_ORIGINAL_DST, libc::sockaddr_in); -#[cfg(any(target_os = "android", target_os = "linux"))] -sockopt_impl!( - #[allow(missing_docs)] - // Not documented by Linux! - Ip6tOriginalDst, GetOnly, libc::SOL_IPV6, libc::IP6T_SO_ORIGINAL_DST, libc::sockaddr_in6); -sockopt_impl!( - /// Enable or disable the receiving of the `SO_TIMESTAMP` control message. - ReceiveTimestamp, Both, libc::SOL_SOCKET, libc::SO_TIMESTAMP, bool); -#[cfg(all(target_os = "linux"))] -sockopt_impl!( - /// Enable or disable the receiving of the `SO_TIMESTAMPNS` control message. - ReceiveTimestampns, Both, libc::SOL_SOCKET, libc::SO_TIMESTAMPNS, bool); -#[cfg(any(target_os = "android", target_os = "linux"))] -sockopt_impl!( - /// Setting this boolean option enables transparent proxying on this socket. - IpTransparent, Both, libc::SOL_IP, libc::IP_TRANSPARENT, bool); -#[cfg(target_os = "openbsd")] -sockopt_impl!( - /// Allows the socket to be bound to addresses which are not local to the - /// machine, so it can be used to make a transparent proxy. - BindAny, Both, libc::SOL_SOCKET, libc::SO_BINDANY, bool); -#[cfg(target_os = "freebsd")] -sockopt_impl!( - /// Can `bind(2)` to any address, even one not bound to any available - /// network interface in the system. - BindAny, Both, libc::IPPROTO_IP, libc::IP_BINDANY, bool); -#[cfg(target_os = "linux")] -sockopt_impl!( - /// Set the mark for each packet sent through this socket (similar to the - /// netfilter MARK target but socket-based). - Mark, Both, libc::SOL_SOCKET, libc::SO_MARK, u32); -#[cfg(any(target_os = "android", target_os = "linux"))] -sockopt_impl!( - /// Enable or disable the receiving of the `SCM_CREDENTIALS` control - /// message. - PassCred, Both, libc::SOL_SOCKET, libc::SO_PASSCRED, bool); -#[cfg(any(target_os = "freebsd", target_os = "linux"))] -sockopt_impl!( - /// This option allows the caller to set the TCP congestion control - /// algorithm to be used, on a per-socket basis. - TcpCongestion, Both, libc::IPPROTO_TCP, libc::TCP_CONGESTION, OsString<[u8; TCP_CA_NAME_MAX]>); -#[cfg(any( - target_os = "android", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", -))] -sockopt_impl!( - /// Pass an `IP_PKTINFO` ancillary message that contains a pktinfo - /// structure that supplies some information about the incoming packet. - Ipv4PacketInfo, Both, libc::IPPROTO_IP, libc::IP_PKTINFO, bool); -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -))] -sockopt_impl!( - /// Set delivery of the `IPV6_PKTINFO` control message on incoming - /// datagrams. - Ipv6RecvPacketInfo, Both, libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO, bool); -#[cfg(any( - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -))] -sockopt_impl!( - /// The `recvmsg(2)` call returns a `struct sockaddr_dl` corresponding to - /// the interface on which the packet was received. - Ipv4RecvIf, Both, libc::IPPROTO_IP, libc::IP_RECVIF, bool); -#[cfg(any( - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -))] -sockopt_impl!( - /// The `recvmsg(2)` call will return the destination IP address for a UDP - /// datagram. - Ipv4RecvDstAddr, Both, libc::IPPROTO_IP, libc::IP_RECVDSTADDR, bool); -#[cfg(target_os = "linux")] -sockopt_impl!( - #[allow(missing_docs)] - // Not documented by Linux! - UdpGsoSegment, Both, libc::SOL_UDP, libc::UDP_SEGMENT, libc::c_int); -#[cfg(target_os = "linux")] -sockopt_impl!( - #[allow(missing_docs)] - // Not documented by Linux! - UdpGroSegment, Both, libc::IPPROTO_UDP, libc::UDP_GRO, bool); -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] -sockopt_impl!( - /// Indicates that an unsigned 32-bit value ancillary message (cmsg) should - /// be attached to received skbs indicating the number of packets dropped by - /// the socket since its creation. - RxqOvfl, Both, libc::SOL_SOCKET, libc::SO_RXQ_OVFL, libc::c_int); -sockopt_impl!( - /// The socket is restricted to sending and receiving IPv6 packets only. - Ipv6V6Only, Both, libc::IPPROTO_IPV6, libc::IPV6_V6ONLY, bool); -#[cfg(any(target_os = "android", target_os = "linux"))] -sockopt_impl!( - /// Enable extended reliable error message passing. - Ipv4RecvErr, Both, libc::IPPROTO_IP, libc::IP_RECVERR, bool); -#[cfg(any(target_os = "android", target_os = "linux"))] -sockopt_impl!( - /// Control receiving of asynchronous error options. - Ipv6RecvErr, Both, libc::IPPROTO_IPV6, libc::IPV6_RECVERR, bool); -#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] -sockopt_impl!( - /// Set or retrieve the current time-to-live field that is used in every - /// packet sent from this socket. - Ipv4Ttl, Both, libc::IPPROTO_IP, libc::IP_TTL, libc::c_int); -#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] -sockopt_impl!( - /// Set the unicast hop limit for the socket. - Ipv6Ttl, Both, libc::IPPROTO_IPV6, libc::IPV6_UNICAST_HOPS, libc::c_int); - -#[allow(missing_docs)] -// Not documented by Linux! -#[cfg(any(target_os = "android", target_os = "linux"))] -#[derive(Copy, Clone, Debug)] -pub struct AlgSetAeadAuthSize; - -// ALG_SET_AEAD_AUTH_SIZE read the length from passed `option_len` -// See https://elixir.bootlin.com/linux/v4.4/source/crypto/af_alg.c#L222 -#[cfg(any(target_os = "android", target_os = "linux"))] -impl SetSockOpt for AlgSetAeadAuthSize { - type Val = usize; - - fn set(&self, fd: RawFd, val: &usize) -> Result<()> { - unsafe { - let res = libc::setsockopt(fd, - libc::SOL_ALG, - libc::ALG_SET_AEAD_AUTHSIZE, - ::std::ptr::null(), - *val as libc::socklen_t); - Errno::result(res).map(drop) - } - } -} - -#[allow(missing_docs)] -// Not documented by Linux! -#[cfg(any(target_os = "android", target_os = "linux"))] -#[derive(Clone, Debug)] -pub struct AlgSetKey(::std::marker::PhantomData); - -#[cfg(any(target_os = "android", target_os = "linux"))] -impl Default for AlgSetKey { - fn default() -> Self { - AlgSetKey(Default::default()) - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -impl SetSockOpt for AlgSetKey where T: AsRef<[u8]> + Clone { - type Val = T; - - fn set(&self, fd: RawFd, val: &T) -> Result<()> { - unsafe { - let res = libc::setsockopt(fd, - libc::SOL_ALG, - libc::ALG_SET_KEY, - val.as_ref().as_ptr() as *const _, - val.as_ref().len() as libc::socklen_t); - Errno::result(res).map(drop) - } - } -} - -/* - * - * ===== Accessor helpers ===== - * - */ - -/// Helper trait that describes what is expected from a `GetSockOpt` getter. -trait Get { - /// Returns an uninitialized value. - fn uninit() -> Self; - /// Returns a pointer to the stored value. This pointer will be passed to the system's - /// `getsockopt` call (`man 3p getsockopt`, argument `option_value`). - fn ffi_ptr(&mut self) -> *mut c_void; - /// Returns length of the stored value. This pointer will be passed to the system's - /// `getsockopt` call (`man 3p getsockopt`, argument `option_len`). - fn ffi_len(&mut self) -> *mut socklen_t; - /// Returns the hopefully initialized inner value. - unsafe fn assume_init(self) -> T; -} - -/// Helper trait that describes what is expected from a `SetSockOpt` setter. -trait Set<'a, T> { - /// Initialize the setter with a given value. - fn new(val: &'a T) -> Self; - /// Returns a pointer to the stored value. This pointer will be passed to the system's - /// `setsockopt` call (`man 3p setsockopt`, argument `option_value`). - fn ffi_ptr(&self) -> *const c_void; - /// Returns length of the stored value. This pointer will be passed to the system's - /// `setsockopt` call (`man 3p setsockopt`, argument `option_len`). - fn ffi_len(&self) -> socklen_t; -} - -/// Getter for an arbitrary `struct`. -struct GetStruct { - len: socklen_t, - val: MaybeUninit, -} - -impl Get for GetStruct { - fn uninit() -> Self { - GetStruct { - len: mem::size_of::() as socklen_t, - val: MaybeUninit::uninit(), - } - } - - fn ffi_ptr(&mut self) -> *mut c_void { - self.val.as_mut_ptr() as *mut c_void - } - - fn ffi_len(&mut self) -> *mut socklen_t { - &mut self.len - } - - unsafe fn assume_init(self) -> T { - assert_eq!(self.len as usize, mem::size_of::(), "invalid getsockopt implementation"); - self.val.assume_init() - } -} - -/// Setter for an arbitrary `struct`. -struct SetStruct<'a, T: 'static> { - ptr: &'a T, -} - -impl<'a, T> Set<'a, T> for SetStruct<'a, T> { - fn new(ptr: &'a T) -> SetStruct<'a, T> { - SetStruct { ptr } - } - - fn ffi_ptr(&self) -> *const c_void { - self.ptr as *const T as *const c_void - } - - fn ffi_len(&self) -> socklen_t { - mem::size_of::() as socklen_t - } -} - -/// Getter for a boolean value. -struct GetBool { - len: socklen_t, - val: MaybeUninit, -} - -impl Get for GetBool { - fn uninit() -> Self { - GetBool { - len: mem::size_of::() as socklen_t, - val: MaybeUninit::uninit(), - } - } - - fn ffi_ptr(&mut self) -> *mut c_void { - self.val.as_mut_ptr() as *mut c_void - } - - fn ffi_len(&mut self) -> *mut socklen_t { - &mut self.len - } - - unsafe fn assume_init(self) -> bool { - assert_eq!(self.len as usize, mem::size_of::(), "invalid getsockopt implementation"); - self.val.assume_init() != 0 - } -} - -/// Setter for a boolean value. -struct SetBool { - val: c_int, -} - -impl<'a> Set<'a, bool> for SetBool { - fn new(val: &'a bool) -> SetBool { - SetBool { val: if *val { 1 } else { 0 } } - } - - fn ffi_ptr(&self) -> *const c_void { - &self.val as *const c_int as *const c_void - } - - fn ffi_len(&self) -> socklen_t { - mem::size_of::() as socklen_t - } -} - -/// Getter for an `u8` value. -struct GetU8 { - len: socklen_t, - val: MaybeUninit, -} - -impl Get for GetU8 { - fn uninit() -> Self { - GetU8 { - len: mem::size_of::() as socklen_t, - val: MaybeUninit::uninit(), - } - } - - fn ffi_ptr(&mut self) -> *mut c_void { - self.val.as_mut_ptr() as *mut c_void - } - - fn ffi_len(&mut self) -> *mut socklen_t { - &mut self.len - } - - unsafe fn assume_init(self) -> u8 { - assert_eq!(self.len as usize, mem::size_of::(), "invalid getsockopt implementation"); - self.val.assume_init() - } -} - -/// Setter for an `u8` value. -struct SetU8 { - val: u8, -} - -impl<'a> Set<'a, u8> for SetU8 { - fn new(val: &'a u8) -> SetU8 { - SetU8 { val: *val as u8 } - } - - fn ffi_ptr(&self) -> *const c_void { - &self.val as *const u8 as *const c_void - } - - fn ffi_len(&self) -> socklen_t { - mem::size_of::() as socklen_t - } -} - -/// Getter for an `usize` value. -struct GetUsize { - len: socklen_t, - val: MaybeUninit, -} - -impl Get for GetUsize { - fn uninit() -> Self { - GetUsize { - len: mem::size_of::() as socklen_t, - val: MaybeUninit::uninit(), - } - } - - fn ffi_ptr(&mut self) -> *mut c_void { - self.val.as_mut_ptr() as *mut c_void - } - - fn ffi_len(&mut self) -> *mut socklen_t { - &mut self.len - } - - unsafe fn assume_init(self) -> usize { - assert_eq!(self.len as usize, mem::size_of::(), "invalid getsockopt implementation"); - self.val.assume_init() as usize - } -} - -/// Setter for an `usize` value. -struct SetUsize { - val: c_int, -} - -impl<'a> Set<'a, usize> for SetUsize { - fn new(val: &'a usize) -> SetUsize { - SetUsize { val: *val as c_int } - } - - fn ffi_ptr(&self) -> *const c_void { - &self.val as *const c_int as *const c_void - } - - fn ffi_len(&self) -> socklen_t { - mem::size_of::() as socklen_t - } -} - -/// Getter for a `OsString` value. -struct GetOsString> { - len: socklen_t, - val: MaybeUninit, -} - -impl> Get for GetOsString { - fn uninit() -> Self { - GetOsString { - len: mem::size_of::() as socklen_t, - val: MaybeUninit::uninit(), - } - } - - fn ffi_ptr(&mut self) -> *mut c_void { - self.val.as_mut_ptr() as *mut c_void - } - - fn ffi_len(&mut self) -> *mut socklen_t { - &mut self.len - } - - unsafe fn assume_init(self) -> OsString { - let len = self.len as usize; - let mut v = self.val.assume_init(); - OsStr::from_bytes(&v.as_mut()[0..len]).to_owned() - } -} - -/// Setter for a `OsString` value. -struct SetOsString<'a> { - val: &'a OsStr, -} - -impl<'a> Set<'a, OsString> for SetOsString<'a> { - fn new(val: &'a OsString) -> SetOsString { - SetOsString { val: val.as_os_str() } - } - - fn ffi_ptr(&self) -> *const c_void { - self.val.as_bytes().as_ptr() as *const c_void - } - - fn ffi_len(&self) -> socklen_t { - self.val.len() as socklen_t - } -} - - -#[cfg(test)] -mod test { - #[cfg(any(target_os = "android", target_os = "linux"))] - #[test] - fn can_get_peercred_on_unix_socket() { - use super::super::*; - - let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap(); - let a_cred = getsockopt(a, super::PeerCredentials).unwrap(); - let b_cred = getsockopt(b, super::PeerCredentials).unwrap(); - assert_eq!(a_cred, b_cred); - assert!(a_cred.pid() != 0); - } - - #[test] - fn is_socket_type_unix() { - use super::super::*; - use crate::unistd::close; - - let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap(); - let a_type = getsockopt(a, super::SockType).unwrap(); - assert_eq!(a_type, SockType::Stream); - close(a).unwrap(); - close(b).unwrap(); - } - - #[test] - fn is_socket_type_dgram() { - use super::super::*; - use crate::unistd::close; - - let s = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap(); - let s_type = getsockopt(s, super::SockType).unwrap(); - assert_eq!(s_type, SockType::Datagram); - close(s).unwrap(); - } - - #[cfg(any(target_os = "freebsd", - target_os = "linux", - target_os = "nacl"))] - #[test] - fn can_get_listen_on_tcp_socket() { - use super::super::*; - use crate::unistd::close; - - let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap(); - let s_listening = getsockopt(s, super::AcceptConn).unwrap(); - assert!(!s_listening); - listen(s, 10).unwrap(); - let s_listening2 = getsockopt(s, super::AcceptConn).unwrap(); - assert!(s_listening2); - close(s).unwrap(); - } - -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/stat.rs b/vendor/nix-v0.23.1-patched/src/sys/stat.rs deleted file mode 100644 index c8f10419c..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/stat.rs +++ /dev/null @@ -1,315 +0,0 @@ -pub use libc::{dev_t, mode_t}; -pub use libc::stat as FileStat; - -use crate::{Result, NixPath, errno::Errno}; -#[cfg(not(target_os = "redox"))] -use crate::fcntl::{AtFlags, at_rawfd}; -use std::mem; -use std::os::unix::io::RawFd; -use crate::sys::time::{TimeSpec, TimeVal}; - -libc_bitflags!( - /// "File type" flags for `mknod` and related functions. - pub struct SFlag: mode_t { - S_IFIFO; - S_IFCHR; - S_IFDIR; - S_IFBLK; - S_IFREG; - S_IFLNK; - S_IFSOCK; - S_IFMT; - } -); - -libc_bitflags! { - /// "File mode / permissions" flags. - pub struct Mode: mode_t { - S_IRWXU; - S_IRUSR; - S_IWUSR; - S_IXUSR; - S_IRWXG; - S_IRGRP; - S_IWGRP; - S_IXGRP; - S_IRWXO; - S_IROTH; - S_IWOTH; - S_IXOTH; - S_ISUID as mode_t; - S_ISGID as mode_t; - S_ISVTX as mode_t; - } -} - -/// Create a special or ordinary file, by pathname. -pub fn mknod(path: &P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> { - let res = path.with_nix_path(|cstr| unsafe { - libc::mknod(cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev) - })?; - - Errno::result(res).map(drop) -} - -/// Create a special or ordinary file, relative to a given directory. -#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))] -pub fn mknodat( - dirfd: RawFd, - path: &P, - kind: SFlag, - perm: Mode, - dev: dev_t, -) -> Result<()> { - let res = path.with_nix_path(|cstr| unsafe { - libc::mknodat(dirfd, cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev) - })?; - - Errno::result(res).map(drop) -} - -#[cfg(target_os = "linux")] -pub const fn major(dev: dev_t) -> u64 { - ((dev >> 32) & 0xffff_f000) | - ((dev >> 8) & 0x0000_0fff) -} - -#[cfg(target_os = "linux")] -pub const fn minor(dev: dev_t) -> u64 { - ((dev >> 12) & 0xffff_ff00) | - ((dev ) & 0x0000_00ff) -} - -#[cfg(target_os = "linux")] -pub const fn makedev(major: u64, minor: u64) -> dev_t { - ((major & 0xffff_f000) << 32) | - ((major & 0x0000_0fff) << 8) | - ((minor & 0xffff_ff00) << 12) | - (minor & 0x0000_00ff) -} - -pub fn umask(mode: Mode) -> Mode { - let prev = unsafe { libc::umask(mode.bits() as mode_t) }; - Mode::from_bits(prev).expect("[BUG] umask returned invalid Mode") -} - -pub fn stat(path: &P) -> Result { - let mut dst = mem::MaybeUninit::uninit(); - let res = path.with_nix_path(|cstr| { - unsafe { - libc::stat(cstr.as_ptr(), dst.as_mut_ptr()) - } - })?; - - Errno::result(res)?; - - Ok(unsafe{dst.assume_init()}) -} - -pub fn lstat(path: &P) -> Result { - let mut dst = mem::MaybeUninit::uninit(); - let res = path.with_nix_path(|cstr| { - unsafe { - libc::lstat(cstr.as_ptr(), dst.as_mut_ptr()) - } - })?; - - Errno::result(res)?; - - Ok(unsafe{dst.assume_init()}) -} - -pub fn fstat(fd: RawFd) -> Result { - let mut dst = mem::MaybeUninit::uninit(); - let res = unsafe { libc::fstat(fd, dst.as_mut_ptr()) }; - - Errno::result(res)?; - - Ok(unsafe{dst.assume_init()}) -} - -#[cfg(not(target_os = "redox"))] -pub fn fstatat(dirfd: RawFd, pathname: &P, f: AtFlags) -> Result { - let mut dst = mem::MaybeUninit::uninit(); - let res = pathname.with_nix_path(|cstr| { - unsafe { libc::fstatat(dirfd, cstr.as_ptr(), dst.as_mut_ptr(), f.bits() as libc::c_int) } - })?; - - Errno::result(res)?; - - Ok(unsafe{dst.assume_init()}) -} - -/// Change the file permission bits of the file specified by a file descriptor. -/// -/// # References -/// -/// [fchmod(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html). -pub fn fchmod(fd: RawFd, mode: Mode) -> Result<()> { - let res = unsafe { libc::fchmod(fd, mode.bits() as mode_t) }; - - Errno::result(res).map(drop) -} - -/// Flags for `fchmodat` function. -#[derive(Clone, Copy, Debug)] -pub enum FchmodatFlags { - FollowSymlink, - NoFollowSymlink, -} - -/// Change the file permission bits. -/// -/// The file to be changed is determined relative to the directory associated -/// with the file descriptor `dirfd` or the current working directory -/// if `dirfd` is `None`. -/// -/// If `flag` is `FchmodatFlags::NoFollowSymlink` and `path` names a symbolic link, -/// then the mode of the symbolic link is changed. -/// -/// `fchmodat(None, path, mode, FchmodatFlags::FollowSymlink)` is identical to -/// a call `libc::chmod(path, mode)`. That's why `chmod` is unimplemented -/// in the `nix` crate. -/// -/// # References -/// -/// [fchmodat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html). -#[cfg(not(target_os = "redox"))] -pub fn fchmodat( - dirfd: Option, - path: &P, - mode: Mode, - flag: FchmodatFlags, -) -> Result<()> { - let atflag = - match flag { - FchmodatFlags::FollowSymlink => AtFlags::empty(), - FchmodatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW, - }; - let res = path.with_nix_path(|cstr| unsafe { - libc::fchmodat( - at_rawfd(dirfd), - cstr.as_ptr(), - mode.bits() as mode_t, - atflag.bits() as libc::c_int, - ) - })?; - - Errno::result(res).map(drop) -} - -/// Change the access and modification times of a file. -/// -/// `utimes(path, times)` is identical to -/// `utimensat(None, path, times, UtimensatFlags::FollowSymlink)`. The former -/// is a deprecated API so prefer using the latter if the platforms you care -/// about support it. -/// -/// # References -/// -/// [utimes(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimes.html). -pub fn utimes(path: &P, atime: &TimeVal, mtime: &TimeVal) -> Result<()> { - let times: [libc::timeval; 2] = [*atime.as_ref(), *mtime.as_ref()]; - let res = path.with_nix_path(|cstr| unsafe { - libc::utimes(cstr.as_ptr(), ×[0]) - })?; - - Errno::result(res).map(drop) -} - -/// Change the access and modification times of a file without following symlinks. -/// -/// `lutimes(path, times)` is identical to -/// `utimensat(None, path, times, UtimensatFlags::NoFollowSymlink)`. The former -/// is a deprecated API so prefer using the latter if the platforms you care -/// about support it. -/// -/// # References -/// -/// [lutimes(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lutimes.html). -#[cfg(any(target_os = "linux", - target_os = "haiku", - target_os = "ios", - target_os = "macos", - target_os = "freebsd", - target_os = "netbsd"))] -pub fn lutimes(path: &P, atime: &TimeVal, mtime: &TimeVal) -> Result<()> { - let times: [libc::timeval; 2] = [*atime.as_ref(), *mtime.as_ref()]; - let res = path.with_nix_path(|cstr| unsafe { - libc::lutimes(cstr.as_ptr(), ×[0]) - })?; - - Errno::result(res).map(drop) -} - -/// Change the access and modification times of the file specified by a file descriptor. -/// -/// # References -/// -/// [futimens(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html). -#[inline] -pub fn futimens(fd: RawFd, atime: &TimeSpec, mtime: &TimeSpec) -> Result<()> { - let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()]; - let res = unsafe { libc::futimens(fd, ×[0]) }; - - Errno::result(res).map(drop) -} - -/// Flags for `utimensat` function. -// TODO: replace with fcntl::AtFlags -#[derive(Clone, Copy, Debug)] -pub enum UtimensatFlags { - FollowSymlink, - NoFollowSymlink, -} - -/// Change the access and modification times of a file. -/// -/// The file to be changed is determined relative to the directory associated -/// with the file descriptor `dirfd` or the current working directory -/// if `dirfd` is `None`. -/// -/// If `flag` is `UtimensatFlags::NoFollowSymlink` and `path` names a symbolic link, -/// then the mode of the symbolic link is changed. -/// -/// `utimensat(None, path, times, UtimensatFlags::FollowSymlink)` is identical to -/// `utimes(path, times)`. The latter is a deprecated API so prefer using the -/// former if the platforms you care about support it. -/// -/// # References -/// -/// [utimensat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimens.html). -#[cfg(not(target_os = "redox"))] -pub fn utimensat( - dirfd: Option, - path: &P, - atime: &TimeSpec, - mtime: &TimeSpec, - flag: UtimensatFlags -) -> Result<()> { - let atflag = - match flag { - UtimensatFlags::FollowSymlink => AtFlags::empty(), - UtimensatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW, - }; - let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()]; - let res = path.with_nix_path(|cstr| unsafe { - libc::utimensat( - at_rawfd(dirfd), - cstr.as_ptr(), - ×[0], - atflag.bits() as libc::c_int, - ) - })?; - - Errno::result(res).map(drop) -} - -#[cfg(not(target_os = "redox"))] -pub fn mkdirat(fd: RawFd, path: &P, mode: Mode) -> Result<()> { - let res = path.with_nix_path(|cstr| { - unsafe { libc::mkdirat(fd, cstr.as_ptr(), mode.bits() as mode_t) } - })?; - - Errno::result(res).map(drop) -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/statfs.rs b/vendor/nix-v0.23.1-patched/src/sys/statfs.rs deleted file mode 100644 index 829be57f6..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/statfs.rs +++ /dev/null @@ -1,622 +0,0 @@ -//! Get filesystem statistics, non-portably -//! -//! See [`statvfs`](crate::sys::statvfs) for a portable alternative. -use std::fmt::{self, Debug}; -use std::mem; -use std::os::unix::io::AsRawFd; -#[cfg(not(any(target_os = "linux", target_os = "android")))] -use std::ffi::CStr; - -use crate::{NixPath, Result, errno::Errno}; - -/// Identifies a mounted file system -#[cfg(target_os = "android")] -pub type fsid_t = libc::__fsid_t; -/// Identifies a mounted file system -#[cfg(not(target_os = "android"))] -pub type fsid_t = libc::fsid_t; - -/// Describes a mounted file system -#[derive(Clone, Copy)] -#[repr(transparent)] -pub struct Statfs(libc::statfs); - -#[cfg(target_os = "freebsd")] -type fs_type_t = u32; -#[cfg(target_os = "android")] -type fs_type_t = libc::c_ulong; -#[cfg(all(target_os = "linux", target_arch = "s390x"))] -type fs_type_t = libc::c_uint; -#[cfg(all(target_os = "linux", target_env = "musl"))] -type fs_type_t = libc::c_ulong; -#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))] -type fs_type_t = libc::__fsword_t; - -/// Describes the file system type as known by the operating system. -#[cfg(any( - target_os = "freebsd", - target_os = "android", - all(target_os = "linux", target_arch = "s390x"), - all(target_os = "linux", target_env = "musl"), - all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))), -))] -#[derive(Eq, Copy, Clone, PartialEq, Debug)] -pub struct FsType(pub fs_type_t); - -// These constants are defined without documentation in the Linux headers, so we -// can't very well document them here. -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const ADFS_SUPER_MAGIC: FsType = FsType(libc::ADFS_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const AFFS_SUPER_MAGIC: FsType = FsType(libc::AFFS_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const CODA_SUPER_MAGIC: FsType = FsType(libc::CODA_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const EXT2_SUPER_MAGIC: FsType = FsType(libc::EXT2_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const HPFS_SUPER_MAGIC: FsType = FsType(libc::HPFS_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const ISOFS_SUPER_MAGIC: FsType = FsType(libc::ISOFS_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const JFFS2_SUPER_MAGIC: FsType = FsType(libc::JFFS2_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const MINIX_SUPER_MAGIC: FsType = FsType(libc::MINIX_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const MINIX_SUPER_MAGIC2: FsType = FsType(libc::MINIX_SUPER_MAGIC2 as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const MINIX2_SUPER_MAGIC: FsType = FsType(libc::MINIX2_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const MINIX2_SUPER_MAGIC2: FsType = FsType(libc::MINIX2_SUPER_MAGIC2 as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const MSDOS_SUPER_MAGIC: FsType = FsType(libc::MSDOS_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const OPENPROM_SUPER_MAGIC: FsType = FsType(libc::OPENPROM_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const OVERLAYFS_SUPER_MAGIC: FsType = FsType(libc::OVERLAYFS_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const PROC_SUPER_MAGIC: FsType = FsType(libc::PROC_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const QNX4_SUPER_MAGIC: FsType = FsType(libc::QNX4_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const REISERFS_SUPER_MAGIC: FsType = FsType(libc::REISERFS_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const USBDEVICE_SUPER_MAGIC: FsType = FsType(libc::USBDEVICE_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const CGROUP_SUPER_MAGIC: FsType = FsType(libc::CGROUP_SUPER_MAGIC as fs_type_t); -#[cfg(all(target_os = "linux", not(target_env = "musl")))] -#[allow(missing_docs)] -pub const CGROUP2_SUPER_MAGIC: FsType = FsType(libc::CGROUP2_SUPER_MAGIC as fs_type_t); - - -impl Statfs { - /// Magic code defining system type - #[cfg(not(any( - target_os = "openbsd", - target_os = "dragonfly", - target_os = "ios", - target_os = "macos" - )))] - pub fn filesystem_type(&self) -> FsType { - FsType(self.0.f_type) - } - - /// Magic code defining system type - #[cfg(not(any(target_os = "linux", target_os = "android")))] - pub fn filesystem_type_name(&self) -> &str { - let c_str = unsafe { CStr::from_ptr(self.0.f_fstypename.as_ptr()) }; - c_str.to_str().unwrap() - } - - /// Optimal transfer block size - #[cfg(any(target_os = "ios", target_os = "macos"))] - pub fn optimal_transfer_size(&self) -> i32 { - self.0.f_iosize - } - - /// Optimal transfer block size - #[cfg(target_os = "openbsd")] - pub fn optimal_transfer_size(&self) -> u32 { - self.0.f_iosize - } - - /// Optimal transfer block size - #[cfg(all(target_os = "linux", target_arch = "s390x"))] - pub fn optimal_transfer_size(&self) -> u32 { - self.0.f_bsize - } - - /// Optimal transfer block size - #[cfg(any( - target_os = "android", - all(target_os = "linux", target_env = "musl") - ))] - pub fn optimal_transfer_size(&self) -> libc::c_ulong { - self.0.f_bsize - } - - /// Optimal transfer block size - #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))] - pub fn optimal_transfer_size(&self) -> libc::__fsword_t { - self.0.f_bsize - } - - /// Optimal transfer block size - #[cfg(target_os = "dragonfly")] - pub fn optimal_transfer_size(&self) -> libc::c_long { - self.0.f_iosize - } - - /// Optimal transfer block size - #[cfg(target_os = "freebsd")] - pub fn optimal_transfer_size(&self) -> u64 { - self.0.f_iosize - } - - /// Size of a block - #[cfg(any(target_os = "ios", target_os = "macos", target_os = "openbsd"))] - pub fn block_size(&self) -> u32 { - self.0.f_bsize - } - - /// Size of a block - // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471 - #[cfg(all(target_os = "linux", target_arch = "s390x"))] - pub fn block_size(&self) -> u32 { - self.0.f_bsize - } - - /// Size of a block - // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471 - #[cfg(all(target_os = "linux", target_env = "musl"))] - pub fn block_size(&self) -> libc::c_ulong { - self.0.f_bsize - } - - /// Size of a block - // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471 - #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))] - pub fn block_size(&self) -> libc::__fsword_t { - self.0.f_bsize - } - - /// Size of a block - #[cfg(target_os = "freebsd")] - pub fn block_size(&self) -> u64 { - self.0.f_bsize - } - - /// Size of a block - #[cfg(target_os = "android")] - pub fn block_size(&self) -> libc::c_ulong { - self.0.f_bsize - } - - /// Size of a block - #[cfg(target_os = "dragonfly")] - pub fn block_size(&self) -> libc::c_long { - self.0.f_bsize - } - - /// Maximum length of filenames - #[cfg(any(target_os = "freebsd", target_os = "openbsd"))] - pub fn maximum_name_length(&self) -> u32 { - self.0.f_namemax - } - - /// Maximum length of filenames - #[cfg(all(target_os = "linux", target_arch = "s390x"))] - pub fn maximum_name_length(&self) -> u32 { - self.0.f_namelen - } - - /// Maximum length of filenames - #[cfg(all(target_os = "linux", target_env = "musl"))] - pub fn maximum_name_length(&self) -> libc::c_ulong { - self.0.f_namelen - } - - /// Maximum length of filenames - #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))] - pub fn maximum_name_length(&self) -> libc::__fsword_t { - self.0.f_namelen - } - - /// Maximum length of filenames - #[cfg(target_os = "android")] - pub fn maximum_name_length(&self) -> libc::c_ulong { - self.0.f_namelen - } - - /// Total data blocks in filesystem - #[cfg(any( - target_os = "ios", - target_os = "macos", - target_os = "android", - target_os = "freebsd", - target_os = "openbsd", - ))] - pub fn blocks(&self) -> u64 { - self.0.f_blocks - } - - /// Total data blocks in filesystem - #[cfg(target_os = "dragonfly")] - pub fn blocks(&self) -> libc::c_long { - self.0.f_blocks - } - - /// Total data blocks in filesystem - #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))] - pub fn blocks(&self) -> u64 { - self.0.f_blocks - } - - /// Total data blocks in filesystem - #[cfg(not(any( - target_os = "ios", - target_os = "macos", - target_os = "android", - target_os = "freebsd", - target_os = "openbsd", - target_os = "dragonfly", - all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))) - )))] - pub fn blocks(&self) -> libc::c_ulong { - self.0.f_blocks - } - - /// Free blocks in filesystem - #[cfg(any( - target_os = "ios", - target_os = "macos", - target_os = "android", - target_os = "freebsd", - target_os = "openbsd", - ))] - pub fn blocks_free(&self) -> u64 { - self.0.f_bfree - } - - /// Free blocks in filesystem - #[cfg(target_os = "dragonfly")] - pub fn blocks_free(&self) -> libc::c_long { - self.0.f_bfree - } - - /// Free blocks in filesystem - #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))] - pub fn blocks_free(&self) -> u64 { - self.0.f_bfree - } - - /// Free blocks in filesystem - #[cfg(not(any( - target_os = "ios", - target_os = "macos", - target_os = "android", - target_os = "freebsd", - target_os = "openbsd", - target_os = "dragonfly", - all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))) - )))] - pub fn blocks_free(&self) -> libc::c_ulong { - self.0.f_bfree - } - - /// Free blocks available to unprivileged user - #[cfg(any(target_os = "ios", target_os = "macos", target_os = "android"))] - pub fn blocks_available(&self) -> u64 { - self.0.f_bavail - } - - /// Free blocks available to unprivileged user - #[cfg(target_os = "dragonfly")] - pub fn blocks_available(&self) -> libc::c_long { - self.0.f_bavail - } - - /// Free blocks available to unprivileged user - #[cfg(any(target_os = "freebsd", target_os = "openbsd"))] - pub fn blocks_available(&self) -> i64 { - self.0.f_bavail - } - - /// Free blocks available to unprivileged user - #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))] - pub fn blocks_available(&self) -> u64 { - self.0.f_bavail - } - - /// Free blocks available to unprivileged user - #[cfg(not(any( - target_os = "ios", - target_os = "macos", - target_os = "android", - target_os = "freebsd", - target_os = "openbsd", - target_os = "dragonfly", - all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))) - )))] - pub fn blocks_available(&self) -> libc::c_ulong { - self.0.f_bavail - } - - /// Total file nodes in filesystem - #[cfg(any( - target_os = "ios", - target_os = "macos", - target_os = "android", - target_os = "freebsd", - target_os = "openbsd", - ))] - pub fn files(&self) -> u64 { - self.0.f_files - } - - /// Total file nodes in filesystem - #[cfg(target_os = "dragonfly")] - pub fn files(&self) -> libc::c_long { - self.0.f_files - } - - /// Total file nodes in filesystem - #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))] - pub fn files(&self) -> libc::fsfilcnt_t { - self.0.f_files - } - - /// Total file nodes in filesystem - #[cfg(not(any( - target_os = "ios", - target_os = "macos", - target_os = "android", - target_os = "freebsd", - target_os = "openbsd", - target_os = "dragonfly", - all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))) - )))] - pub fn files(&self) -> libc::c_ulong { - self.0.f_files - } - - /// Free file nodes in filesystem - #[cfg(any( - target_os = "android", - target_os = "ios", - target_os = "macos", - target_os = "openbsd" - ))] - pub fn files_free(&self) -> u64 { - self.0.f_ffree - } - - /// Free file nodes in filesystem - #[cfg(target_os = "dragonfly")] - pub fn files_free(&self) -> libc::c_long { - self.0.f_ffree - } - - /// Free file nodes in filesystem - #[cfg(target_os = "freebsd")] - pub fn files_free(&self) -> i64 { - self.0.f_ffree - } - - /// Free file nodes in filesystem - #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))] - pub fn files_free(&self) -> libc::fsfilcnt_t { - self.0.f_ffree - } - - /// Free file nodes in filesystem - #[cfg(not(any( - target_os = "ios", - target_os = "macos", - target_os = "android", - target_os = "freebsd", - target_os = "openbsd", - target_os = "dragonfly", - all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))) - )))] - pub fn files_free(&self) -> libc::c_ulong { - self.0.f_ffree - } - - /// Filesystem ID - pub fn filesystem_id(&self) -> fsid_t { - self.0.f_fsid - } -} - -impl Debug for Statfs { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Statfs") - .field("optimal_transfer_size", &self.optimal_transfer_size()) - .field("block_size", &self.block_size()) - .field("blocks", &self.blocks()) - .field("blocks_free", &self.blocks_free()) - .field("blocks_available", &self.blocks_available()) - .field("files", &self.files()) - .field("files_free", &self.files_free()) - .field("filesystem_id", &self.filesystem_id()) - .finish() - } -} - -/// Describes a mounted file system. -/// -/// The result is OS-dependent. For a portabable alternative, see -/// [`statvfs`](crate::sys::statvfs::statvfs). -/// -/// # Arguments -/// -/// `path` - Path to any file within the file system to describe -pub fn statfs(path: &P) -> Result { - unsafe { - let mut stat = mem::MaybeUninit::::uninit(); - let res = path.with_nix_path(|path| libc::statfs(path.as_ptr(), stat.as_mut_ptr()))?; - Errno::result(res).map(|_| Statfs(stat.assume_init())) - } -} - -/// Describes a mounted file system. -/// -/// The result is OS-dependent. For a portabable alternative, see -/// [`fstatvfs`](crate::sys::statvfs::fstatvfs). -/// -/// # Arguments -/// -/// `fd` - File descriptor of any open file within the file system to describe -pub fn fstatfs(fd: &T) -> Result { - unsafe { - let mut stat = mem::MaybeUninit::::uninit(); - Errno::result(libc::fstatfs(fd.as_raw_fd(), stat.as_mut_ptr())) - .map(|_| Statfs(stat.assume_init())) - } -} - -#[cfg(test)] -mod test { - use std::fs::File; - - use crate::sys::statfs::*; - use crate::sys::statvfs::*; - use std::path::Path; - - #[test] - fn statfs_call() { - check_statfs("/tmp"); - check_statfs("/dev"); - check_statfs("/run"); - check_statfs("/"); - } - - #[test] - fn fstatfs_call() { - check_fstatfs("/tmp"); - check_fstatfs("/dev"); - check_fstatfs("/run"); - check_fstatfs("/"); - } - - fn check_fstatfs(path: &str) { - if !Path::new(path).exists() { - return; - } - let vfs = statvfs(path.as_bytes()).unwrap(); - let file = File::open(path).unwrap(); - let fs = fstatfs(&file).unwrap(); - assert_fs_equals(fs, vfs); - } - - fn check_statfs(path: &str) { - if !Path::new(path).exists() { - return; - } - let vfs = statvfs(path.as_bytes()).unwrap(); - let fs = statfs(path.as_bytes()).unwrap(); - assert_fs_equals(fs, vfs); - } - - fn assert_fs_equals(fs: Statfs, vfs: Statvfs) { - assert_eq!(fs.files() as u64, vfs.files() as u64); - assert_eq!(fs.blocks() as u64, vfs.blocks() as u64); - assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64); - } - - // This test is ignored because files_free/blocks_free can change after statvfs call and before - // statfs call. - #[test] - #[ignore] - fn statfs_call_strict() { - check_statfs_strict("/tmp"); - check_statfs_strict("/dev"); - check_statfs_strict("/run"); - check_statfs_strict("/"); - } - - // This test is ignored because files_free/blocks_free can change after statvfs call and before - // fstatfs call. - #[test] - #[ignore] - fn fstatfs_call_strict() { - check_fstatfs_strict("/tmp"); - check_fstatfs_strict("/dev"); - check_fstatfs_strict("/run"); - check_fstatfs_strict("/"); - } - - fn check_fstatfs_strict(path: &str) { - if !Path::new(path).exists() { - return; - } - let vfs = statvfs(path.as_bytes()); - let file = File::open(path).unwrap(); - let fs = fstatfs(&file); - assert_fs_equals_strict(fs.unwrap(), vfs.unwrap()) - } - - fn check_statfs_strict(path: &str) { - if !Path::new(path).exists() { - return; - } - let vfs = statvfs(path.as_bytes()); - let fs = statfs(path.as_bytes()); - assert_fs_equals_strict(fs.unwrap(), vfs.unwrap()) - } - - fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) { - assert_eq!(fs.files_free() as u64, vfs.files_free() as u64); - assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64); - assert_eq!(fs.blocks_available() as u64, vfs.blocks_available() as u64); - assert_eq!(fs.files() as u64, vfs.files() as u64); - assert_eq!(fs.blocks() as u64, vfs.blocks() as u64); - assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64); - } -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/statvfs.rs b/vendor/nix-v0.23.1-patched/src/sys/statvfs.rs deleted file mode 100644 index 15e7a7d4a..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/statvfs.rs +++ /dev/null @@ -1,161 +0,0 @@ -//! Get filesystem statistics -//! -//! See [the man pages](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html) -//! for more details. -use std::mem; -use std::os::unix::io::AsRawFd; - -use libc::{self, c_ulong}; - -use crate::{Result, NixPath, errno::Errno}; - -#[cfg(not(target_os = "redox"))] -libc_bitflags!( - /// File system mount Flags - #[repr(C)] - #[derive(Default)] - pub struct FsFlags: c_ulong { - /// Read Only - ST_RDONLY; - /// Do not allow the set-uid bits to have an effect - ST_NOSUID; - /// Do not interpret character or block-special devices - #[cfg(any(target_os = "android", target_os = "linux"))] - ST_NODEV; - /// Do not allow execution of binaries on the filesystem - #[cfg(any(target_os = "android", target_os = "linux"))] - ST_NOEXEC; - /// All IO should be done synchronously - #[cfg(any(target_os = "android", target_os = "linux"))] - ST_SYNCHRONOUS; - /// Allow mandatory locks on the filesystem - #[cfg(any(target_os = "android", target_os = "linux"))] - ST_MANDLOCK; - /// Write on file/directory/symlink - #[cfg(target_os = "linux")] - ST_WRITE; - /// Append-only file - #[cfg(target_os = "linux")] - ST_APPEND; - /// Immutable file - #[cfg(target_os = "linux")] - ST_IMMUTABLE; - /// Do not update access times on files - #[cfg(any(target_os = "android", target_os = "linux"))] - ST_NOATIME; - /// Do not update access times on files - #[cfg(any(target_os = "android", target_os = "linux"))] - ST_NODIRATIME; - /// Update access time relative to modify/change time - #[cfg(any(target_os = "android", all(target_os = "linux", not(target_env = "musl"))))] - ST_RELATIME; - } -); - -/// Wrapper around the POSIX `statvfs` struct -/// -/// For more information see the [`statvfs(3)` man pages](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_statvfs.h.html). -#[repr(transparent)] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct Statvfs(libc::statvfs); - -impl Statvfs { - /// get the file system block size - pub fn block_size(&self) -> c_ulong { - self.0.f_bsize - } - - /// Get the fundamental file system block size - pub fn fragment_size(&self) -> c_ulong { - self.0.f_frsize - } - - /// Get the number of blocks. - /// - /// Units are in units of `fragment_size()` - pub fn blocks(&self) -> libc::fsblkcnt_t { - self.0.f_blocks - } - - /// Get the number of free blocks in the file system - pub fn blocks_free(&self) -> libc::fsblkcnt_t { - self.0.f_bfree - } - - /// Get the number of free blocks for unprivileged users - pub fn blocks_available(&self) -> libc::fsblkcnt_t { - self.0.f_bavail - } - - /// Get the total number of file inodes - pub fn files(&self) -> libc::fsfilcnt_t { - self.0.f_files - } - - /// Get the number of free file inodes - pub fn files_free(&self) -> libc::fsfilcnt_t { - self.0.f_ffree - } - - /// Get the number of free file inodes for unprivileged users - pub fn files_available(&self) -> libc::fsfilcnt_t { - self.0.f_favail - } - - /// Get the file system id - pub fn filesystem_id(&self) -> c_ulong { - self.0.f_fsid - } - - /// Get the mount flags - #[cfg(not(target_os = "redox"))] - pub fn flags(&self) -> FsFlags { - FsFlags::from_bits_truncate(self.0.f_flag) - } - - /// Get the maximum filename length - pub fn name_max(&self) -> c_ulong { - self.0.f_namemax - } - -} - -/// Return a `Statvfs` object with information about the `path` -pub fn statvfs(path: &P) -> Result { - unsafe { - Errno::clear(); - let mut stat = mem::MaybeUninit::::uninit(); - let res = path.with_nix_path(|path| - libc::statvfs(path.as_ptr(), stat.as_mut_ptr()) - )?; - - Errno::result(res).map(|_| Statvfs(stat.assume_init())) - } -} - -/// Return a `Statvfs` object with information about `fd` -pub fn fstatvfs(fd: &T) -> Result { - unsafe { - Errno::clear(); - let mut stat = mem::MaybeUninit::::uninit(); - Errno::result(libc::fstatvfs(fd.as_raw_fd(), stat.as_mut_ptr())) - .map(|_| Statvfs(stat.assume_init())) - } -} - -#[cfg(test)] -mod test { - use std::fs::File; - use crate::sys::statvfs::*; - - #[test] - fn statvfs_call() { - statvfs(&b"/"[..]).unwrap(); - } - - #[test] - fn fstatvfs_call() { - let root = File::open("/").unwrap(); - fstatvfs(&root).unwrap(); - } -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/sysinfo.rs b/vendor/nix-v0.23.1-patched/src/sys/sysinfo.rs deleted file mode 100644 index dc943c1ad..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/sysinfo.rs +++ /dev/null @@ -1,79 +0,0 @@ -use libc::{self, SI_LOAD_SHIFT}; -use std::{cmp, mem}; -use std::time::Duration; - -use crate::Result; -use crate::errno::Errno; - -/// System info structure returned by `sysinfo`. -#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] -#[repr(transparent)] -pub struct SysInfo(libc::sysinfo); - -// The fields are c_ulong on 32-bit linux, u64 on 64-bit linux; x32's ulong is u32 -#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] -type mem_blocks_t = u64; -#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] -type mem_blocks_t = libc::c_ulong; - -impl SysInfo { - /// Returns the load average tuple. - /// - /// The returned values represent the load average over time intervals of - /// 1, 5, and 15 minutes, respectively. - pub fn load_average(&self) -> (f64, f64, f64) { - ( - self.0.loads[0] as f64 / (1 << SI_LOAD_SHIFT) as f64, - self.0.loads[1] as f64 / (1 << SI_LOAD_SHIFT) as f64, - self.0.loads[2] as f64 / (1 << SI_LOAD_SHIFT) as f64, - ) - } - - /// Returns the time since system boot. - pub fn uptime(&self) -> Duration { - // Truncate negative values to 0 - Duration::from_secs(cmp::max(self.0.uptime, 0) as u64) - } - - /// Current number of processes. - pub fn process_count(&self) -> u16 { - self.0.procs - } - - /// Returns the amount of swap memory in Bytes. - pub fn swap_total(&self) -> u64 { - self.scale_mem(self.0.totalswap) - } - - /// Returns the amount of unused swap memory in Bytes. - pub fn swap_free(&self) -> u64 { - self.scale_mem(self.0.freeswap) - } - - /// Returns the total amount of installed RAM in Bytes. - pub fn ram_total(&self) -> u64 { - self.scale_mem(self.0.totalram) - } - - /// Returns the amount of completely unused RAM in Bytes. - /// - /// "Unused" in this context means that the RAM in neither actively used by - /// programs, nor by the operating system as disk cache or buffer. It is - /// "wasted" RAM since it currently serves no purpose. - pub fn ram_unused(&self) -> u64 { - self.scale_mem(self.0.freeram) - } - - fn scale_mem(&self, units: mem_blocks_t) -> u64 { - units as u64 * self.0.mem_unit as u64 - } -} - -/// Returns system information. -/// -/// [See `sysinfo(2)`](https://man7.org/linux/man-pages/man2/sysinfo.2.html). -pub fn sysinfo() -> Result { - let mut info = mem::MaybeUninit::uninit(); - let res = unsafe { libc::sysinfo(info.as_mut_ptr()) }; - Errno::result(res).map(|_| unsafe{ SysInfo(info.assume_init()) }) -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/termios.rs b/vendor/nix-v0.23.1-patched/src/sys/termios.rs deleted file mode 100644 index 01d460803..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/termios.rs +++ /dev/null @@ -1,1016 +0,0 @@ -//! An interface for controlling asynchronous communication ports -//! -//! This interface provides a safe wrapper around the termios subsystem defined by POSIX. The -//! underlying types are all implemented in libc for most platforms and either wrapped in safer -//! types here or exported directly. -//! -//! If you are unfamiliar with the `termios` API, you should first read the -//! [API documentation](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/termios.h.html) and -//! then come back to understand how `nix` safely wraps it. -//! -//! It should be noted that this API incurs some runtime overhead above the base `libc` definitions. -//! As this interface is not used with high-bandwidth information, this should be fine in most -//! cases. The primary cost when using this API is that the `Termios` datatype here duplicates the -//! standard fields of the underlying `termios` struct and uses safe type wrappers for those fields. -//! This means that when crossing the FFI interface to the underlying C library, data is first -//! copied into the underlying `termios` struct, then the operation is done, and the data is copied -//! back (with additional sanity checking) into the safe wrapper types. The `termios` struct is -//! relatively small across all platforms (on the order of 32-64 bytes). -//! -//! The following examples highlight some of the API use cases such that users coming from using C -//! or reading the standard documentation will understand how to use the safe API exposed here. -//! -//! Example disabling processing of the end-of-file control character: -//! -//! ``` -//! # use self::nix::sys::termios::SpecialCharacterIndices::VEOF; -//! # use self::nix::sys::termios::{_POSIX_VDISABLE, Termios}; -//! # let mut termios: Termios = unsafe { std::mem::zeroed() }; -//! termios.control_chars[VEOF as usize] = _POSIX_VDISABLE; -//! ``` -//! -//! The flags within `Termios` are defined as bitfields using the `bitflags` crate. This provides -//! an interface for working with bitfields that is similar to working with the raw unsigned -//! integer types but offers type safety because of the internal checking that values will always -//! be a valid combination of the defined flags. -//! -//! An example showing some of the basic operations for interacting with the control flags: -//! -//! ``` -//! # use self::nix::sys::termios::{ControlFlags, Termios}; -//! # let mut termios: Termios = unsafe { std::mem::zeroed() }; -//! termios.control_flags & ControlFlags::CSIZE == ControlFlags::CS5; -//! termios.control_flags |= ControlFlags::CS5; -//! ``` -//! -//! # Baud rates -//! -//! This API is not consistent across platforms when it comes to `BaudRate`: Android and Linux both -//! only support the rates specified by the `BaudRate` enum through their termios API while the BSDs -//! support arbitrary baud rates as the values of the `BaudRate` enum constants are the same integer -//! value of the constant (`B9600` == `9600`). Therefore the `nix::termios` API uses the following -//! conventions: -//! -//! * `cfgetispeed()` - Returns `u32` on BSDs, `BaudRate` on Android/Linux -//! * `cfgetospeed()` - Returns `u32` on BSDs, `BaudRate` on Android/Linux -//! * `cfsetispeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux -//! * `cfsetospeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux -//! * `cfsetspeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux -//! -//! The most common use case of specifying a baud rate using the enum will work the same across -//! platforms: -//! -//! ```rust -//! # use nix::sys::termios::{BaudRate, cfsetispeed, cfsetospeed, cfsetspeed, Termios}; -//! # fn main() { -//! # let mut t: Termios = unsafe { std::mem::zeroed() }; -//! cfsetispeed(&mut t, BaudRate::B9600); -//! cfsetospeed(&mut t, BaudRate::B9600); -//! cfsetspeed(&mut t, BaudRate::B9600); -//! # } -//! ``` -//! -//! Additionally round-tripping baud rates is consistent across platforms: -//! -//! ```rust -//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetispeed, cfsetspeed, Termios}; -//! # fn main() { -//! # let mut t: Termios = unsafe { std::mem::zeroed() }; -//! # cfsetspeed(&mut t, BaudRate::B9600); -//! let speed = cfgetispeed(&t); -//! assert_eq!(speed, cfgetospeed(&t)); -//! cfsetispeed(&mut t, speed); -//! # } -//! ``` -//! -//! On non-BSDs, `cfgetispeed()` and `cfgetospeed()` both return a `BaudRate`: -//! -#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios", - target_os = "macos", target_os = "netbsd", target_os = "openbsd"), - doc = " ```rust,ignore")] -#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios", - target_os = "macos", target_os = "netbsd", target_os = "openbsd")), - doc = " ```rust")] -//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios}; -//! # fn main() { -//! # let mut t: Termios = unsafe { std::mem::zeroed() }; -//! # cfsetspeed(&mut t, BaudRate::B9600); -//! assert_eq!(cfgetispeed(&t), BaudRate::B9600); -//! assert_eq!(cfgetospeed(&t), BaudRate::B9600); -//! # } -//! ``` -//! -//! But on the BSDs, `cfgetispeed()` and `cfgetospeed()` both return `u32`s: -//! -#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios", - target_os = "macos", target_os = "netbsd", target_os = "openbsd"), - doc = " ```rust")] -#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios", - target_os = "macos", target_os = "netbsd", target_os = "openbsd")), - doc = " ```rust,ignore")] -//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios}; -//! # fn main() { -//! # let mut t: Termios = unsafe { std::mem::zeroed() }; -//! # cfsetspeed(&mut t, 9600u32); -//! assert_eq!(cfgetispeed(&t), 9600u32); -//! assert_eq!(cfgetospeed(&t), 9600u32); -//! # } -//! ``` -//! -//! It's trivial to convert from a `BaudRate` to a `u32` on BSDs: -//! -#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios", - target_os = "macos", target_os = "netbsd", target_os = "openbsd"), - doc = " ```rust")] -#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios", - target_os = "macos", target_os = "netbsd", target_os = "openbsd")), - doc = " ```rust,ignore")] -//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfsetspeed, Termios}; -//! # fn main() { -//! # let mut t: Termios = unsafe { std::mem::zeroed() }; -//! # cfsetspeed(&mut t, 9600u32); -//! assert_eq!(cfgetispeed(&t), BaudRate::B9600.into()); -//! assert_eq!(u32::from(BaudRate::B9600), 9600u32); -//! # } -//! ``` -//! -//! And on BSDs you can specify arbitrary baud rates (**note** this depends on hardware support) -//! by specifying baud rates directly using `u32`s: -//! -#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios", - target_os = "macos", target_os = "netbsd", target_os = "openbsd"), - doc = " ```rust")] -#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios", - target_os = "macos", target_os = "netbsd", target_os = "openbsd")), - doc = " ```rust,ignore")] -//! # use nix::sys::termios::{cfsetispeed, cfsetospeed, cfsetspeed, Termios}; -//! # fn main() { -//! # let mut t: Termios = unsafe { std::mem::zeroed() }; -//! cfsetispeed(&mut t, 9600u32); -//! cfsetospeed(&mut t, 9600u32); -//! cfsetspeed(&mut t, 9600u32); -//! # } -//! ``` -use cfg_if::cfg_if; -use crate::Result; -use crate::errno::Errno; -use libc::{self, c_int, tcflag_t}; -use std::cell::{Ref, RefCell}; -use std::convert::From; -use std::mem; -use std::os::unix::io::RawFd; - -use crate::unistd::Pid; - -/// Stores settings for the termios API -/// -/// This is a wrapper around the `libc::termios` struct that provides a safe interface for the -/// standard fields. The only safe way to obtain an instance of this struct is to extract it from -/// an open port using `tcgetattr()`. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct Termios { - inner: RefCell, - /// Input mode flags (see `termios.c_iflag` documentation) - pub input_flags: InputFlags, - /// Output mode flags (see `termios.c_oflag` documentation) - pub output_flags: OutputFlags, - /// Control mode flags (see `termios.c_cflag` documentation) - pub control_flags: ControlFlags, - /// Local mode flags (see `termios.c_lflag` documentation) - pub local_flags: LocalFlags, - /// Control characters (see `termios.c_cc` documentation) - pub control_chars: [libc::cc_t; NCCS], -} - -impl Termios { - /// Exposes an immutable reference to the underlying `libc::termios` data structure. - /// - /// This is not part of `nix`'s public API because it requires additional work to maintain type - /// safety. - pub(crate) fn get_libc_termios(&self) -> Ref { - { - let mut termios = self.inner.borrow_mut(); - termios.c_iflag = self.input_flags.bits(); - termios.c_oflag = self.output_flags.bits(); - termios.c_cflag = self.control_flags.bits(); - termios.c_lflag = self.local_flags.bits(); - termios.c_cc = self.control_chars; - } - self.inner.borrow() - } - - /// Exposes the inner `libc::termios` datastore within `Termios`. - /// - /// This is unsafe because if this is used to modify the inner `libc::termios` struct, it will - /// not automatically update the safe wrapper type around it. In this case it should also be - /// paired with a call to `update_wrapper()` so that the wrapper-type and internal - /// representation stay consistent. - pub(crate) unsafe fn get_libc_termios_mut(&mut self) -> *mut libc::termios { - { - let mut termios = self.inner.borrow_mut(); - termios.c_iflag = self.input_flags.bits(); - termios.c_oflag = self.output_flags.bits(); - termios.c_cflag = self.control_flags.bits(); - termios.c_lflag = self.local_flags.bits(); - termios.c_cc = self.control_chars; - } - self.inner.as_ptr() - } - - /// Updates the wrapper values from the internal `libc::termios` data structure. - pub(crate) fn update_wrapper(&mut self) { - let termios = *self.inner.borrow_mut(); - self.input_flags = InputFlags::from_bits_truncate(termios.c_iflag); - self.output_flags = OutputFlags::from_bits_truncate(termios.c_oflag); - self.control_flags = ControlFlags::from_bits_truncate(termios.c_cflag); - self.local_flags = LocalFlags::from_bits_truncate(termios.c_lflag); - self.control_chars = termios.c_cc; - } -} - -impl From for Termios { - fn from(termios: libc::termios) -> Self { - Termios { - inner: RefCell::new(termios), - input_flags: InputFlags::from_bits_truncate(termios.c_iflag), - output_flags: OutputFlags::from_bits_truncate(termios.c_oflag), - control_flags: ControlFlags::from_bits_truncate(termios.c_cflag), - local_flags: LocalFlags::from_bits_truncate(termios.c_lflag), - control_chars: termios.c_cc, - } - } -} - -impl From for libc::termios { - fn from(termios: Termios) -> Self { - termios.inner.into_inner() - } -} - -libc_enum!{ - /// Baud rates supported by the system. - /// - /// For the BSDs, arbitrary baud rates can be specified by using `u32`s directly instead of this - /// enum. - /// - /// B0 is special and will disable the port. - #[cfg_attr(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64"), repr(u64))] - #[cfg_attr(not(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64")), repr(u32))] - #[non_exhaustive] - pub enum BaudRate { - B0, - B50, - B75, - B110, - B134, - B150, - B200, - B300, - B600, - B1200, - B1800, - B2400, - B4800, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - B7200, - B9600, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - B14400, - B19200, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - B28800, - B38400, - B57600, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - B76800, - B115200, - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - B153600, - B230400, - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - B307200, - #[cfg(any(target_os = "android", - target_os = "freebsd", - target_os = "illumos", - target_os = "linux", - target_os = "netbsd", - target_os = "solaris"))] - B460800, - #[cfg(any(target_os = "android", target_os = "linux"))] - B500000, - #[cfg(any(target_os = "android", target_os = "linux"))] - B576000, - #[cfg(any(target_os = "android", - target_os = "freebsd", - target_os = "illumos", - target_os = "linux", - target_os = "netbsd", - target_os = "solaris"))] - B921600, - #[cfg(any(target_os = "android", target_os = "linux"))] - B1000000, - #[cfg(any(target_os = "android", target_os = "linux"))] - B1152000, - #[cfg(any(target_os = "android", target_os = "linux"))] - B1500000, - #[cfg(any(target_os = "android", target_os = "linux"))] - B2000000, - #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))] - B2500000, - #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))] - B3000000, - #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))] - B3500000, - #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))] - B4000000, - } - impl TryFrom -} - -#[cfg(any(target_os = "freebsd", - target_os = "dragonfly", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] -impl From for u32 { - fn from(b: BaudRate) -> u32 { - b as u32 - } -} - -// TODO: Add TCSASOFT, which will require treating this as a bitfield. -libc_enum! { - /// Specify when a port configuration change should occur. - /// - /// Used as an argument to `tcsetattr()` - #[repr(i32)] - #[non_exhaustive] - pub enum SetArg { - /// The change will occur immediately - TCSANOW, - /// The change occurs after all output has been written - TCSADRAIN, - /// Same as `TCSADRAIN`, but will also flush the input buffer - TCSAFLUSH, - } -} - -libc_enum! { - /// Specify a combination of the input and output buffers to flush - /// - /// Used as an argument to `tcflush()`. - #[repr(i32)] - #[non_exhaustive] - pub enum FlushArg { - /// Flush data that was received but not read - TCIFLUSH, - /// Flush data written but not transmitted - TCOFLUSH, - /// Flush both received data not read and written data not transmitted - TCIOFLUSH, - } -} - -libc_enum! { - /// Specify how transmission flow should be altered - /// - /// Used as an argument to `tcflow()`. - #[repr(i32)] - #[non_exhaustive] - pub enum FlowArg { - /// Suspend transmission - TCOOFF, - /// Resume transmission - TCOON, - /// Transmit a STOP character, which should disable a connected terminal device - TCIOFF, - /// Transmit a START character, which should re-enable a connected terminal device - TCION, - } -} - -// TODO: Make this usable directly as a slice index. -libc_enum! { - /// Indices into the `termios.c_cc` array for special characters. - #[repr(usize)] - #[non_exhaustive] - pub enum SpecialCharacterIndices { - VDISCARD, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "illumos", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris"))] - VDSUSP, - VEOF, - VEOL, - VEOL2, - VERASE, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "illumos", - target_os = "solaris"))] - VERASE2, - VINTR, - VKILL, - VLNEXT, - #[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"), - target_os = "illumos", target_os = "solaris")))] - VMIN, - VQUIT, - VREPRINT, - VSTART, - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "illumos", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris"))] - VSTATUS, - VSTOP, - VSUSP, - #[cfg(target_os = "linux")] - VSWTC, - #[cfg(any(target_os = "haiku", target_os = "illumos", target_os = "solaris"))] - VSWTCH, - #[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"), - target_os = "illumos", target_os = "solaris")))] - VTIME, - VWERASE, - #[cfg(target_os = "dragonfly")] - VCHECKPT, - } -} - -#[cfg(any(all(target_os = "linux", target_arch = "sparc64"), - target_os = "illumos", target_os = "solaris"))] -impl SpecialCharacterIndices { - pub const VMIN: SpecialCharacterIndices = SpecialCharacterIndices::VEOF; - pub const VTIME: SpecialCharacterIndices = SpecialCharacterIndices::VEOL; -} - -pub use libc::NCCS; -#[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] -pub use libc::_POSIX_VDISABLE; - -libc_bitflags! { - /// Flags for configuring the input mode of a terminal - pub struct InputFlags: tcflag_t { - IGNBRK; - BRKINT; - IGNPAR; - PARMRK; - INPCK; - ISTRIP; - INLCR; - IGNCR; - ICRNL; - IXON; - IXOFF; - #[cfg(not(target_os = "redox"))] - IXANY; - #[cfg(not(target_os = "redox"))] - IMAXBEL; - #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))] - IUTF8; - } -} - -libc_bitflags! { - /// Flags for configuring the output mode of a terminal - pub struct OutputFlags: tcflag_t { - OPOST; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "linux", - target_os = "openbsd"))] - OLCUC; - ONLCR; - OCRNL as tcflag_t; - ONOCR as tcflag_t; - ONLRET as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - OFILL as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - OFDEL as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - NL0 as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - NL1 as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - CR0 as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - CR1 as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - CR2 as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - CR3 as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "freebsd", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - TAB0 as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - TAB1 as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - TAB2 as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "freebsd", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - TAB3 as tcflag_t; - #[cfg(any(target_os = "android", target_os = "linux"))] - XTABS; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - BS0 as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - BS1 as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - VT0 as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - VT1 as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - FF0 as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - FF1 as tcflag_t; - #[cfg(any(target_os = "freebsd", - target_os = "dragonfly", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - OXTABS; - #[cfg(any(target_os = "freebsd", - target_os = "dragonfly", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - ONOEOT as tcflag_t; - - // Bitmasks for use with OutputFlags to select specific settings - // These should be moved to be a mask once https://github.com/rust-lang-nursery/bitflags/issues/110 - // is resolved. - - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - NLDLY as tcflag_t; // FIXME: Datatype needs to be corrected in libc for mac - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - CRDLY as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "freebsd", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - TABDLY as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - BSDLY as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - VTDLY as tcflag_t; - #[cfg(any(target_os = "android", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] - FFDLY as tcflag_t; - } -} - -libc_bitflags! { - /// Flags for setting the control mode of a terminal - pub struct ControlFlags: tcflag_t { - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - CIGNORE; - CS5; - CS6; - CS7; - CS8; - CSTOPB; - CREAD; - PARENB; - PARODD; - HUPCL; - CLOCAL; - #[cfg(not(target_os = "redox"))] - CRTSCTS; - #[cfg(any(target_os = "android", target_os = "linux"))] - CBAUD; - #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "mips"))))] - CMSPAR; - #[cfg(any(target_os = "android", - all(target_os = "linux", - not(any(target_arch = "powerpc", target_arch = "powerpc64")))))] - CIBAUD; - #[cfg(any(target_os = "android", target_os = "linux"))] - CBAUDEX; - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - MDMBUF; - #[cfg(any(target_os = "netbsd", target_os = "openbsd"))] - CHWFLOW; - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "netbsd", - target_os = "openbsd"))] - CCTS_OFLOW; - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "netbsd", - target_os = "openbsd"))] - CRTS_IFLOW; - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd"))] - CDTR_IFLOW; - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd"))] - CDSR_OFLOW; - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd"))] - CCAR_OFLOW; - - // Bitmasks for use with ControlFlags to select specific settings - // These should be moved to be a mask once https://github.com/rust-lang-nursery/bitflags/issues/110 - // is resolved. - - CSIZE; - } -} - -libc_bitflags! { - /// Flags for setting any local modes - pub struct LocalFlags: tcflag_t { - #[cfg(not(target_os = "redox"))] - ECHOKE; - ECHOE; - ECHOK; - ECHO; - ECHONL; - #[cfg(not(target_os = "redox"))] - ECHOPRT; - #[cfg(not(target_os = "redox"))] - ECHOCTL; - ISIG; - ICANON; - #[cfg(any(target_os = "freebsd", - target_os = "dragonfly", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - ALTWERASE; - IEXTEN; - #[cfg(not(target_os = "redox"))] - EXTPROC; - TOSTOP; - #[cfg(not(target_os = "redox"))] - FLUSHO; - #[cfg(any(target_os = "freebsd", - target_os = "dragonfly", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] - NOKERNINFO; - #[cfg(not(target_os = "redox"))] - PENDIN; - NOFLSH; - } -} - -cfg_if!{ - if #[cfg(any(target_os = "freebsd", - target_os = "dragonfly", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] { - /// Get input baud rate (see - /// [cfgetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)). - /// - /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure. - pub fn cfgetispeed(termios: &Termios) -> u32 { - let inner_termios = termios.get_libc_termios(); - unsafe { libc::cfgetispeed(&*inner_termios) as u32 } - } - - /// Get output baud rate (see - /// [cfgetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)). - /// - /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure. - pub fn cfgetospeed(termios: &Termios) -> u32 { - let inner_termios = termios.get_libc_termios(); - unsafe { libc::cfgetospeed(&*inner_termios) as u32 } - } - - /// Set input baud rate (see - /// [cfsetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)). - /// - /// `cfsetispeed()` sets the intput baud rate in the given `Termios` structure. - pub fn cfsetispeed>(termios: &mut Termios, baud: T) -> Result<()> { - let inner_termios = unsafe { termios.get_libc_termios_mut() }; - let res = unsafe { libc::cfsetispeed(inner_termios, baud.into() as libc::speed_t) }; - termios.update_wrapper(); - Errno::result(res).map(drop) - } - - /// Set output baud rate (see - /// [cfsetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)). - /// - /// `cfsetospeed()` sets the output baud rate in the given termios structure. - pub fn cfsetospeed>(termios: &mut Termios, baud: T) -> Result<()> { - let inner_termios = unsafe { termios.get_libc_termios_mut() }; - let res = unsafe { libc::cfsetospeed(inner_termios, baud.into() as libc::speed_t) }; - termios.update_wrapper(); - Errno::result(res).map(drop) - } - - /// Set both the input and output baud rates (see - /// [termios(3)](https://www.freebsd.org/cgi/man.cgi?query=cfsetspeed)). - /// - /// `cfsetspeed()` sets the input and output baud rate in the given termios structure. Note that - /// this is part of the 4.4BSD standard and not part of POSIX. - pub fn cfsetspeed>(termios: &mut Termios, baud: T) -> Result<()> { - let inner_termios = unsafe { termios.get_libc_termios_mut() }; - let res = unsafe { libc::cfsetspeed(inner_termios, baud.into() as libc::speed_t) }; - termios.update_wrapper(); - Errno::result(res).map(drop) - } - } else { - use std::convert::TryInto; - - /// Get input baud rate (see - /// [cfgetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)). - /// - /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure. - pub fn cfgetispeed(termios: &Termios) -> BaudRate { - let inner_termios = termios.get_libc_termios(); - unsafe { libc::cfgetispeed(&*inner_termios) }.try_into().unwrap() - } - - /// Get output baud rate (see - /// [cfgetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)). - /// - /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure. - pub fn cfgetospeed(termios: &Termios) -> BaudRate { - let inner_termios = termios.get_libc_termios(); - unsafe { libc::cfgetospeed(&*inner_termios) }.try_into().unwrap() - } - - /// Set input baud rate (see - /// [cfsetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)). - /// - /// `cfsetispeed()` sets the intput baud rate in the given `Termios` structure. - pub fn cfsetispeed(termios: &mut Termios, baud: BaudRate) -> Result<()> { - let inner_termios = unsafe { termios.get_libc_termios_mut() }; - let res = unsafe { libc::cfsetispeed(inner_termios, baud as libc::speed_t) }; - termios.update_wrapper(); - Errno::result(res).map(drop) - } - - /// Set output baud rate (see - /// [cfsetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)). - /// - /// `cfsetospeed()` sets the output baud rate in the given `Termios` structure. - pub fn cfsetospeed(termios: &mut Termios, baud: BaudRate) -> Result<()> { - let inner_termios = unsafe { termios.get_libc_termios_mut() }; - let res = unsafe { libc::cfsetospeed(inner_termios, baud as libc::speed_t) }; - termios.update_wrapper(); - Errno::result(res).map(drop) - } - - /// Set both the input and output baud rates (see - /// [termios(3)](https://www.freebsd.org/cgi/man.cgi?query=cfsetspeed)). - /// - /// `cfsetspeed()` sets the input and output baud rate in the given `Termios` structure. Note that - /// this is part of the 4.4BSD standard and not part of POSIX. - pub fn cfsetspeed(termios: &mut Termios, baud: BaudRate) -> Result<()> { - let inner_termios = unsafe { termios.get_libc_termios_mut() }; - let res = unsafe { libc::cfsetspeed(inner_termios, baud as libc::speed_t) }; - termios.update_wrapper(); - Errno::result(res).map(drop) - } - } -} - -/// Configures the port to something like the "raw" mode of the old Version 7 terminal driver (see -/// [termios(3)](https://man7.org/linux/man-pages/man3/termios.3.html)). -/// -/// `cfmakeraw()` configures the termios structure such that input is available character-by- -/// character, echoing is disabled, and all special input and output processing is disabled. Note -/// that this is a non-standard function, but is available on Linux and BSDs. -pub fn cfmakeraw(termios: &mut Termios) { - let inner_termios = unsafe { termios.get_libc_termios_mut() }; - unsafe { - libc::cfmakeraw(inner_termios); - } - termios.update_wrapper(); -} - -/// Configures the port to "sane" mode (like the configuration of a newly created terminal) (see -/// [tcsetattr(3)](https://www.freebsd.org/cgi/man.cgi?query=tcsetattr)). -/// -/// Note that this is a non-standard function, available on FreeBSD. -#[cfg(target_os = "freebsd")] -pub fn cfmakesane(termios: &mut Termios) { - let inner_termios = unsafe { termios.get_libc_termios_mut() }; - unsafe { - libc::cfmakesane(inner_termios); - } - termios.update_wrapper(); -} - -/// Return the configuration of a port -/// [tcgetattr(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html)). -/// -/// `tcgetattr()` returns a `Termios` structure with the current configuration for a port. Modifying -/// this structure *will not* reconfigure the port, instead the modifications should be done to -/// the `Termios` structure and then the port should be reconfigured using `tcsetattr()`. -pub fn tcgetattr(fd: RawFd) -> Result { - let mut termios = mem::MaybeUninit::uninit(); - - let res = unsafe { libc::tcgetattr(fd, termios.as_mut_ptr()) }; - - Errno::result(res)?; - - unsafe { Ok(termios.assume_init().into()) } -} - -/// Set the configuration for a terminal (see -/// [tcsetattr(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetattr.html)). -/// -/// `tcsetattr()` reconfigures the given port based on a given `Termios` structure. This change -/// takes affect at a time specified by `actions`. Note that this function may return success if -/// *any* of the parameters were successfully set, not only if all were set successfully. -pub fn tcsetattr(fd: RawFd, actions: SetArg, termios: &Termios) -> Result<()> { - let inner_termios = termios.get_libc_termios(); - Errno::result(unsafe { libc::tcsetattr(fd, actions as c_int, &*inner_termios) }).map(drop) -} - -/// Block until all output data is written (see -/// [tcdrain(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcdrain.html)). -pub fn tcdrain(fd: RawFd) -> Result<()> { - Errno::result(unsafe { libc::tcdrain(fd) }).map(drop) -} - -/// Suspend or resume the transmission or reception of data (see -/// [tcflow(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflow.html)). -/// -/// `tcflow()` suspends of resumes the transmission or reception of data for the given port -/// depending on the value of `action`. -pub fn tcflow(fd: RawFd, action: FlowArg) -> Result<()> { - Errno::result(unsafe { libc::tcflow(fd, action as c_int) }).map(drop) -} - -/// Discard data in the output or input queue (see -/// [tcflush(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflush.html)). -/// -/// `tcflush()` will discard data for a terminal port in the input queue, output queue, or both -/// depending on the value of `action`. -pub fn tcflush(fd: RawFd, action: FlushArg) -> Result<()> { - Errno::result(unsafe { libc::tcflush(fd, action as c_int) }).map(drop) -} - -/// Send a break for a specific duration (see -/// [tcsendbreak(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsendbreak.html)). -/// -/// When using asynchronous data transmission `tcsendbreak()` will transmit a continuous stream -/// of zero-valued bits for an implementation-defined duration. -pub fn tcsendbreak(fd: RawFd, duration: c_int) -> Result<()> { - Errno::result(unsafe { libc::tcsendbreak(fd, duration) }).map(drop) -} - -/// Get the session controlled by the given terminal (see -/// [tcgetsid(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetsid.html)). -pub fn tcgetsid(fd: RawFd) -> Result { - let res = unsafe { libc::tcgetsid(fd) }; - - Errno::result(res).map(Pid::from_raw) -} - -#[cfg(test)] -mod test { - use super::*; - use std::convert::TryFrom; - - #[test] - fn try_from() { - assert_eq!(Ok(BaudRate::B0), BaudRate::try_from(libc::B0)); - assert!(BaudRate::try_from(999999999).is_err()); - } -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/time.rs b/vendor/nix-v0.23.1-patched/src/sys/time.rs deleted file mode 100644 index ac4247180..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/time.rs +++ /dev/null @@ -1,609 +0,0 @@ -use std::{cmp, fmt, ops}; -use std::time::Duration; -use std::convert::From; -use libc::{timespec, timeval}; -#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 -pub use libc::{time_t, suseconds_t}; - -pub trait TimeValLike: Sized { - #[inline] - fn zero() -> Self { - Self::seconds(0) - } - - #[inline] - fn hours(hours: i64) -> Self { - let secs = hours.checked_mul(SECS_PER_HOUR) - .expect("TimeValLike::hours ouf of bounds"); - Self::seconds(secs) - } - - #[inline] - fn minutes(minutes: i64) -> Self { - let secs = minutes.checked_mul(SECS_PER_MINUTE) - .expect("TimeValLike::minutes out of bounds"); - Self::seconds(secs) - } - - fn seconds(seconds: i64) -> Self; - fn milliseconds(milliseconds: i64) -> Self; - fn microseconds(microseconds: i64) -> Self; - fn nanoseconds(nanoseconds: i64) -> Self; - - #[inline] - fn num_hours(&self) -> i64 { - self.num_seconds() / 3600 - } - - #[inline] - fn num_minutes(&self) -> i64 { - self.num_seconds() / 60 - } - - fn num_seconds(&self) -> i64; - fn num_milliseconds(&self) -> i64; - fn num_microseconds(&self) -> i64; - fn num_nanoseconds(&self) -> i64; -} - -#[repr(C)] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct TimeSpec(timespec); - -const NANOS_PER_SEC: i64 = 1_000_000_000; -const SECS_PER_MINUTE: i64 = 60; -const SECS_PER_HOUR: i64 = 3600; - -#[cfg(target_pointer_width = "64")] -const TS_MAX_SECONDS: i64 = (::std::i64::MAX / NANOS_PER_SEC) - 1; - -#[cfg(target_pointer_width = "32")] -const TS_MAX_SECONDS: i64 = ::std::isize::MAX as i64; - -const TS_MIN_SECONDS: i64 = -TS_MAX_SECONDS; - -// x32 compatibility -// See https://sourceware.org/bugzilla/show_bug.cgi?id=16437 -#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] -type timespec_tv_nsec_t = i64; -#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] -type timespec_tv_nsec_t = libc::c_long; - -impl From for TimeSpec { - fn from(ts: timespec) -> Self { - Self(ts) - } -} - -impl From for TimeSpec { - fn from(duration: Duration) -> Self { - Self::from_duration(duration) - } -} - -impl From for Duration { - fn from(timespec: TimeSpec) -> Self { - Duration::new(timespec.0.tv_sec as u64, timespec.0.tv_nsec as u32) - } -} - -impl AsRef for TimeSpec { - fn as_ref(&self) -> ×pec { - &self.0 - } -} - -impl AsMut for TimeSpec { - fn as_mut(&mut self) -> &mut timespec { - &mut self.0 - } -} - -impl Ord for TimeSpec { - // The implementation of cmp is simplified by assuming that the struct is - // normalized. That is, tv_nsec must always be within [0, 1_000_000_000) - fn cmp(&self, other: &TimeSpec) -> cmp::Ordering { - if self.tv_sec() == other.tv_sec() { - self.tv_nsec().cmp(&other.tv_nsec()) - } else { - self.tv_sec().cmp(&other.tv_sec()) - } - } -} - -impl PartialOrd for TimeSpec { - fn partial_cmp(&self, other: &TimeSpec) -> Option { - Some(self.cmp(other)) - } -} - -impl TimeValLike for TimeSpec { - #[inline] - fn seconds(seconds: i64) -> TimeSpec { - assert!(seconds >= TS_MIN_SECONDS && seconds <= TS_MAX_SECONDS, - "TimeSpec out of bounds; seconds={}", seconds); - #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 - TimeSpec(timespec {tv_sec: seconds as time_t, tv_nsec: 0 }) - } - - #[inline] - fn milliseconds(milliseconds: i64) -> TimeSpec { - let nanoseconds = milliseconds.checked_mul(1_000_000) - .expect("TimeSpec::milliseconds out of bounds"); - - TimeSpec::nanoseconds(nanoseconds) - } - - /// Makes a new `TimeSpec` with given number of microseconds. - #[inline] - fn microseconds(microseconds: i64) -> TimeSpec { - let nanoseconds = microseconds.checked_mul(1_000) - .expect("TimeSpec::milliseconds out of bounds"); - - TimeSpec::nanoseconds(nanoseconds) - } - - /// Makes a new `TimeSpec` with given number of nanoseconds. - #[inline] - fn nanoseconds(nanoseconds: i64) -> TimeSpec { - let (secs, nanos) = div_mod_floor_64(nanoseconds, NANOS_PER_SEC); - assert!(secs >= TS_MIN_SECONDS && secs <= TS_MAX_SECONDS, - "TimeSpec out of bounds"); - #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 - TimeSpec(timespec {tv_sec: secs as time_t, - tv_nsec: nanos as timespec_tv_nsec_t }) - } - - fn num_seconds(&self) -> i64 { - if self.tv_sec() < 0 && self.tv_nsec() > 0 { - (self.tv_sec() + 1) as i64 - } else { - self.tv_sec() as i64 - } - } - - fn num_milliseconds(&self) -> i64 { - self.num_nanoseconds() / 1_000_000 - } - - fn num_microseconds(&self) -> i64 { - self.num_nanoseconds() / 1_000_000_000 - } - - fn num_nanoseconds(&self) -> i64 { - let secs = self.num_seconds() * 1_000_000_000; - let nsec = self.nanos_mod_sec(); - secs + nsec as i64 - } -} - -impl TimeSpec { - fn nanos_mod_sec(&self) -> timespec_tv_nsec_t { - if self.tv_sec() < 0 && self.tv_nsec() > 0 { - self.tv_nsec() - NANOS_PER_SEC as timespec_tv_nsec_t - } else { - self.tv_nsec() - } - } - - #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 - pub const fn tv_sec(&self) -> time_t { - self.0.tv_sec - } - - pub const fn tv_nsec(&self) -> timespec_tv_nsec_t { - self.0.tv_nsec - } - - pub const fn from_duration(duration: Duration) -> Self { - #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 - TimeSpec(timespec { - tv_sec: duration.as_secs() as time_t, - tv_nsec: duration.subsec_nanos() as timespec_tv_nsec_t - }) - } - - pub const fn from_timespec(timespec: timespec) -> Self { - Self(timespec) - } -} - -impl ops::Neg for TimeSpec { - type Output = TimeSpec; - - fn neg(self) -> TimeSpec { - TimeSpec::nanoseconds(-self.num_nanoseconds()) - } -} - -impl ops::Add for TimeSpec { - type Output = TimeSpec; - - fn add(self, rhs: TimeSpec) -> TimeSpec { - TimeSpec::nanoseconds( - self.num_nanoseconds() + rhs.num_nanoseconds()) - } -} - -impl ops::Sub for TimeSpec { - type Output = TimeSpec; - - fn sub(self, rhs: TimeSpec) -> TimeSpec { - TimeSpec::nanoseconds( - self.num_nanoseconds() - rhs.num_nanoseconds()) - } -} - -impl ops::Mul for TimeSpec { - type Output = TimeSpec; - - fn mul(self, rhs: i32) -> TimeSpec { - let usec = self.num_nanoseconds().checked_mul(i64::from(rhs)) - .expect("TimeSpec multiply out of bounds"); - - TimeSpec::nanoseconds(usec) - } -} - -impl ops::Div for TimeSpec { - type Output = TimeSpec; - - fn div(self, rhs: i32) -> TimeSpec { - let usec = self.num_nanoseconds() / i64::from(rhs); - TimeSpec::nanoseconds(usec) - } -} - -impl fmt::Display for TimeSpec { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let (abs, sign) = if self.tv_sec() < 0 { - (-*self, "-") - } else { - (*self, "") - }; - - let sec = abs.tv_sec(); - - write!(f, "{}", sign)?; - - if abs.tv_nsec() == 0 { - if abs.tv_sec() == 1 { - write!(f, "{} second", sec)?; - } else { - write!(f, "{} seconds", sec)?; - } - } else if abs.tv_nsec() % 1_000_000 == 0 { - write!(f, "{}.{:03} seconds", sec, abs.tv_nsec() / 1_000_000)?; - } else if abs.tv_nsec() % 1_000 == 0 { - write!(f, "{}.{:06} seconds", sec, abs.tv_nsec() / 1_000)?; - } else { - write!(f, "{}.{:09} seconds", sec, abs.tv_nsec())?; - } - - Ok(()) - } -} - - - -#[repr(transparent)] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct TimeVal(timeval); - -const MICROS_PER_SEC: i64 = 1_000_000; - -#[cfg(target_pointer_width = "64")] -const TV_MAX_SECONDS: i64 = (::std::i64::MAX / MICROS_PER_SEC) - 1; - -#[cfg(target_pointer_width = "32")] -const TV_MAX_SECONDS: i64 = ::std::isize::MAX as i64; - -const TV_MIN_SECONDS: i64 = -TV_MAX_SECONDS; - -impl AsRef for TimeVal { - fn as_ref(&self) -> &timeval { - &self.0 - } -} - -impl AsMut for TimeVal { - fn as_mut(&mut self) -> &mut timeval { - &mut self.0 - } -} - -impl Ord for TimeVal { - // The implementation of cmp is simplified by assuming that the struct is - // normalized. That is, tv_usec must always be within [0, 1_000_000) - fn cmp(&self, other: &TimeVal) -> cmp::Ordering { - if self.tv_sec() == other.tv_sec() { - self.tv_usec().cmp(&other.tv_usec()) - } else { - self.tv_sec().cmp(&other.tv_sec()) - } - } -} - -impl PartialOrd for TimeVal { - fn partial_cmp(&self, other: &TimeVal) -> Option { - Some(self.cmp(other)) - } -} - -impl TimeValLike for TimeVal { - #[inline] - fn seconds(seconds: i64) -> TimeVal { - assert!(seconds >= TV_MIN_SECONDS && seconds <= TV_MAX_SECONDS, - "TimeVal out of bounds; seconds={}", seconds); - #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 - TimeVal(timeval {tv_sec: seconds as time_t, tv_usec: 0 }) - } - - #[inline] - fn milliseconds(milliseconds: i64) -> TimeVal { - let microseconds = milliseconds.checked_mul(1_000) - .expect("TimeVal::milliseconds out of bounds"); - - TimeVal::microseconds(microseconds) - } - - /// Makes a new `TimeVal` with given number of microseconds. - #[inline] - fn microseconds(microseconds: i64) -> TimeVal { - let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC); - assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS, - "TimeVal out of bounds"); - #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 - TimeVal(timeval {tv_sec: secs as time_t, - tv_usec: micros as suseconds_t }) - } - - /// Makes a new `TimeVal` with given number of nanoseconds. Some precision - /// will be lost - #[inline] - fn nanoseconds(nanoseconds: i64) -> TimeVal { - let microseconds = nanoseconds / 1000; - let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC); - assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS, - "TimeVal out of bounds"); - #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 - TimeVal(timeval {tv_sec: secs as time_t, - tv_usec: micros as suseconds_t }) - } - - fn num_seconds(&self) -> i64 { - if self.tv_sec() < 0 && self.tv_usec() > 0 { - (self.tv_sec() + 1) as i64 - } else { - self.tv_sec() as i64 - } - } - - fn num_milliseconds(&self) -> i64 { - self.num_microseconds() / 1_000 - } - - fn num_microseconds(&self) -> i64 { - let secs = self.num_seconds() * 1_000_000; - let usec = self.micros_mod_sec(); - secs + usec as i64 - } - - fn num_nanoseconds(&self) -> i64 { - self.num_microseconds() * 1_000 - } -} - -impl TimeVal { - fn micros_mod_sec(&self) -> suseconds_t { - if self.tv_sec() < 0 && self.tv_usec() > 0 { - self.tv_usec() - MICROS_PER_SEC as suseconds_t - } else { - self.tv_usec() - } - } - - #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 - pub const fn tv_sec(&self) -> time_t { - self.0.tv_sec - } - - pub const fn tv_usec(&self) -> suseconds_t { - self.0.tv_usec - } -} - -impl ops::Neg for TimeVal { - type Output = TimeVal; - - fn neg(self) -> TimeVal { - TimeVal::microseconds(-self.num_microseconds()) - } -} - -impl ops::Add for TimeVal { - type Output = TimeVal; - - fn add(self, rhs: TimeVal) -> TimeVal { - TimeVal::microseconds( - self.num_microseconds() + rhs.num_microseconds()) - } -} - -impl ops::Sub for TimeVal { - type Output = TimeVal; - - fn sub(self, rhs: TimeVal) -> TimeVal { - TimeVal::microseconds( - self.num_microseconds() - rhs.num_microseconds()) - } -} - -impl ops::Mul for TimeVal { - type Output = TimeVal; - - fn mul(self, rhs: i32) -> TimeVal { - let usec = self.num_microseconds().checked_mul(i64::from(rhs)) - .expect("TimeVal multiply out of bounds"); - - TimeVal::microseconds(usec) - } -} - -impl ops::Div for TimeVal { - type Output = TimeVal; - - fn div(self, rhs: i32) -> TimeVal { - let usec = self.num_microseconds() / i64::from(rhs); - TimeVal::microseconds(usec) - } -} - -impl fmt::Display for TimeVal { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let (abs, sign) = if self.tv_sec() < 0 { - (-*self, "-") - } else { - (*self, "") - }; - - let sec = abs.tv_sec(); - - write!(f, "{}", sign)?; - - if abs.tv_usec() == 0 { - if abs.tv_sec() == 1 { - write!(f, "{} second", sec)?; - } else { - write!(f, "{} seconds", sec)?; - } - } else if abs.tv_usec() % 1000 == 0 { - write!(f, "{}.{:03} seconds", sec, abs.tv_usec() / 1000)?; - } else { - write!(f, "{}.{:06} seconds", sec, abs.tv_usec())?; - } - - Ok(()) - } -} - -impl From for TimeVal { - fn from(tv: timeval) -> Self { - TimeVal(tv) - } -} - -#[inline] -fn div_mod_floor_64(this: i64, other: i64) -> (i64, i64) { - (div_floor_64(this, other), mod_floor_64(this, other)) -} - -#[inline] -fn div_floor_64(this: i64, other: i64) -> i64 { - match div_rem_64(this, other) { - (d, r) if (r > 0 && other < 0) - || (r < 0 && other > 0) => d - 1, - (d, _) => d, - } -} - -#[inline] -fn mod_floor_64(this: i64, other: i64) -> i64 { - match this % other { - r if (r > 0 && other < 0) - || (r < 0 && other > 0) => r + other, - r => r, - } -} - -#[inline] -fn div_rem_64(this: i64, other: i64) -> (i64, i64) { - (this / other, this % other) -} - -#[cfg(test)] -mod test { - use super::{TimeSpec, TimeVal, TimeValLike}; - use std::time::Duration; - - #[test] - pub fn test_timespec() { - assert!(TimeSpec::seconds(1) != TimeSpec::zero()); - assert_eq!(TimeSpec::seconds(1) + TimeSpec::seconds(2), - TimeSpec::seconds(3)); - assert_eq!(TimeSpec::minutes(3) + TimeSpec::seconds(2), - TimeSpec::seconds(182)); - } - - #[test] - pub fn test_timespec_from() { - let duration = Duration::new(123, 123_456_789); - let timespec = TimeSpec::nanoseconds(123_123_456_789); - - assert_eq!(TimeSpec::from(duration), timespec); - assert_eq!(Duration::from(timespec), duration); - } - - #[test] - pub fn test_timespec_neg() { - let a = TimeSpec::seconds(1) + TimeSpec::nanoseconds(123); - let b = TimeSpec::seconds(-1) + TimeSpec::nanoseconds(-123); - - assert_eq!(a, -b); - } - - #[test] - pub fn test_timespec_ord() { - assert!(TimeSpec::seconds(1) == TimeSpec::nanoseconds(1_000_000_000)); - assert!(TimeSpec::seconds(1) < TimeSpec::nanoseconds(1_000_000_001)); - assert!(TimeSpec::seconds(1) > TimeSpec::nanoseconds(999_999_999)); - assert!(TimeSpec::seconds(-1) < TimeSpec::nanoseconds(-999_999_999)); - assert!(TimeSpec::seconds(-1) > TimeSpec::nanoseconds(-1_000_000_001)); - } - - #[test] - pub fn test_timespec_fmt() { - assert_eq!(TimeSpec::zero().to_string(), "0 seconds"); - assert_eq!(TimeSpec::seconds(42).to_string(), "42 seconds"); - assert_eq!(TimeSpec::milliseconds(42).to_string(), "0.042 seconds"); - assert_eq!(TimeSpec::microseconds(42).to_string(), "0.000042 seconds"); - assert_eq!(TimeSpec::nanoseconds(42).to_string(), "0.000000042 seconds"); - assert_eq!(TimeSpec::seconds(-86401).to_string(), "-86401 seconds"); - } - - #[test] - pub fn test_timeval() { - assert!(TimeVal::seconds(1) != TimeVal::zero()); - assert_eq!(TimeVal::seconds(1) + TimeVal::seconds(2), - TimeVal::seconds(3)); - assert_eq!(TimeVal::minutes(3) + TimeVal::seconds(2), - TimeVal::seconds(182)); - } - - #[test] - pub fn test_timeval_ord() { - assert!(TimeVal::seconds(1) == TimeVal::microseconds(1_000_000)); - assert!(TimeVal::seconds(1) < TimeVal::microseconds(1_000_001)); - assert!(TimeVal::seconds(1) > TimeVal::microseconds(999_999)); - assert!(TimeVal::seconds(-1) < TimeVal::microseconds(-999_999)); - assert!(TimeVal::seconds(-1) > TimeVal::microseconds(-1_000_001)); - } - - #[test] - pub fn test_timeval_neg() { - let a = TimeVal::seconds(1) + TimeVal::microseconds(123); - let b = TimeVal::seconds(-1) + TimeVal::microseconds(-123); - - assert_eq!(a, -b); - } - - #[test] - pub fn test_timeval_fmt() { - assert_eq!(TimeVal::zero().to_string(), "0 seconds"); - assert_eq!(TimeVal::seconds(42).to_string(), "42 seconds"); - assert_eq!(TimeVal::milliseconds(42).to_string(), "0.042 seconds"); - assert_eq!(TimeVal::microseconds(42).to_string(), "0.000042 seconds"); - assert_eq!(TimeVal::nanoseconds(1402).to_string(), "0.000001 seconds"); - assert_eq!(TimeVal::seconds(-86401).to_string(), "-86401 seconds"); - } -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/timerfd.rs b/vendor/nix-v0.23.1-patched/src/sys/timerfd.rs deleted file mode 100644 index 705a3c4d6..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/timerfd.rs +++ /dev/null @@ -1,281 +0,0 @@ -//! Timer API via file descriptors. -//! -//! Timer FD is a Linux-only API to create timers and get expiration -//! notifications through file descriptors. -//! -//! For more documentation, please read [timerfd_create(2)](https://man7.org/linux/man-pages/man2/timerfd_create.2.html). -//! -//! # Examples -//! -//! Create a new one-shot timer that expires after 1 second. -//! ``` -//! # use std::os::unix::io::AsRawFd; -//! # use nix::sys::timerfd::{TimerFd, ClockId, TimerFlags, TimerSetTimeFlags, -//! # Expiration}; -//! # use nix::sys::time::{TimeSpec, TimeValLike}; -//! # use nix::unistd::read; -//! # -//! // We create a new monotonic timer. -//! let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()) -//! .unwrap(); -//! -//! // We set a new one-shot timer in 1 seconds. -//! timer.set( -//! Expiration::OneShot(TimeSpec::seconds(1)), -//! TimerSetTimeFlags::empty() -//! ).unwrap(); -//! -//! // We wait for the timer to expire. -//! timer.wait().unwrap(); -//! ``` -use crate::sys::time::TimeSpec; -use crate::unistd::read; -use crate::{errno::Errno, Result}; -use bitflags::bitflags; -use libc::c_int; -use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; - -/// A timerfd instance. This is also a file descriptor, you can feed it to -/// other interfaces consuming file descriptors, epoll for example. -#[derive(Debug)] -pub struct TimerFd { - fd: RawFd, -} - -impl AsRawFd for TimerFd { - fn as_raw_fd(&self) -> RawFd { - self.fd - } -} - -impl FromRawFd for TimerFd { - unsafe fn from_raw_fd(fd: RawFd) -> Self { - TimerFd { fd } - } -} - -libc_enum! { - /// The type of the clock used to mark the progress of the timer. For more - /// details on each kind of clock, please refer to [timerfd_create(2)](https://man7.org/linux/man-pages/man2/timerfd_create.2.html). - #[repr(i32)] - #[non_exhaustive] - pub enum ClockId { - CLOCK_REALTIME, - CLOCK_MONOTONIC, - CLOCK_BOOTTIME, - CLOCK_REALTIME_ALARM, - CLOCK_BOOTTIME_ALARM, - } -} - -libc_bitflags! { - /// Additional flags to change the behaviour of the file descriptor at the - /// time of creation. - pub struct TimerFlags: c_int { - TFD_NONBLOCK; - TFD_CLOEXEC; - } -} - -bitflags! { - /// Flags that are used for arming the timer. - pub struct TimerSetTimeFlags: libc::c_int { - const TFD_TIMER_ABSTIME = libc::TFD_TIMER_ABSTIME; - } -} - -#[derive(Debug, Clone, Copy)] -struct TimerSpec(libc::itimerspec); - -impl TimerSpec { - pub const fn none() -> Self { - Self(libc::itimerspec { - it_interval: libc::timespec { - tv_sec: 0, - tv_nsec: 0, - }, - it_value: libc::timespec { - tv_sec: 0, - tv_nsec: 0, - }, - }) - } -} - -impl AsRef for TimerSpec { - fn as_ref(&self) -> &libc::itimerspec { - &self.0 - } -} - -impl From for TimerSpec { - fn from(expiration: Expiration) -> TimerSpec { - match expiration { - Expiration::OneShot(t) => TimerSpec(libc::itimerspec { - it_interval: libc::timespec { - tv_sec: 0, - tv_nsec: 0, - }, - it_value: *t.as_ref(), - }), - Expiration::IntervalDelayed(start, interval) => TimerSpec(libc::itimerspec { - it_interval: *interval.as_ref(), - it_value: *start.as_ref(), - }), - Expiration::Interval(t) => TimerSpec(libc::itimerspec { - it_interval: *t.as_ref(), - it_value: *t.as_ref(), - }), - } - } -} - -impl From for Expiration { - fn from(timerspec: TimerSpec) -> Expiration { - match timerspec { - TimerSpec(libc::itimerspec { - it_interval: - libc::timespec { - tv_sec: 0, - tv_nsec: 0, - }, - it_value: ts, - }) => Expiration::OneShot(ts.into()), - TimerSpec(libc::itimerspec { - it_interval: int_ts, - it_value: val_ts, - }) => { - if (int_ts.tv_sec == val_ts.tv_sec) && (int_ts.tv_nsec == val_ts.tv_nsec) { - Expiration::Interval(int_ts.into()) - } else { - Expiration::IntervalDelayed(val_ts.into(), int_ts.into()) - } - } - } - } -} - -/// An enumeration allowing the definition of the expiration time of an alarm, -/// recurring or not. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Expiration { - OneShot(TimeSpec), - IntervalDelayed(TimeSpec, TimeSpec), - Interval(TimeSpec), -} - -impl TimerFd { - /// Creates a new timer based on the clock defined by `clockid`. The - /// underlying fd can be assigned specific flags with `flags` (CLOEXEC, - /// NONBLOCK). The underlying fd will be closed on drop. - pub fn new(clockid: ClockId, flags: TimerFlags) -> Result { - Errno::result(unsafe { libc::timerfd_create(clockid as i32, flags.bits()) }) - .map(|fd| Self { fd }) - } - - /// Sets a new alarm on the timer. - /// - /// # Types of alarm - /// - /// There are 3 types of alarms you can set: - /// - /// - one shot: the alarm will trigger once after the specified amount of - /// time. - /// Example: I want an alarm to go off in 60s and then disables itself. - /// - /// - interval: the alarm will trigger every specified interval of time. - /// Example: I want an alarm to go off every 60s. The alarm will first - /// go off 60s after I set it and every 60s after that. The alarm will - /// not disable itself. - /// - /// - interval delayed: the alarm will trigger after a certain amount of - /// time and then trigger at a specified interval. - /// Example: I want an alarm to go off every 60s but only start in 1h. - /// The alarm will first trigger 1h after I set it and then every 60s - /// after that. The alarm will not disable itself. - /// - /// # Relative vs absolute alarm - /// - /// If you do not set any `TimerSetTimeFlags`, then the `TimeSpec` you pass - /// to the `Expiration` you want is relative. If however you want an alarm - /// to go off at a certain point in time, you can set `TFD_TIMER_ABSTIME`. - /// Then the one shot TimeSpec and the delay TimeSpec of the delayed - /// interval are going to be interpreted as absolute. - /// - /// # Disabling alarms - /// - /// Note: Only one alarm can be set for any given timer. Setting a new alarm - /// actually removes the previous one. - /// - /// Note: Setting a one shot alarm with a 0s TimeSpec disables the alarm - /// altogether. - pub fn set(&self, expiration: Expiration, flags: TimerSetTimeFlags) -> Result<()> { - let timerspec: TimerSpec = expiration.into(); - Errno::result(unsafe { - libc::timerfd_settime( - self.fd, - flags.bits(), - timerspec.as_ref(), - std::ptr::null_mut(), - ) - }) - .map(drop) - } - - /// Get the parameters for the alarm currently set, if any. - pub fn get(&self) -> Result> { - let mut timerspec = TimerSpec::none(); - let timerspec_ptr: *mut libc::itimerspec = &mut timerspec.0; - - Errno::result(unsafe { libc::timerfd_gettime(self.fd, timerspec_ptr) }).map(|_| { - if timerspec.0.it_interval.tv_sec == 0 - && timerspec.0.it_interval.tv_nsec == 0 - && timerspec.0.it_value.tv_sec == 0 - && timerspec.0.it_value.tv_nsec == 0 - { - None - } else { - Some(timerspec.into()) - } - }) - } - - /// Remove the alarm if any is set. - pub fn unset(&self) -> Result<()> { - Errno::result(unsafe { - libc::timerfd_settime( - self.fd, - TimerSetTimeFlags::empty().bits(), - TimerSpec::none().as_ref(), - std::ptr::null_mut(), - ) - }) - .map(drop) - } - - /// Wait for the configured alarm to expire. - /// - /// Note: If the alarm is unset, then you will wait forever. - pub fn wait(&self) -> Result<()> { - while let Err(e) = read(self.fd, &mut [0u8; 8]) { - if e != Errno::EINTR { - return Err(e) - } - } - - Ok(()) - } -} - -impl Drop for TimerFd { - fn drop(&mut self) { - if !std::thread::panicking() { - let result = Errno::result(unsafe { - libc::close(self.fd) - }); - if let Err(Errno::EBADF) = result { - panic!("close of TimerFd encountered EBADF"); - } - } - } -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/uio.rs b/vendor/nix-v0.23.1-patched/src/sys/uio.rs deleted file mode 100644 index 878f5cbe2..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/uio.rs +++ /dev/null @@ -1,223 +0,0 @@ -//! Vectored I/O - -use crate::Result; -use crate::errno::Errno; -use libc::{self, c_int, c_void, size_t, off_t}; -use std::marker::PhantomData; -use std::os::unix::io::RawFd; - -/// Low-level vectored write to a raw file descriptor -/// -/// See also [writev(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html) -pub fn writev(fd: RawFd, iov: &[IoVec<&[u8]>]) -> Result { - let res = unsafe { libc::writev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) }; - - Errno::result(res).map(|r| r as usize) -} - -/// Low-level vectored read from a raw file descriptor -/// -/// See also [readv(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html) -pub fn readv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>]) -> Result { - let res = unsafe { libc::readv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) }; - - Errno::result(res).map(|r| r as usize) -} - -/// Write to `fd` at `offset` from buffers in `iov`. -/// -/// Buffers in `iov` will be written in order until all buffers have been written -/// or an error occurs. The file offset is not changed. -/// -/// See also: [`writev`](fn.writev.html) and [`pwrite`](fn.pwrite.html) -#[cfg(not(any(target_os = "macos", target_os = "redox")))] -pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>], - offset: off_t) -> Result { - let res = unsafe { - libc::pwritev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset) - }; - - Errno::result(res).map(|r| r as usize) -} - -/// Read from `fd` at `offset` filling buffers in `iov`. -/// -/// Buffers in `iov` will be filled in order until all buffers have been filled, -/// no more bytes are available, or an error occurs. The file offset is not -/// changed. -/// -/// See also: [`readv`](fn.readv.html) and [`pread`](fn.pread.html) -#[cfg(not(any(target_os = "macos", target_os = "redox")))] -pub fn preadv(fd: RawFd, iov: &[IoVec<&mut [u8]>], - offset: off_t) -> Result { - let res = unsafe { - libc::preadv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset) - }; - - Errno::result(res).map(|r| r as usize) -} - -/// Low-level write to a file, with specified offset. -/// -/// See also [pwrite(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html) -// TODO: move to unistd -pub fn pwrite(fd: RawFd, buf: &[u8], offset: off_t) -> Result { - let res = unsafe { - libc::pwrite(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, - offset) - }; - - Errno::result(res).map(|r| r as usize) -} - -/// Low-level write to a file, with specified offset. -/// -/// See also [pread(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html) -// TODO: move to unistd -pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result{ - let res = unsafe { - libc::pread(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t, - offset) - }; - - Errno::result(res).map(|r| r as usize) -} - -/// A slice of memory in a remote process, starting at address `base` -/// and consisting of `len` bytes. -/// -/// This is the same underlying C structure as [`IoVec`](struct.IoVec.html), -/// except that it refers to memory in some other process, and is -/// therefore not represented in Rust by an actual slice as `IoVec` is. It -/// is used with [`process_vm_readv`](fn.process_vm_readv.html) -/// and [`process_vm_writev`](fn.process_vm_writev.html). -#[cfg(target_os = "linux")] -#[repr(C)] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct RemoteIoVec { - /// The starting address of this slice (`iov_base`). - pub base: usize, - /// The number of bytes in this slice (`iov_len`). - pub len: usize, -} - -/// Write data directly to another process's virtual memory -/// (see [`process_vm_writev`(2)]). -/// -/// `local_iov` is a list of [`IoVec`]s containing the data to be written, -/// and `remote_iov` is a list of [`RemoteIoVec`]s identifying where the -/// data should be written in the target process. On success, returns the -/// number of bytes written, which will always be a whole -/// number of `remote_iov` chunks. -/// -/// This requires the same permissions as debugging the process using -/// [ptrace]: you must either be a privileged process (with -/// `CAP_SYS_PTRACE`), or you must be running as the same user as the -/// target process and the OS must have unprivileged debugging enabled. -/// -/// This function is only available on Linux. -/// -/// [`process_vm_writev`(2)]: https://man7.org/linux/man-pages/man2/process_vm_writev.2.html -/// [ptrace]: ../ptrace/index.html -/// [`IoVec`]: struct.IoVec.html -/// [`RemoteIoVec`]: struct.RemoteIoVec.html -#[cfg(target_os = "linux")] -pub fn process_vm_writev( - pid: crate::unistd::Pid, - local_iov: &[IoVec<&[u8]>], - remote_iov: &[RemoteIoVec]) -> Result -{ - let res = unsafe { - libc::process_vm_writev(pid.into(), - local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong, - remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0) - }; - - Errno::result(res).map(|r| r as usize) -} - -/// Read data directly from another process's virtual memory -/// (see [`process_vm_readv`(2)]). -/// -/// `local_iov` is a list of [`IoVec`]s containing the buffer to copy -/// data into, and `remote_iov` is a list of [`RemoteIoVec`]s identifying -/// where the source data is in the target process. On success, -/// returns the number of bytes written, which will always be a whole -/// number of `remote_iov` chunks. -/// -/// This requires the same permissions as debugging the process using -/// [`ptrace`]: you must either be a privileged process (with -/// `CAP_SYS_PTRACE`), or you must be running as the same user as the -/// target process and the OS must have unprivileged debugging enabled. -/// -/// This function is only available on Linux. -/// -/// [`process_vm_readv`(2)]: https://man7.org/linux/man-pages/man2/process_vm_readv.2.html -/// [`ptrace`]: ../ptrace/index.html -/// [`IoVec`]: struct.IoVec.html -/// [`RemoteIoVec`]: struct.RemoteIoVec.html -#[cfg(any(target_os = "linux"))] -pub fn process_vm_readv( - pid: crate::unistd::Pid, - local_iov: &[IoVec<&mut [u8]>], - remote_iov: &[RemoteIoVec]) -> Result -{ - let res = unsafe { - libc::process_vm_readv(pid.into(), - local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong, - remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0) - }; - - Errno::result(res).map(|r| r as usize) -} - -/// A vector of buffers. -/// -/// Vectored I/O methods like [`writev`] and [`readv`] use this structure for -/// both reading and writing. Each `IoVec` specifies the base address and -/// length of an area in memory. -#[repr(transparent)] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct IoVec(pub(crate) libc::iovec, PhantomData); - -impl IoVec { - /// View the `IoVec` as a Rust slice. - #[inline] - pub fn as_slice(&self) -> &[u8] { - use std::slice; - - unsafe { - slice::from_raw_parts( - self.0.iov_base as *const u8, - self.0.iov_len as usize) - } - } -} - -impl<'a> IoVec<&'a [u8]> { - #[cfg(target_os = "freebsd")] - pub(crate) fn from_raw_parts(base: *mut c_void, len: usize) -> Self { - IoVec(libc::iovec { - iov_base: base, - iov_len: len - }, PhantomData) - } - - /// Create an `IoVec` from a Rust slice. - pub fn from_slice(buf: &'a [u8]) -> IoVec<&'a [u8]> { - IoVec(libc::iovec { - iov_base: buf.as_ptr() as *mut c_void, - iov_len: buf.len() as size_t, - }, PhantomData) - } -} - -impl<'a> IoVec<&'a mut [u8]> { - /// Create an `IoVec` from a mutable Rust slice. - pub fn from_mut_slice(buf: &'a mut [u8]) -> IoVec<&'a mut [u8]> { - IoVec(libc::iovec { - iov_base: buf.as_ptr() as *mut c_void, - iov_len: buf.len() as size_t, - }, PhantomData) - } -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/utsname.rs b/vendor/nix-v0.23.1-patched/src/sys/utsname.rs deleted file mode 100644 index 98edee042..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/utsname.rs +++ /dev/null @@ -1,75 +0,0 @@ -//! Get system identification -use std::mem; -use libc::{self, c_char}; -use std::ffi::CStr; -use std::str::from_utf8_unchecked; - -/// Describes the running system. Return type of [`uname`]. -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -#[repr(transparent)] -pub struct UtsName(libc::utsname); - -impl UtsName { - /// Name of the operating system implementation - pub fn sysname(&self) -> &str { - to_str(&(&self.0.sysname as *const c_char ) as *const *const c_char) - } - - /// Network name of this machine. - pub fn nodename(&self) -> &str { - to_str(&(&self.0.nodename as *const c_char ) as *const *const c_char) - } - - /// Release level of the operating system. - pub fn release(&self) -> &str { - to_str(&(&self.0.release as *const c_char ) as *const *const c_char) - } - - /// Version level of the operating system. - pub fn version(&self) -> &str { - to_str(&(&self.0.version as *const c_char ) as *const *const c_char) - } - - /// Machine hardware platform. - pub fn machine(&self) -> &str { - to_str(&(&self.0.machine as *const c_char ) as *const *const c_char) - } -} - -/// Get system identification -pub fn uname() -> UtsName { - unsafe { - let mut ret = mem::MaybeUninit::uninit(); - libc::uname(ret.as_mut_ptr()); - UtsName(ret.assume_init()) - } -} - -#[inline] -fn to_str<'a>(s: *const *const c_char) -> &'a str { - unsafe { - let res = CStr::from_ptr(*s).to_bytes(); - from_utf8_unchecked(res) - } -} - -#[cfg(test)] -mod test { - #[cfg(target_os = "linux")] - #[test] - pub fn test_uname_linux() { - assert_eq!(super::uname().sysname(), "Linux"); - } - - #[cfg(any(target_os = "macos", target_os = "ios"))] - #[test] - pub fn test_uname_darwin() { - assert_eq!(super::uname().sysname(), "Darwin"); - } - - #[cfg(target_os = "freebsd")] - #[test] - pub fn test_uname_freebsd() { - assert_eq!(super::uname().sysname(), "FreeBSD"); - } -} diff --git a/vendor/nix-v0.23.1-patched/src/sys/wait.rs b/vendor/nix-v0.23.1-patched/src/sys/wait.rs deleted file mode 100644 index ee49e37de..000000000 --- a/vendor/nix-v0.23.1-patched/src/sys/wait.rs +++ /dev/null @@ -1,262 +0,0 @@ -//! Wait for a process to change status -use crate::errno::Errno; -use crate::sys::signal::Signal; -use crate::unistd::Pid; -use crate::Result; -use cfg_if::cfg_if; -use libc::{self, c_int}; -use std::convert::TryFrom; - -libc_bitflags!( - /// Controls the behavior of [`waitpid`]. - pub struct WaitPidFlag: c_int { - /// Do not block when there are no processes wishing to report status. - WNOHANG; - /// Report the status of selected processes which are stopped due to a - /// [`SIGTTIN`](crate::sys::signal::Signal::SIGTTIN), - /// [`SIGTTOU`](crate::sys::signal::Signal::SIGTTOU), - /// [`SIGTSTP`](crate::sys::signal::Signal::SIGTSTP), or - /// [`SIGSTOP`](crate::sys::signal::Signal::SIGSTOP) signal. - WUNTRACED; - /// Report the status of selected processes which have terminated. - #[cfg(any(target_os = "android", - target_os = "freebsd", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "redox", - target_os = "macos", - target_os = "netbsd"))] - WEXITED; - /// Report the status of selected processes that have continued from a - /// job control stop by receiving a - /// [`SIGCONT`](crate::sys::signal::Signal::SIGCONT) signal. - WCONTINUED; - /// An alias for WUNTRACED. - #[cfg(any(target_os = "android", - target_os = "freebsd", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "redox", - target_os = "macos", - target_os = "netbsd"))] - WSTOPPED; - /// Don't reap, just poll status. - #[cfg(any(target_os = "android", - target_os = "freebsd", - target_os = "haiku", - target_os = "ios", - target_os = "linux", - target_os = "redox", - target_os = "macos", - target_os = "netbsd"))] - WNOWAIT; - /// Don't wait on children of other threads in this group - #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))] - __WNOTHREAD; - /// Wait on all children, regardless of type - #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))] - __WALL; - /// Wait for "clone" children only. - #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))] - __WCLONE; - } -); - -/// Possible return values from `wait()` or `waitpid()`. -/// -/// Each status (other than `StillAlive`) describes a state transition -/// in a child process `Pid`, such as the process exiting or stopping, -/// plus additional data about the transition if any. -/// -/// Note that there are two Linux-specific enum variants, `PtraceEvent` -/// and `PtraceSyscall`. Portable code should avoid exhaustively -/// matching on `WaitStatus`. -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum WaitStatus { - /// The process exited normally (as with `exit()` or returning from - /// `main`) with the given exit code. This case matches the C macro - /// `WIFEXITED(status)`; the second field is `WEXITSTATUS(status)`. - Exited(Pid, i32), - /// The process was killed by the given signal. The third field - /// indicates whether the signal generated a core dump. This case - /// matches the C macro `WIFSIGNALED(status)`; the last two fields - /// correspond to `WTERMSIG(status)` and `WCOREDUMP(status)`. - Signaled(Pid, Signal, bool), - /// The process is alive, but was stopped by the given signal. This - /// is only reported if `WaitPidFlag::WUNTRACED` was passed. This - /// case matches the C macro `WIFSTOPPED(status)`; the second field - /// is `WSTOPSIG(status)`. - Stopped(Pid, Signal), - /// The traced process was stopped by a `PTRACE_EVENT_*` event. See - /// [`nix::sys::ptrace`] and [`ptrace`(2)] for more information. All - /// currently-defined events use `SIGTRAP` as the signal; the third - /// field is the `PTRACE_EVENT_*` value of the event. - /// - /// [`nix::sys::ptrace`]: ../ptrace/index.html - /// [`ptrace`(2)]: https://man7.org/linux/man-pages/man2/ptrace.2.html - #[cfg(any(target_os = "linux", target_os = "android"))] - PtraceEvent(Pid, Signal, c_int), - /// The traced process was stopped by execution of a system call, - /// and `PTRACE_O_TRACESYSGOOD` is in effect. See [`ptrace`(2)] for - /// more information. - /// - /// [`ptrace`(2)]: https://man7.org/linux/man-pages/man2/ptrace.2.html - #[cfg(any(target_os = "linux", target_os = "android"))] - PtraceSyscall(Pid), - /// The process was previously stopped but has resumed execution - /// after receiving a `SIGCONT` signal. This is only reported if - /// `WaitPidFlag::WCONTINUED` was passed. This case matches the C - /// macro `WIFCONTINUED(status)`. - Continued(Pid), - /// There are currently no state changes to report in any awaited - /// child process. This is only returned if `WaitPidFlag::WNOHANG` - /// was used (otherwise `wait()` or `waitpid()` would block until - /// there was something to report). - StillAlive, -} - -impl WaitStatus { - /// Extracts the PID from the WaitStatus unless it equals StillAlive. - pub fn pid(&self) -> Option { - use self::WaitStatus::*; - match *self { - Exited(p, _) | Signaled(p, _, _) | Stopped(p, _) | Continued(p) => Some(p), - StillAlive => None, - #[cfg(any(target_os = "android", target_os = "linux"))] - PtraceEvent(p, _, _) | PtraceSyscall(p) => Some(p), - } - } -} - -fn exited(status: i32) -> bool { - libc::WIFEXITED(status) -} - -fn exit_status(status: i32) -> i32 { - libc::WEXITSTATUS(status) -} - -fn signaled(status: i32) -> bool { - libc::WIFSIGNALED(status) -} - -fn term_signal(status: i32) -> Result { - Signal::try_from(libc::WTERMSIG(status)) -} - -fn dumped_core(status: i32) -> bool { - libc::WCOREDUMP(status) -} - -fn stopped(status: i32) -> bool { - libc::WIFSTOPPED(status) -} - -fn stop_signal(status: i32) -> Result { - Signal::try_from(libc::WSTOPSIG(status)) -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -fn syscall_stop(status: i32) -> bool { - // From ptrace(2), setting PTRACE_O_TRACESYSGOOD has the effect - // of delivering SIGTRAP | 0x80 as the signal number for syscall - // stops. This allows easily distinguishing syscall stops from - // genuine SIGTRAP signals. - libc::WSTOPSIG(status) == libc::SIGTRAP | 0x80 -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -fn stop_additional(status: i32) -> c_int { - (status >> 16) as c_int -} - -fn continued(status: i32) -> bool { - libc::WIFCONTINUED(status) -} - -impl WaitStatus { - /// Convert a raw `wstatus` as returned by `waitpid`/`wait` into a `WaitStatus` - /// - /// # Errors - /// - /// Returns an `Error` corresponding to `EINVAL` for invalid status values. - /// - /// # Examples - /// - /// Convert a `wstatus` obtained from `libc::waitpid` into a `WaitStatus`: - /// - /// ``` - /// use nix::sys::wait::WaitStatus; - /// use nix::sys::signal::Signal; - /// let pid = nix::unistd::Pid::from_raw(1); - /// let status = WaitStatus::from_raw(pid, 0x0002); - /// assert_eq!(status, Ok(WaitStatus::Signaled(pid, Signal::SIGINT, false))); - /// ``` - pub fn from_raw(pid: Pid, status: i32) -> Result { - Ok(if exited(status) { - WaitStatus::Exited(pid, exit_status(status)) - } else if signaled(status) { - WaitStatus::Signaled(pid, term_signal(status)?, dumped_core(status)) - } else if stopped(status) { - cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { - fn decode_stopped(pid: Pid, status: i32) -> Result { - let status_additional = stop_additional(status); - Ok(if syscall_stop(status) { - WaitStatus::PtraceSyscall(pid) - } else if status_additional == 0 { - WaitStatus::Stopped(pid, stop_signal(status)?) - } else { - WaitStatus::PtraceEvent(pid, stop_signal(status)?, - stop_additional(status)) - }) - } - } else { - fn decode_stopped(pid: Pid, status: i32) -> Result { - Ok(WaitStatus::Stopped(pid, stop_signal(status)?)) - } - } - } - return decode_stopped(pid, status); - } else { - assert!(continued(status)); - WaitStatus::Continued(pid) - }) - } -} - -/// Wait for a process to change status -/// -/// See also [waitpid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/waitpid.html) -pub fn waitpid>>(pid: P, options: Option) -> Result { - use self::WaitStatus::*; - - let mut status: i32 = 0; - - let option_bits = match options { - Some(bits) => bits.bits(), - None => 0, - }; - - let res = unsafe { - libc::waitpid( - pid.into().unwrap_or_else(|| Pid::from_raw(-1)).into(), - &mut status as *mut c_int, - option_bits, - ) - }; - - match Errno::result(res)? { - 0 => Ok(StillAlive), - res => WaitStatus::from_raw(Pid::from_raw(res), status), - } -} - -/// Wait for any child process to change status or a signal is received. -/// -/// See also [wait(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html) -pub fn wait() -> Result { - waitpid(None, None) -} diff --git a/vendor/nix-v0.23.1-patched/src/time.rs b/vendor/nix-v0.23.1-patched/src/time.rs deleted file mode 100644 index 6275b59c7..000000000 --- a/vendor/nix-v0.23.1-patched/src/time.rs +++ /dev/null @@ -1,260 +0,0 @@ -use crate::sys::time::TimeSpec; -#[cfg(any( - target_os = "freebsd", - target_os = "dragonfly", - target_os = "linux", - target_os = "android", - target_os = "emscripten", -))] -use crate::unistd::Pid; -use crate::{Errno, Result}; -use libc::{self, clockid_t}; -use std::mem::MaybeUninit; - -/// Clock identifier -/// -/// Newtype pattern around `clockid_t` (which is just alias). It pervents bugs caused by -/// accidentally passing wrong value. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct ClockId(clockid_t); - -impl ClockId { - /// Creates `ClockId` from raw `clockid_t` - pub const fn from_raw(clk_id: clockid_t) -> Self { - ClockId(clk_id) - } - - /// Returns `ClockId` of a `pid` CPU-time clock - #[cfg(any( - target_os = "freebsd", - target_os = "dragonfly", - target_os = "linux", - target_os = "android", - target_os = "emscripten", - ))] - pub fn pid_cpu_clock_id(pid: Pid) -> Result { - clock_getcpuclockid(pid) - } - - /// Returns resolution of the clock id - #[cfg(not(target_os = "redox"))] - pub fn res(self) -> Result { - clock_getres(self) - } - - /// Returns the current time on the clock id - pub fn now(self) -> Result { - clock_gettime(self) - } - - /// Sets time to `timespec` on the clock id - #[cfg(not(any( - target_os = "macos", - target_os = "ios", - all( - not(any(target_env = "uclibc", target_env = "newlibc")), - any(target_os = "redox", target_os = "hermit",), - ), - )))] - pub fn set_time(self, timespec: TimeSpec) -> Result<()> { - clock_settime(self, timespec) - } - - /// Gets the raw `clockid_t` wrapped by `self` - pub const fn as_raw(self) -> clockid_t { - self.0 - } - - #[cfg(any( - target_os = "fuchsia", - all( - not(any(target_env = "uclibc", target_env = "newlib")), - any(target_os = "linux", target_os = "android", target_os = "emscripten"), - ) - ))] - pub const CLOCK_BOOTTIME: ClockId = ClockId(libc::CLOCK_BOOTTIME); - #[cfg(any( - target_os = "fuchsia", - all( - not(any(target_env = "uclibc", target_env = "newlib")), - any(target_os = "linux", target_os = "android", target_os = "emscripten") - ) - ))] - pub const CLOCK_BOOTTIME_ALARM: ClockId = ClockId(libc::CLOCK_BOOTTIME_ALARM); - pub const CLOCK_MONOTONIC: ClockId = ClockId(libc::CLOCK_MONOTONIC); - #[cfg(any( - target_os = "fuchsia", - all( - not(any(target_env = "uclibc", target_env = "newlib")), - any(target_os = "linux", target_os = "android", target_os = "emscripten") - ) - ))] - pub const CLOCK_MONOTONIC_COARSE: ClockId = ClockId(libc::CLOCK_MONOTONIC_COARSE); - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - pub const CLOCK_MONOTONIC_FAST: ClockId = ClockId(libc::CLOCK_MONOTONIC_FAST); - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - pub const CLOCK_MONOTONIC_PRECISE: ClockId = ClockId(libc::CLOCK_MONOTONIC_PRECISE); - #[cfg(any( - target_os = "fuchsia", - all( - not(any(target_env = "uclibc", target_env = "newlib")), - any(target_os = "linux", target_os = "android", target_os = "emscripten") - ) - ))] - pub const CLOCK_MONOTONIC_RAW: ClockId = ClockId(libc::CLOCK_MONOTONIC_RAW); - #[cfg(any( - target_os = "fuchsia", - target_env = "uclibc", - target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "dragonfly", - all( - not(target_env = "newlib"), - any(target_os = "linux", target_os = "android", target_os = "emscripten") - ) - ))] - pub const CLOCK_PROCESS_CPUTIME_ID: ClockId = ClockId(libc::CLOCK_PROCESS_CPUTIME_ID); - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - pub const CLOCK_PROF: ClockId = ClockId(libc::CLOCK_PROF); - pub const CLOCK_REALTIME: ClockId = ClockId(libc::CLOCK_REALTIME); - #[cfg(any( - target_os = "fuchsia", - all( - not(any(target_env = "uclibc", target_env = "newlib")), - any(target_os = "linux", target_os = "android", target_os = "emscripten") - ) - ))] - pub const CLOCK_REALTIME_ALARM: ClockId = ClockId(libc::CLOCK_REALTIME_ALARM); - #[cfg(any( - target_os = "fuchsia", - all( - not(any(target_env = "uclibc", target_env = "newlib")), - any(target_os = "linux", target_os = "android", target_os = "emscripten") - ) - ))] - pub const CLOCK_REALTIME_COARSE: ClockId = ClockId(libc::CLOCK_REALTIME_COARSE); - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - pub const CLOCK_REALTIME_FAST: ClockId = ClockId(libc::CLOCK_REALTIME_FAST); - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - pub const CLOCK_REALTIME_PRECISE: ClockId = ClockId(libc::CLOCK_REALTIME_PRECISE); - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - pub const CLOCK_SECOND: ClockId = ClockId(libc::CLOCK_SECOND); - #[cfg(any( - target_os = "fuchsia", - all( - not(any(target_env = "uclibc", target_env = "newlib")), - any( - target_os = "emscripten", - all(target_os = "linux", target_env = "musl") - ) - ) - ))] - pub const CLOCK_SGI_CYCLE: ClockId = ClockId(libc::CLOCK_SGI_CYCLE); - #[cfg(any( - target_os = "fuchsia", - all( - not(any(target_env = "uclibc", target_env = "newlib")), - any( - target_os = "emscripten", - all(target_os = "linux", target_env = "musl") - ) - ) - ))] - pub const CLOCK_TAI: ClockId = ClockId(libc::CLOCK_TAI); - #[cfg(any( - target_env = "uclibc", - target_os = "fuchsia", - target_os = "ios", - target_os = "macos", - target_os = "freebsd", - target_os = "dragonfly", - all( - not(target_env = "newlib"), - any(target_os = "linux", target_os = "android", target_os = "emscripten",), - ), - ))] - pub const CLOCK_THREAD_CPUTIME_ID: ClockId = ClockId(libc::CLOCK_THREAD_CPUTIME_ID); - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - pub const CLOCK_UPTIME: ClockId = ClockId(libc::CLOCK_UPTIME); - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - pub const CLOCK_UPTIME_FAST: ClockId = ClockId(libc::CLOCK_UPTIME_FAST); - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - pub const CLOCK_UPTIME_PRECISE: ClockId = ClockId(libc::CLOCK_UPTIME_PRECISE); - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - pub const CLOCK_VIRTUAL: ClockId = ClockId(libc::CLOCK_VIRTUAL); -} - -impl From for clockid_t { - fn from(clock_id: ClockId) -> Self { - clock_id.as_raw() - } -} - -impl From for ClockId { - fn from(clk_id: clockid_t) -> Self { - ClockId::from_raw(clk_id) - } -} - -impl std::fmt::Display for ClockId { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - std::fmt::Display::fmt(&self.0, f) - } -} - -/// Get the resolution of the specified clock, (see -/// [clock_getres(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_getres.html)). -#[cfg(not(target_os = "redox"))] -pub fn clock_getres(clock_id: ClockId) -> Result { - let mut c_time: MaybeUninit = MaybeUninit::uninit(); - let ret = unsafe { libc::clock_getres(clock_id.as_raw(), c_time.as_mut_ptr()) }; - Errno::result(ret)?; - let res = unsafe { c_time.assume_init() }; - Ok(TimeSpec::from(res)) -} - -/// Get the time of the specified clock, (see -/// [clock_gettime(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_gettime.html)). -pub fn clock_gettime(clock_id: ClockId) -> Result { - let mut c_time: MaybeUninit = MaybeUninit::uninit(); - let ret = unsafe { libc::clock_gettime(clock_id.as_raw(), c_time.as_mut_ptr()) }; - Errno::result(ret)?; - let res = unsafe { c_time.assume_init() }; - Ok(TimeSpec::from(res)) -} - -/// Set the time of the specified clock, (see -/// [clock_settime(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_settime.html)). -#[cfg(not(any( - target_os = "macos", - target_os = "ios", - all( - not(any(target_env = "uclibc", target_env = "newlibc")), - any(target_os = "redox", target_os = "hermit",), - ), -)))] -pub fn clock_settime(clock_id: ClockId, timespec: TimeSpec) -> Result<()> { - let ret = unsafe { libc::clock_settime(clock_id.as_raw(), timespec.as_ref()) }; - Errno::result(ret).map(drop) -} - -/// Get the clock id of the specified process id, (see -/// [clock_getcpuclockid(3)](https://pubs.opengroup.org/onlinepubs/009695399/functions/clock_getcpuclockid.html)). -#[cfg(any( - target_os = "freebsd", - target_os = "dragonfly", - target_os = "linux", - target_os = "android", - target_os = "emscripten", -))] -pub fn clock_getcpuclockid(pid: Pid) -> Result { - let mut clk_id: MaybeUninit = MaybeUninit::uninit(); - let ret = unsafe { libc::clock_getcpuclockid(pid.into(), clk_id.as_mut_ptr()) }; - if ret == 0 { - let res = unsafe { clk_id.assume_init() }; - Ok(ClockId::from(res)) - } else { - Err(Errno::from_i32(ret)) - } -} diff --git a/vendor/nix-v0.23.1-patched/src/ucontext.rs b/vendor/nix-v0.23.1-patched/src/ucontext.rs deleted file mode 100644 index f2338bd42..000000000 --- a/vendor/nix-v0.23.1-patched/src/ucontext.rs +++ /dev/null @@ -1,43 +0,0 @@ -#[cfg(not(target_env = "musl"))] -use crate::Result; -#[cfg(not(target_env = "musl"))] -use crate::errno::Errno; -#[cfg(not(target_env = "musl"))] -use std::mem; -use crate::sys::signal::SigSet; - -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub struct UContext { - context: libc::ucontext_t, -} - -impl UContext { - #[cfg(not(target_env = "musl"))] - pub fn get() -> Result { - let mut context = mem::MaybeUninit::::uninit(); - let res = unsafe { libc::getcontext(context.as_mut_ptr()) }; - Errno::result(res).map(|_| unsafe { - UContext { context: context.assume_init()} - }) - } - - #[cfg(not(target_env = "musl"))] - pub fn set(&self) -> Result<()> { - let res = unsafe { - libc::setcontext(&self.context as *const libc::ucontext_t) - }; - Errno::result(res).map(drop) - } - - pub fn sigmask_mut(&mut self) -> &mut SigSet { - unsafe { - &mut *(&mut self.context.uc_sigmask as *mut libc::sigset_t as *mut SigSet) - } - } - - pub fn sigmask(&self) -> &SigSet { - unsafe { - &*(&self.context.uc_sigmask as *const libc::sigset_t as *const SigSet) - } - } -} diff --git a/vendor/nix-v0.23.1-patched/src/unistd.rs b/vendor/nix-v0.23.1-patched/src/unistd.rs deleted file mode 100644 index a9862d37a..000000000 --- a/vendor/nix-v0.23.1-patched/src/unistd.rs +++ /dev/null @@ -1,2994 +0,0 @@ -//! Safe wrappers around functions found in libc "unistd.h" header - -#[cfg(not(target_os = "redox"))] -use cfg_if::cfg_if; -use crate::errno::{self, Errno}; -use crate::{Error, Result, NixPath}; -#[cfg(not(target_os = "redox"))] -use crate::fcntl::{AtFlags, at_rawfd}; -use crate::fcntl::{FdFlag, OFlag, fcntl}; -use crate::fcntl::FcntlArg::F_SETFD; -use libc::{self, c_char, c_void, c_int, c_long, c_uint, size_t, pid_t, off_t, - uid_t, gid_t, mode_t, PATH_MAX}; -use std::{fmt, mem, ptr}; -use std::convert::Infallible; -use std::ffi::{CStr, OsString}; -#[cfg(not(target_os = "redox"))] -use std::ffi::{CString, OsStr}; -use std::os::unix::ffi::OsStringExt; -#[cfg(not(target_os = "redox"))] -use std::os::unix::ffi::OsStrExt; -use std::os::unix::io::RawFd; -use std::path::PathBuf; -use crate::sys::stat::Mode; - -#[cfg(any(target_os = "android", target_os = "linux"))] -pub use self::pivot_root::*; - -#[cfg(any(target_os = "android", target_os = "freebsd", - target_os = "linux", target_os = "openbsd"))] -pub use self::setres::*; - -#[cfg(any(target_os = "android", target_os = "linux"))] -pub use self::getres::*; - -/// User identifier -/// -/// Newtype pattern around `uid_t` (which is just alias). It prevents bugs caused by accidentally -/// passing wrong value. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub struct Uid(uid_t); - -impl Uid { - /// Creates `Uid` from raw `uid_t`. - pub const fn from_raw(uid: uid_t) -> Self { - Uid(uid) - } - - /// Returns Uid of calling process. This is practically a more Rusty alias for `getuid`. - pub fn current() -> Self { - getuid() - } - - /// Returns effective Uid of calling process. This is practically a more Rusty alias for `geteuid`. - pub fn effective() -> Self { - geteuid() - } - - /// Returns true if the `Uid` represents privileged user - root. (If it equals zero.) - pub const fn is_root(self) -> bool { - self.0 == ROOT.0 - } - - /// Get the raw `uid_t` wrapped by `self`. - pub const fn as_raw(self) -> uid_t { - self.0 - } -} - -impl From for uid_t { - fn from(uid: Uid) -> Self { - uid.0 - } -} - -impl fmt::Display for Uid { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.0, f) - } -} - -/// Constant for UID = 0 -pub const ROOT: Uid = Uid(0); - -/// Group identifier -/// -/// Newtype pattern around `gid_t` (which is just alias). It prevents bugs caused by accidentally -/// passing wrong value. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub struct Gid(gid_t); - -impl Gid { - /// Creates `Gid` from raw `gid_t`. - pub const fn from_raw(gid: gid_t) -> Self { - Gid(gid) - } - - /// Returns Gid of calling process. This is practically a more Rusty alias for `getgid`. - pub fn current() -> Self { - getgid() - } - - /// Returns effective Gid of calling process. This is practically a more Rusty alias for `getegid`. - pub fn effective() -> Self { - getegid() - } - - /// Get the raw `gid_t` wrapped by `self`. - pub const fn as_raw(self) -> gid_t { - self.0 - } -} - -impl From for gid_t { - fn from(gid: Gid) -> Self { - gid.0 - } -} - -impl fmt::Display for Gid { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.0, f) - } -} - -/// Process identifier -/// -/// Newtype pattern around `pid_t` (which is just alias). It prevents bugs caused by accidentally -/// passing wrong value. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct Pid(pid_t); - -impl Pid { - /// Creates `Pid` from raw `pid_t`. - pub const fn from_raw(pid: pid_t) -> Self { - Pid(pid) - } - - /// Returns PID of calling process - pub fn this() -> Self { - getpid() - } - - /// Returns PID of parent of calling process - pub fn parent() -> Self { - getppid() - } - - /// Get the raw `pid_t` wrapped by `self`. - pub const fn as_raw(self) -> pid_t { - self.0 - } -} - -impl From for pid_t { - fn from(pid: Pid) -> Self { - pid.0 - } -} - -impl fmt::Display for Pid { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.0, f) - } -} - - -/// Represents the successful result of calling `fork` -/// -/// When `fork` is called, the process continues execution in the parent process -/// and in the new child. This return type can be examined to determine whether -/// you are now executing in the parent process or in the child. -#[derive(Clone, Copy, Debug)] -pub enum ForkResult { - Parent { child: Pid }, - Child, -} - -impl ForkResult { - - /// Return `true` if this is the child process of the `fork()` - #[inline] - pub fn is_child(self) -> bool { - matches!(self, ForkResult::Child) - } - - /// Returns `true` if this is the parent process of the `fork()` - #[inline] - pub fn is_parent(self) -> bool { - !self.is_child() - } -} - -/// Create a new child process duplicating the parent process ([see -/// fork(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html)). -/// -/// After calling the fork system call (successfully) two processes will -/// be created that are identical with the exception of their pid and the -/// return value of this function. As an example: -/// -/// ``` -/// use nix::{sys::wait::waitpid,unistd::{fork, ForkResult, write}}; -/// -/// match unsafe{fork()} { -/// Ok(ForkResult::Parent { child, .. }) => { -/// println!("Continuing execution in parent process, new child has pid: {}", child); -/// waitpid(child, None).unwrap(); -/// } -/// Ok(ForkResult::Child) => { -/// // Unsafe to use `println!` (or `unwrap`) here. See Safety. -/// write(libc::STDOUT_FILENO, "I'm a new child process\n".as_bytes()).ok(); -/// unsafe { libc::_exit(0) }; -/// } -/// Err(_) => println!("Fork failed"), -/// } -/// ``` -/// -/// This will print something like the following (order indeterministic). The -/// thing to note is that you end up with two processes continuing execution -/// immediately after the fork call but with different match arms. -/// -/// ```text -/// Continuing execution in parent process, new child has pid: 1234 -/// I'm a new child process -/// ``` -/// -/// # Safety -/// -/// In a multithreaded program, only [async-signal-safe] functions like `pause` -/// and `_exit` may be called by the child (the parent isn't restricted). Note -/// that memory allocation may **not** be async-signal-safe and thus must be -/// prevented. -/// -/// Those functions are only a small subset of your operating system's API, so -/// special care must be taken to only invoke code you can control and audit. -/// -/// [async-signal-safe]: https://man7.org/linux/man-pages/man7/signal-safety.7.html -#[inline] -pub unsafe fn fork() -> Result { - use self::ForkResult::*; - let res = libc::fork(); - - Errno::result(res).map(|res| match res { - 0 => Child, - res => Parent { child: Pid(res) }, - }) -} - -/// Get the pid of this process (see -/// [getpid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpid.html)). -/// -/// Since you are running code, there is always a pid to return, so there -/// is no error case that needs to be handled. -#[inline] -pub fn getpid() -> Pid { - Pid(unsafe { libc::getpid() }) -} - -/// Get the pid of this processes' parent (see -/// [getpid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getppid.html)). -/// -/// There is always a parent pid to return, so there is no error case that needs -/// to be handled. -#[inline] -pub fn getppid() -> Pid { - Pid(unsafe { libc::getppid() }) // no error handling, according to man page: "These functions are always successful." -} - -/// Set a process group ID (see -/// [setpgid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setpgid.html)). -/// -/// Set the process group id (PGID) of a particular process. If a pid of zero -/// is specified, then the pid of the calling process is used. Process groups -/// may be used to group together a set of processes in order for the OS to -/// apply some operations across the group. -/// -/// `setsid()` may be used to create a new process group. -#[inline] -pub fn setpgid(pid: Pid, pgid: Pid) -> Result<()> { - let res = unsafe { libc::setpgid(pid.into(), pgid.into()) }; - Errno::result(res).map(drop) -} -#[inline] -pub fn getpgid(pid: Option) -> Result { - let res = unsafe { libc::getpgid(pid.unwrap_or(Pid(0)).into()) }; - Errno::result(res).map(Pid) -} - -/// Create new session and set process group id (see -/// [setsid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setsid.html)). -#[inline] -pub fn setsid() -> Result { - Errno::result(unsafe { libc::setsid() }).map(Pid) -} - -/// Get the process group ID of a session leader -/// [getsid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsid.html). -/// -/// Obtain the process group ID of the process that is the session leader of the process specified -/// by pid. If pid is zero, it specifies the calling process. -#[inline] -#[cfg(not(target_os = "redox"))] -pub fn getsid(pid: Option) -> Result { - let res = unsafe { libc::getsid(pid.unwrap_or(Pid(0)).into()) }; - Errno::result(res).map(Pid) -} - - -/// Get the terminal foreground process group (see -/// [tcgetpgrp(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetpgrp.html)). -/// -/// Get the group process id (GPID) of the foreground process group on the -/// terminal associated to file descriptor (FD). -#[inline] -pub fn tcgetpgrp(fd: c_int) -> Result { - let res = unsafe { libc::tcgetpgrp(fd) }; - Errno::result(res).map(Pid) -} -/// Set the terminal foreground process group (see -/// [tcgetpgrp(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetpgrp.html)). -/// -/// Get the group process id (PGID) to the foreground process group on the -/// terminal associated to file descriptor (FD). -#[inline] -pub fn tcsetpgrp(fd: c_int, pgrp: Pid) -> Result<()> { - let res = unsafe { libc::tcsetpgrp(fd, pgrp.into()) }; - Errno::result(res).map(drop) -} - - -/// Get the group id of the calling process (see -///[getpgrp(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgrp.html)). -/// -/// Get the process group id (PGID) of the calling process. -/// According to the man page it is always successful. -#[inline] -pub fn getpgrp() -> Pid { - Pid(unsafe { libc::getpgrp() }) -} - -/// Get the caller's thread ID (see -/// [gettid(2)](https://man7.org/linux/man-pages/man2/gettid.2.html). -/// -/// This function is only available on Linux based systems. In a single -/// threaded process, the main thread will have the same ID as the process. In -/// a multithreaded process, each thread will have a unique thread id but the -/// same process ID. -/// -/// No error handling is required as a thread id should always exist for any -/// process, even if threads are not being used. -#[cfg(any(target_os = "linux", target_os = "android"))] -#[inline] -pub fn gettid() -> Pid { - Pid(unsafe { libc::syscall(libc::SYS_gettid) as pid_t }) -} - -/// Create a copy of the specified file descriptor (see -/// [dup(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)). -/// -/// The new file descriptor will be have a new index but refer to the same -/// resource as the old file descriptor and the old and new file descriptors may -/// be used interchangeably. The new and old file descriptor share the same -/// underlying resource, offset, and file status flags. The actual index used -/// for the file descriptor will be the lowest fd index that is available. -/// -/// The two file descriptors do not share file descriptor flags (e.g. `OFlag::FD_CLOEXEC`). -#[inline] -pub fn dup(oldfd: RawFd) -> Result { - let res = unsafe { libc::dup(oldfd) }; - - Errno::result(res) -} - -/// Create a copy of the specified file descriptor using the specified fd (see -/// [dup(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)). -/// -/// This function behaves similar to `dup()` except that it will try to use the -/// specified fd instead of allocating a new one. See the man pages for more -/// detail on the exact behavior of this function. -#[inline] -pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result { - let res = unsafe { libc::dup2(oldfd, newfd) }; - - Errno::result(res) -} - -/// Create a new copy of the specified file descriptor using the specified fd -/// and flags (see [dup(2)](https://man7.org/linux/man-pages/man2/dup.2.html)). -/// -/// This function behaves similar to `dup2()` but allows for flags to be -/// specified. -pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result { - dup3_polyfill(oldfd, newfd, flags) -} - -#[inline] -fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result { - if oldfd == newfd { - return Err(Errno::EINVAL); - } - - let fd = dup2(oldfd, newfd)?; - - if flags.contains(OFlag::O_CLOEXEC) { - if let Err(e) = fcntl(fd, F_SETFD(FdFlag::FD_CLOEXEC)) { - let _ = close(fd); - return Err(e); - } - } - - Ok(fd) -} - -/// Change the current working directory of the calling process (see -/// [chdir(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html)). -/// -/// This function may fail in a number of different scenarios. See the man -/// pages for additional details on possible failure cases. -#[inline] -pub fn chdir(path: &P) -> Result<()> { - let res = path.with_nix_path(|cstr| { - unsafe { libc::chdir(cstr.as_ptr()) } - })?; - - Errno::result(res).map(drop) -} - -/// Change the current working directory of the process to the one -/// given as an open file descriptor (see -/// [fchdir(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html)). -/// -/// This function may fail in a number of different scenarios. See the man -/// pages for additional details on possible failure cases. -#[inline] -#[cfg(not(target_os = "fuchsia"))] -pub fn fchdir(dirfd: RawFd) -> Result<()> { - let res = unsafe { libc::fchdir(dirfd) }; - - Errno::result(res).map(drop) -} - -/// Creates new directory `path` with access rights `mode`. (see [mkdir(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdir.html)) -/// -/// # Errors -/// -/// There are several situations where mkdir might fail: -/// -/// - current user has insufficient rights in the parent directory -/// - the path already exists -/// - the path name is too long (longer than `PATH_MAX`, usually 4096 on linux, 1024 on OS X) -/// -/// # Example -/// -/// ```rust -/// use nix::unistd; -/// use nix::sys::stat; -/// use tempfile::tempdir; -/// -/// let tmp_dir1 = tempdir().unwrap(); -/// let tmp_dir2 = tmp_dir1.path().join("new_dir"); -/// -/// // create new directory and give read, write and execute rights to the owner -/// match unistd::mkdir(&tmp_dir2, stat::Mode::S_IRWXU) { -/// Ok(_) => println!("created {:?}", tmp_dir2), -/// Err(err) => println!("Error creating directory: {}", err), -/// } -/// ``` -#[inline] -pub fn mkdir(path: &P, mode: Mode) -> Result<()> { - let res = path.with_nix_path(|cstr| { - unsafe { libc::mkdir(cstr.as_ptr(), mode.bits() as mode_t) } - })?; - - Errno::result(res).map(drop) -} - -/// Creates new fifo special file (named pipe) with path `path` and access rights `mode`. -/// -/// # Errors -/// -/// There are several situations where mkfifo might fail: -/// -/// - current user has insufficient rights in the parent directory -/// - the path already exists -/// - the path name is too long (longer than `PATH_MAX`, usually 4096 on linux, 1024 on OS X) -/// -/// For a full list consult -/// [posix specification](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifo.html) -/// -/// # Example -/// -/// ```rust -/// use nix::unistd; -/// use nix::sys::stat; -/// use tempfile::tempdir; -/// -/// let tmp_dir = tempdir().unwrap(); -/// let fifo_path = tmp_dir.path().join("foo.pipe"); -/// -/// // create new fifo and give read, write and execute rights to the owner -/// match unistd::mkfifo(&fifo_path, stat::Mode::S_IRWXU) { -/// Ok(_) => println!("created {:?}", fifo_path), -/// Err(err) => println!("Error creating fifo: {}", err), -/// } -/// ``` -#[inline] -#[cfg(not(target_os = "redox"))] // RedoxFS does not support fifo yet -pub fn mkfifo(path: &P, mode: Mode) -> Result<()> { - let res = path.with_nix_path(|cstr| { - unsafe { libc::mkfifo(cstr.as_ptr(), mode.bits() as mode_t) } - })?; - - Errno::result(res).map(drop) -} - -/// Creates new fifo special file (named pipe) with path `path` and access rights `mode`. -/// -/// If `dirfd` has a value, then `path` is relative to directory associated with the file descriptor. -/// -/// If `dirfd` is `None`, then `path` is relative to the current working directory. -/// -/// # References -/// -/// [mkfifoat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifoat.html). -// mkfifoat is not implemented in OSX or android -#[inline] -#[cfg(not(any( - target_os = "macos", target_os = "ios", - target_os = "android", target_os = "redox")))] -pub fn mkfifoat(dirfd: Option, path: &P, mode: Mode) -> Result<()> { - let res = path.with_nix_path(|cstr| unsafe { - libc::mkfifoat(at_rawfd(dirfd), cstr.as_ptr(), mode.bits() as mode_t) - })?; - - Errno::result(res).map(drop) -} - -/// Creates a symbolic link at `path2` which points to `path1`. -/// -/// If `dirfd` has a value, then `path2` is relative to directory associated -/// with the file descriptor. -/// -/// If `dirfd` is `None`, then `path2` is relative to the current working -/// directory. This is identical to `libc::symlink(path1, path2)`. -/// -/// See also [symlinkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html). -#[cfg(not(target_os = "redox"))] -pub fn symlinkat( - path1: &P1, - dirfd: Option, - path2: &P2) -> Result<()> { - let res = - path1.with_nix_path(|path1| { - path2.with_nix_path(|path2| { - unsafe { - libc::symlinkat( - path1.as_ptr(), - dirfd.unwrap_or(libc::AT_FDCWD), - path2.as_ptr() - ) - } - }) - })??; - Errno::result(res).map(drop) -} - -// Double the buffer capacity up to limit. In case it already has -// reached the limit, return Errno::ERANGE. -fn reserve_double_buffer_size(buf: &mut Vec, limit: usize) -> Result<()> { - use std::cmp::min; - - if buf.capacity() >= limit { - return Err(Errno::ERANGE) - } - - let capacity = min(buf.capacity() * 2, limit); - buf.reserve(capacity); - - Ok(()) -} - -/// Returns the current directory as a `PathBuf` -/// -/// Err is returned if the current user doesn't have the permission to read or search a component -/// of the current path. -/// -/// # Example -/// -/// ```rust -/// use nix::unistd; -/// -/// // assume that we are allowed to get current directory -/// let dir = unistd::getcwd().unwrap(); -/// println!("The current directory is {:?}", dir); -/// ``` -#[inline] -pub fn getcwd() -> Result { - let mut buf = Vec::with_capacity(512); - loop { - unsafe { - let ptr = buf.as_mut_ptr() as *mut c_char; - - // The buffer must be large enough to store the absolute pathname plus - // a terminating null byte, or else null is returned. - // To safely handle this we start with a reasonable size (512 bytes) - // and double the buffer size upon every error - if !libc::getcwd(ptr, buf.capacity()).is_null() { - let len = CStr::from_ptr(buf.as_ptr() as *const c_char).to_bytes().len(); - buf.set_len(len); - buf.shrink_to_fit(); - return Ok(PathBuf::from(OsString::from_vec(buf))); - } else { - let error = Errno::last(); - // ERANGE means buffer was too small to store directory name - if error != Errno::ERANGE { - return Err(error); - } - } - - // Trigger the internal buffer resizing logic. - reserve_double_buffer_size(&mut buf, PATH_MAX as usize)?; - } - } -} - -/// Computes the raw UID and GID values to pass to a `*chown` call. -// The cast is not unnecessary on all platforms. -#[allow(clippy::unnecessary_cast)] -fn chown_raw_ids(owner: Option, group: Option) -> (libc::uid_t, libc::gid_t) { - // According to the POSIX specification, -1 is used to indicate that owner and group - // are not to be changed. Since uid_t and gid_t are unsigned types, we have to wrap - // around to get -1. - let uid = owner.map(Into::into) - .unwrap_or_else(|| (0 as uid_t).wrapping_sub(1)); - let gid = group.map(Into::into) - .unwrap_or_else(|| (0 as gid_t).wrapping_sub(1)); - (uid, gid) -} - -/// Change the ownership of the file at `path` to be owned by the specified -/// `owner` (user) and `group` (see -/// [chown(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/chown.html)). -/// -/// The owner/group for the provided path name will not be modified if `None` is -/// provided for that argument. Ownership change will be attempted for the path -/// only if `Some` owner/group is provided. -#[inline] -pub fn chown(path: &P, owner: Option, group: Option) -> Result<()> { - let res = path.with_nix_path(|cstr| { - let (uid, gid) = chown_raw_ids(owner, group); - unsafe { libc::chown(cstr.as_ptr(), uid, gid) } - })?; - - Errno::result(res).map(drop) -} - -/// Change the ownership of the file referred to by the open file descriptor `fd` to be owned by -/// the specified `owner` (user) and `group` (see -/// [fchown(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchown.html)). -/// -/// The owner/group for the provided file will not be modified if `None` is -/// provided for that argument. Ownership change will be attempted for the path -/// only if `Some` owner/group is provided. -#[inline] -pub fn fchown(fd: RawFd, owner: Option, group: Option) -> Result<()> { - let (uid, gid) = chown_raw_ids(owner, group); - let res = unsafe { libc::fchown(fd, uid, gid) }; - Errno::result(res).map(drop) -} - -/// Flags for `fchownat` function. -#[derive(Clone, Copy, Debug)] -pub enum FchownatFlags { - FollowSymlink, - NoFollowSymlink, -} - -/// Change the ownership of the file at `path` to be owned by the specified -/// `owner` (user) and `group`. -/// -/// The owner/group for the provided path name will not be modified if `None` is -/// provided for that argument. Ownership change will be attempted for the path -/// only if `Some` owner/group is provided. -/// -/// The file to be changed is determined relative to the directory associated -/// with the file descriptor `dirfd` or the current working directory -/// if `dirfd` is `None`. -/// -/// If `flag` is `FchownatFlags::NoFollowSymlink` and `path` names a symbolic link, -/// then the mode of the symbolic link is changed. -/// -/// `fchownat(None, path, mode, FchownatFlags::NoFollowSymlink)` is identical to -/// a call `libc::lchown(path, mode)`. That's why `lchmod` is unimplemented in -/// the `nix` crate. -/// -/// # References -/// -/// [fchownat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchownat.html). -#[cfg(not(target_os = "redox"))] -pub fn fchownat( - dirfd: Option, - path: &P, - owner: Option, - group: Option, - flag: FchownatFlags, -) -> Result<()> { - let atflag = - match flag { - FchownatFlags::FollowSymlink => AtFlags::empty(), - FchownatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW, - }; - let res = path.with_nix_path(|cstr| unsafe { - let (uid, gid) = chown_raw_ids(owner, group); - libc::fchownat(at_rawfd(dirfd), cstr.as_ptr(), uid, gid, - atflag.bits() as libc::c_int) - })?; - - Errno::result(res).map(drop) -} - -fn to_exec_array>(args: &[S]) -> Vec<*const c_char> { - use std::iter::once; - args.iter().map(|s| s.as_ref().as_ptr()).chain(once(ptr::null())).collect() -} - -/// Replace the current process image with a new one (see -/// [exec(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)). -/// -/// See the `::nix::unistd::execve` system call for additional details. `execv` -/// performs the same action but does not allow for customization of the -/// environment for the new process. -#[inline] -pub fn execv>(path: &CStr, argv: &[S]) -> Result { - let args_p = to_exec_array(argv); - - unsafe { - libc::execv(path.as_ptr(), args_p.as_ptr()) - }; - - Err(Errno::last()) -} - - -/// Replace the current process image with a new one (see -/// [execve(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)). -/// -/// The execve system call allows for another process to be "called" which will -/// replace the current process image. That is, this process becomes the new -/// command that is run. On success, this function will not return. Instead, -/// the new program will run until it exits. -/// -/// `::nix::unistd::execv` and `::nix::unistd::execve` take as arguments a slice -/// of `::std::ffi::CString`s for `args` and `env` (for `execve`). Each element -/// in the `args` list is an argument to the new process. Each element in the -/// `env` list should be a string in the form "key=value". -#[inline] -pub fn execve, SE: AsRef>(path: &CStr, args: &[SA], env: &[SE]) -> Result { - let args_p = to_exec_array(args); - let env_p = to_exec_array(env); - - unsafe { - libc::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr()) - }; - - Err(Errno::last()) -} - -/// Replace the current process image with a new one and replicate shell `PATH` -/// searching behavior (see -/// [exec(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)). -/// -/// See `::nix::unistd::execve` for additional details. `execvp` behaves the -/// same as execv except that it will examine the `PATH` environment variables -/// for file names not specified with a leading slash. For example, `execv` -/// would not work if "bash" was specified for the path argument, but `execvp` -/// would assuming that a bash executable was on the system `PATH`. -#[inline] -pub fn execvp>(filename: &CStr, args: &[S]) -> Result { - let args_p = to_exec_array(args); - - unsafe { - libc::execvp(filename.as_ptr(), args_p.as_ptr()) - }; - - Err(Errno::last()) -} - -/// Replace the current process image with a new one and replicate shell `PATH` -/// searching behavior (see -/// [`execvpe(3)`](https://man7.org/linux/man-pages/man3/exec.3.html)). -/// -/// This functions like a combination of `execvp(2)` and `execve(2)` to pass an -/// environment and have a search path. See these two for additional -/// information. -#[cfg(any(target_os = "haiku", - target_os = "linux", - target_os = "openbsd"))] -pub fn execvpe, SE: AsRef>(filename: &CStr, args: &[SA], env: &[SE]) -> Result { - let args_p = to_exec_array(args); - let env_p = to_exec_array(env); - - unsafe { - libc::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr()) - }; - - Err(Errno::last()) -} - -/// Replace the current process image with a new one (see -/// [fexecve(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fexecve.html)). -/// -/// The `fexecve` function allows for another process to be "called" which will -/// replace the current process image. That is, this process becomes the new -/// command that is run. On success, this function will not return. Instead, -/// the new program will run until it exits. -/// -/// This function is similar to `execve`, except that the program to be executed -/// is referenced as a file descriptor instead of a path. -// Note for NetBSD and OpenBSD: although rust-lang/libc includes it (under -// unix/bsd/netbsdlike/) fexecve is not currently implemented on NetBSD nor on -// OpenBSD. -#[cfg(any(target_os = "android", - target_os = "linux", - target_os = "freebsd"))] -#[inline] -pub fn fexecve ,SE: AsRef>(fd: RawFd, args: &[SA], env: &[SE]) -> Result { - let args_p = to_exec_array(args); - let env_p = to_exec_array(env); - - unsafe { - libc::fexecve(fd, args_p.as_ptr(), env_p.as_ptr()) - }; - - Err(Errno::last()) -} - -/// Execute program relative to a directory file descriptor (see -/// [execveat(2)](https://man7.org/linux/man-pages/man2/execveat.2.html)). -/// -/// The `execveat` function allows for another process to be "called" which will -/// replace the current process image. That is, this process becomes the new -/// command that is run. On success, this function will not return. Instead, -/// the new program will run until it exits. -/// -/// This function is similar to `execve`, except that the program to be executed -/// is referenced as a file descriptor to the base directory plus a path. -#[cfg(any(target_os = "android", target_os = "linux"))] -#[inline] -pub fn execveat,SE: AsRef>(dirfd: RawFd, pathname: &CStr, args: &[SA], - env: &[SE], flags: super::fcntl::AtFlags) -> Result { - let args_p = to_exec_array(args); - let env_p = to_exec_array(env); - - unsafe { - libc::syscall(libc::SYS_execveat, dirfd, pathname.as_ptr(), - args_p.as_ptr(), env_p.as_ptr(), flags); - }; - - Err(Errno::last()) -} - -/// Daemonize this process by detaching from the controlling terminal (see -/// [daemon(3)](https://man7.org/linux/man-pages/man3/daemon.3.html)). -/// -/// When a process is launched it is typically associated with a parent and it, -/// in turn, by its controlling terminal/process. In order for a process to run -/// in the "background" it must daemonize itself by detaching itself. Under -/// posix, this is done by doing the following: -/// -/// 1. Parent process (this one) forks -/// 2. Parent process exits -/// 3. Child process continues to run. -/// -/// `nochdir`: -/// -/// * `nochdir = true`: The current working directory after daemonizing will -/// be the current working directory. -/// * `nochdir = false`: The current working directory after daemonizing will -/// be the root direcory, `/`. -/// -/// `noclose`: -/// -/// * `noclose = true`: The process' current stdin, stdout, and stderr file -/// descriptors will remain identical after daemonizing. -/// * `noclose = false`: The process' stdin, stdout, and stderr will point to -/// `/dev/null` after daemonizing. -#[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "illumos", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris"))] -pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> { - let res = unsafe { libc::daemon(nochdir as c_int, noclose as c_int) }; - Errno::result(res).map(drop) -} - -/// Set the system host name (see -/// [sethostname(2)](https://man7.org/linux/man-pages/man2/gethostname.2.html)). -/// -/// Given a name, attempt to update the system host name to the given string. -/// On some systems, the host name is limited to as few as 64 bytes. An error -/// will be return if the name is not valid or the current process does not have -/// permissions to update the host name. -#[cfg(not(target_os = "redox"))] -pub fn sethostname>(name: S) -> Result<()> { - // Handle some differences in type of the len arg across platforms. - cfg_if! { - if #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "illumos", - target_os = "ios", - target_os = "macos", - target_os = "solaris", ))] { - type sethostname_len_t = c_int; - } else { - type sethostname_len_t = size_t; - } - } - let ptr = name.as_ref().as_bytes().as_ptr() as *const c_char; - let len = name.as_ref().len() as sethostname_len_t; - - let res = unsafe { libc::sethostname(ptr, len) }; - Errno::result(res).map(drop) -} - -/// Get the host name and store it in the provided buffer, returning a pointer -/// the `CStr` in that buffer on success (see -/// [gethostname(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html)). -/// -/// This function call attempts to get the host name for the running system and -/// store it in a provided buffer. The buffer will be populated with bytes up -/// to the length of the provided slice including a NUL terminating byte. If -/// the hostname is longer than the length provided, no error will be provided. -/// The posix specification does not specify whether implementations will -/// null-terminate in this case, but the nix implementation will ensure that the -/// buffer is null terminated in this case. -/// -/// ```no_run -/// use nix::unistd; -/// -/// let mut buf = [0u8; 64]; -/// let hostname_cstr = unistd::gethostname(&mut buf).expect("Failed getting hostname"); -/// let hostname = hostname_cstr.to_str().expect("Hostname wasn't valid UTF-8"); -/// println!("Hostname: {}", hostname); -/// ``` -pub fn gethostname(buffer: &mut [u8]) -> Result<&CStr> { - let ptr = buffer.as_mut_ptr() as *mut c_char; - let len = buffer.len() as size_t; - - let res = unsafe { libc::gethostname(ptr, len) }; - Errno::result(res).map(|_| { - buffer[len - 1] = 0; // ensure always null-terminated - unsafe { CStr::from_ptr(buffer.as_ptr() as *const c_char) } - }) -} - -/// Close a raw file descriptor -/// -/// Be aware that many Rust types implicitly close-on-drop, including -/// `std::fs::File`. Explicitly closing them with this method too can result in -/// a double-close condition, which can cause confusing `EBADF` errors in -/// seemingly unrelated code. Caveat programmer. See also -/// [close(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html). -/// -/// # Examples -/// -/// ```no_run -/// use std::os::unix::io::AsRawFd; -/// use nix::unistd::close; -/// -/// let f = tempfile::tempfile().unwrap(); -/// close(f.as_raw_fd()).unwrap(); // Bad! f will also close on drop! -/// ``` -/// -/// ```rust -/// use std::os::unix::io::IntoRawFd; -/// use nix::unistd::close; -/// -/// let f = tempfile::tempfile().unwrap(); -/// close(f.into_raw_fd()).unwrap(); // Good. into_raw_fd consumes f -/// ``` -pub fn close(fd: RawFd) -> Result<()> { - let res = unsafe { libc::close(fd) }; - Errno::result(res).map(drop) -} - -/// Read from a raw file descriptor. -/// -/// See also [read(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html) -pub fn read(fd: RawFd, buf: &mut [u8]) -> Result { - let res = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) }; - - Errno::result(res).map(|r| r as usize) -} - -/// Write to a raw file descriptor. -/// -/// See also [write(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html) -pub fn write(fd: RawFd, buf: &[u8]) -> Result { - let res = unsafe { libc::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) }; - - Errno::result(res).map(|r| r as usize) -} - -/// Directive that tells [`lseek`] and [`lseek64`] what the offset is relative to. -/// -/// [`lseek`]: ./fn.lseek.html -/// [`lseek64`]: ./fn.lseek64.html -#[repr(i32)] -#[derive(Clone, Copy, Debug)] -pub enum Whence { - /// Specify an offset relative to the start of the file. - SeekSet = libc::SEEK_SET, - /// Specify an offset relative to the current file location. - SeekCur = libc::SEEK_CUR, - /// Specify an offset relative to the end of the file. - SeekEnd = libc::SEEK_END, - /// Specify an offset relative to the next location in the file greater than or - /// equal to offset that contains some data. If offset points to - /// some data, then the file offset is set to offset. - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "illumos", - target_os = "linux", - target_os = "solaris"))] - SeekData = libc::SEEK_DATA, - /// Specify an offset relative to the next hole in the file greater than - /// or equal to offset. If offset points into the middle of a hole, then - /// the file offset should be set to offset. If there is no hole past offset, - /// then the file offset should be adjusted to the end of the file (i.e., there - /// is an implicit hole at the end of any file). - #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "illumos", - target_os = "linux", - target_os = "solaris"))] - SeekHole = libc::SEEK_HOLE -} - -/// Move the read/write file offset. -/// -/// See also [lseek(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html) -pub fn lseek(fd: RawFd, offset: off_t, whence: Whence) -> Result { - let res = unsafe { libc::lseek(fd, offset, whence as i32) }; - - Errno::result(res).map(|r| r as off_t) -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -pub fn lseek64(fd: RawFd, offset: libc::off64_t, whence: Whence) -> Result { - let res = unsafe { libc::lseek64(fd, offset, whence as i32) }; - - Errno::result(res).map(|r| r as libc::off64_t) -} - -/// Create an interprocess channel. -/// -/// See also [pipe(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html) -pub fn pipe() -> std::result::Result<(RawFd, RawFd), Error> { - unsafe { - let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit(); - - let res = libc::pipe(fds.as_mut_ptr() as *mut c_int); - - Error::result(res)?; - - Ok((fds.assume_init()[0], fds.assume_init()[1])) - } -} - -/// Like `pipe`, but allows setting certain file descriptor flags. -/// -/// The following flags are supported, and will be set atomically as the pipe is -/// created: -/// -/// `O_CLOEXEC`: Set the close-on-exec flag for the new file descriptors. -#[cfg_attr(target_os = "linux", doc = "`O_DIRECT`: Create a pipe that performs I/O in \"packet\" mode. ")] -#[cfg_attr(target_os = "netbsd", doc = "`O_NOSIGPIPE`: Return `EPIPE` instead of raising `SIGPIPE`. ")] -/// `O_NONBLOCK`: Set the non-blocking flag for the ends of the pipe. -/// -/// See also [pipe(2)](https://man7.org/linux/man-pages/man2/pipe.2.html) -#[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "illumos", - target_os = "linux", - target_os = "redox", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris"))] -pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> { - let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit(); - - let res = unsafe { - libc::pipe2(fds.as_mut_ptr() as *mut c_int, flags.bits()) - }; - - Errno::result(res)?; - - unsafe { Ok((fds.assume_init()[0], fds.assume_init()[1])) } -} - -/// Truncate a file to a specified length -/// -/// See also -/// [truncate(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html) -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -pub fn truncate(path: &P, len: off_t) -> Result<()> { - let res = path.with_nix_path(|cstr| { - unsafe { - libc::truncate(cstr.as_ptr(), len) - } - })?; - - Errno::result(res).map(drop) -} - -/// Truncate a file to a specified length -/// -/// See also -/// [ftruncate(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html) -pub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> { - Errno::result(unsafe { libc::ftruncate(fd, len) }).map(drop) -} - -pub fn isatty(fd: RawFd) -> Result { - unsafe { - // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so - // we return `Ok(false)` - if libc::isatty(fd) == 1 { - Ok(true) - } else { - match Errno::last() { - Errno::ENOTTY => Ok(false), - err => Err(err), - } - } - } -} - -/// Flags for `linkat` function. -#[derive(Clone, Copy, Debug)] -pub enum LinkatFlags { - SymlinkFollow, - NoSymlinkFollow, -} - -/// Link one file to another file -/// -/// Creates a new link (directory entry) at `newpath` for the existing file at `oldpath`. In the -/// case of a relative `oldpath`, the path is interpreted relative to the directory associated -/// with file descriptor `olddirfd` instead of the current working directory and similiarly for -/// `newpath` and file descriptor `newdirfd`. In case `flag` is LinkatFlags::SymlinkFollow and -/// `oldpath` names a symoblic link, a new link for the target of the symbolic link is created. -/// If either `olddirfd` or `newdirfd` is `None`, `AT_FDCWD` is used respectively where `oldpath` -/// and/or `newpath` is then interpreted relative to the current working directory of the calling -/// process. If either `oldpath` or `newpath` is absolute, then `dirfd` is ignored. -/// -/// # References -/// See also [linkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html) -#[cfg(not(target_os = "redox"))] // RedoxFS does not support symlinks yet -pub fn linkat( - olddirfd: Option, - oldpath: &P, - newdirfd: Option, - newpath: &P, - flag: LinkatFlags, -) -> Result<()> { - - let atflag = - match flag { - LinkatFlags::SymlinkFollow => AtFlags::AT_SYMLINK_FOLLOW, - LinkatFlags::NoSymlinkFollow => AtFlags::empty(), - }; - - let res = - oldpath.with_nix_path(|oldcstr| { - newpath.with_nix_path(|newcstr| { - unsafe { - libc::linkat( - at_rawfd(olddirfd), - oldcstr.as_ptr(), - at_rawfd(newdirfd), - newcstr.as_ptr(), - atflag.bits() as libc::c_int - ) - } - }) - })??; - Errno::result(res).map(drop) -} - - -/// Remove a directory entry -/// -/// See also [unlink(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html) -pub fn unlink(path: &P) -> Result<()> { - let res = path.with_nix_path(|cstr| { - unsafe { - libc::unlink(cstr.as_ptr()) - } - })?; - Errno::result(res).map(drop) -} - -/// Flags for `unlinkat` function. -#[derive(Clone, Copy, Debug)] -pub enum UnlinkatFlags { - RemoveDir, - NoRemoveDir, -} - -/// Remove a directory entry -/// -/// In the case of a relative path, the directory entry to be removed is determined relative to -/// the directory associated with the file descriptor `dirfd` or the current working directory -/// if `dirfd` is `None`. In the case of an absolute `path` `dirfd` is ignored. If `flag` is -/// `UnlinkatFlags::RemoveDir` then removal of the directory entry specified by `dirfd` and `path` -/// is performed. -/// -/// # References -/// See also [unlinkat(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html) -#[cfg(not(target_os = "redox"))] -pub fn unlinkat( - dirfd: Option, - path: &P, - flag: UnlinkatFlags, -) -> Result<()> { - let atflag = - match flag { - UnlinkatFlags::RemoveDir => AtFlags::AT_REMOVEDIR, - UnlinkatFlags::NoRemoveDir => AtFlags::empty(), - }; - let res = path.with_nix_path(|cstr| { - unsafe { - libc::unlinkat(at_rawfd(dirfd), cstr.as_ptr(), atflag.bits() as libc::c_int) - } - })?; - Errno::result(res).map(drop) -} - - -#[inline] -#[cfg(not(target_os = "fuchsia"))] -pub fn chroot(path: &P) -> Result<()> { - let res = path.with_nix_path(|cstr| { - unsafe { libc::chroot(cstr.as_ptr()) } - })?; - - Errno::result(res).map(drop) -} - -/// Commit filesystem caches to disk -/// -/// See also [sync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sync.html) -#[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd" -))] -pub fn sync() { - unsafe { libc::sync() }; -} - -/// Synchronize changes to a file -/// -/// See also [fsync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html) -#[inline] -pub fn fsync(fd: RawFd) -> Result<()> { - let res = unsafe { libc::fsync(fd) }; - - Errno::result(res).map(drop) -} - -/// Synchronize the data of a file -/// -/// See also -/// [fdatasync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html) -// `fdatasync(2) is in POSIX, but in libc it is only defined in `libc::notbsd`. -// TODO: exclude only Apple systems after https://github.com/rust-lang/libc/pull/211 -#[cfg(any(target_os = "linux", - target_os = "android", - target_os = "emscripten", - target_os = "illumos", - target_os = "solaris"))] -#[inline] -pub fn fdatasync(fd: RawFd) -> Result<()> { - let res = unsafe { libc::fdatasync(fd) }; - - Errno::result(res).map(drop) -} - -/// Get a real user ID -/// -/// See also [getuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html) -// POSIX requires that getuid is always successful, so no need to check return -// value or errno. -#[inline] -pub fn getuid() -> Uid { - Uid(unsafe { libc::getuid() }) -} - -/// Get the effective user ID -/// -/// See also [geteuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html) -// POSIX requires that geteuid is always successful, so no need to check return -// value or errno. -#[inline] -pub fn geteuid() -> Uid { - Uid(unsafe { libc::geteuid() }) -} - -/// Get the real group ID -/// -/// See also [getgid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getgid.html) -// POSIX requires that getgid is always successful, so no need to check return -// value or errno. -#[inline] -pub fn getgid() -> Gid { - Gid(unsafe { libc::getgid() }) -} - -/// Get the effective group ID -/// -/// See also [getegid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getegid.html) -// POSIX requires that getegid is always successful, so no need to check return -// value or errno. -#[inline] -pub fn getegid() -> Gid { - Gid(unsafe { libc::getegid() }) -} - -/// Set the effective user ID -/// -/// See also [seteuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/seteuid.html) -#[inline] -pub fn seteuid(euid: Uid) -> Result<()> { - let res = unsafe { libc::seteuid(euid.into()) }; - - Errno::result(res).map(drop) -} - -/// Set the effective group ID -/// -/// See also [setegid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setegid.html) -#[inline] -pub fn setegid(egid: Gid) -> Result<()> { - let res = unsafe { libc::setegid(egid.into()) }; - - Errno::result(res).map(drop) -} - -/// Set the user ID -/// -/// See also [setuid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setuid.html) -#[inline] -pub fn setuid(uid: Uid) -> Result<()> { - let res = unsafe { libc::setuid(uid.into()) }; - - Errno::result(res).map(drop) -} - -/// Set the group ID -/// -/// See also [setgid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/setgid.html) -#[inline] -pub fn setgid(gid: Gid) -> Result<()> { - let res = unsafe { libc::setgid(gid.into()) }; - - Errno::result(res).map(drop) -} - -/// Set the user identity used for filesystem checks per-thread. -/// On both success and failure, this call returns the previous filesystem user -/// ID of the caller. -/// -/// See also [setfsuid(2)](https://man7.org/linux/man-pages/man2/setfsuid.2.html) -#[cfg(any(target_os = "linux", target_os = "android"))] -pub fn setfsuid(uid: Uid) -> Uid { - let prev_fsuid = unsafe { libc::setfsuid(uid.into()) }; - Uid::from_raw(prev_fsuid as uid_t) -} - -/// Set the group identity used for filesystem checks per-thread. -/// On both success and failure, this call returns the previous filesystem group -/// ID of the caller. -/// -/// See also [setfsgid(2)](https://man7.org/linux/man-pages/man2/setfsgid.2.html) -#[cfg(any(target_os = "linux", target_os = "android"))] -pub fn setfsgid(gid: Gid) -> Gid { - let prev_fsgid = unsafe { libc::setfsgid(gid.into()) }; - Gid::from_raw(prev_fsgid as gid_t) -} - -/// Get the list of supplementary group IDs of the calling process. -/// -/// [Further reading](https://pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html) -/// -/// **Note:** This function is not available for Apple platforms. On those -/// platforms, checking group membership should be achieved via communication -/// with the `opendirectoryd` service. -#[cfg(not(any(target_os = "ios", target_os = "macos")))] -pub fn getgroups() -> Result> { - // First get the maximum number of groups. The value returned - // shall always be greater than or equal to one and less than or - // equal to the value of {NGROUPS_MAX} + 1. - let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) { - Ok(Some(n)) => (n + 1) as usize, - Ok(None) | Err(_) => ::max_value(), - }; - - // Next, get the number of groups so we can size our Vec - let ngroups = unsafe { libc::getgroups(0, ptr::null_mut()) }; - - // If there are no supplementary groups, return early. - // This prevents a potential buffer over-read if the number of groups - // increases from zero before the next call. It would return the total - // number of groups beyond the capacity of the buffer. - if ngroups == 0 { - return Ok(Vec::new()); - } - - // Now actually get the groups. We try multiple times in case the number of - // groups has changed since the first call to getgroups() and the buffer is - // now too small. - let mut groups = Vec::::with_capacity(Errno::result(ngroups)? as usize); - loop { - // FIXME: On the platforms we currently support, the `Gid` struct has - // the same representation in memory as a bare `gid_t`. This is not - // necessarily the case on all Rust platforms, though. See RFC 1785. - let ngroups = unsafe { - libc::getgroups(groups.capacity() as c_int, groups.as_mut_ptr() as *mut gid_t) - }; - - match Errno::result(ngroups) { - Ok(s) => { - unsafe { groups.set_len(s as usize) }; - return Ok(groups); - }, - Err(Errno::EINVAL) => { - // EINVAL indicates that the buffer size was too - // small, resize it up to ngroups_max as limit. - reserve_double_buffer_size(&mut groups, ngroups_max) - .or(Err(Errno::EINVAL))?; - }, - Err(e) => return Err(e) - } - } -} - -/// Set the list of supplementary group IDs for the calling process. -/// -/// [Further reading](https://man7.org/linux/man-pages/man2/getgroups.2.html) -/// -/// **Note:** This function is not available for Apple platforms. On those -/// platforms, group membership management should be achieved via communication -/// with the `opendirectoryd` service. -/// -/// # Examples -/// -/// `setgroups` can be used when dropping privileges from the root user to a -/// specific user and group. For example, given the user `www-data` with UID -/// `33` and the group `backup` with the GID `34`, one could switch the user as -/// follows: -/// -/// ```rust,no_run -/// # use std::error::Error; -/// # use nix::unistd::*; -/// # -/// # fn try_main() -> Result<(), Box> { -/// let uid = Uid::from_raw(33); -/// let gid = Gid::from_raw(34); -/// setgroups(&[gid])?; -/// setgid(gid)?; -/// setuid(uid)?; -/// # -/// # Ok(()) -/// # } -/// # -/// # try_main().unwrap(); -/// ``` -#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))] -pub fn setgroups(groups: &[Gid]) -> Result<()> { - cfg_if! { - if #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "illumos", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "illumos", - target_os = "openbsd"))] { - type setgroups_ngroups_t = c_int; - } else { - type setgroups_ngroups_t = size_t; - } - } - // FIXME: On the platforms we currently support, the `Gid` struct has the - // same representation in memory as a bare `gid_t`. This is not necessarily - // the case on all Rust platforms, though. See RFC 1785. - let res = unsafe { - libc::setgroups(groups.len() as setgroups_ngroups_t, groups.as_ptr() as *const gid_t) - }; - - Errno::result(res).map(drop) -} - -/// Calculate the supplementary group access list. -/// -/// Gets the group IDs of all groups that `user` is a member of. The additional -/// group `group` is also added to the list. -/// -/// [Further reading](https://man7.org/linux/man-pages/man3/getgrouplist.3.html) -/// -/// **Note:** This function is not available for Apple platforms. On those -/// platforms, checking group membership should be achieved via communication -/// with the `opendirectoryd` service. -/// -/// # Errors -/// -/// Although the `getgrouplist()` call does not return any specific -/// errors on any known platforms, this implementation will return a system -/// error of `EINVAL` if the number of groups to be fetched exceeds the -/// `NGROUPS_MAX` sysconf value. This mimics the behaviour of `getgroups()` -/// and `setgroups()`. Additionally, while some implementations will return a -/// partial list of groups when `NGROUPS_MAX` is exceeded, this implementation -/// will only ever return the complete list or else an error. -#[cfg(not(any(target_os = "illumos", - target_os = "ios", - target_os = "macos", - target_os = "redox")))] -pub fn getgrouplist(user: &CStr, group: Gid) -> Result> { - let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) { - Ok(Some(n)) => n as c_int, - Ok(None) | Err(_) => ::max_value(), - }; - use std::cmp::min; - let mut groups = Vec::::with_capacity(min(ngroups_max, 8) as usize); - cfg_if! { - if #[cfg(any(target_os = "ios", target_os = "macos"))] { - type getgrouplist_group_t = c_int; - } else { - type getgrouplist_group_t = gid_t; - } - } - let gid: gid_t = group.into(); - loop { - let mut ngroups = groups.capacity() as i32; - let ret = unsafe { - libc::getgrouplist(user.as_ptr(), - gid as getgrouplist_group_t, - groups.as_mut_ptr() as *mut getgrouplist_group_t, - &mut ngroups) - }; - - // BSD systems only return 0 or -1, Linux returns ngroups on success. - if ret >= 0 { - unsafe { groups.set_len(ngroups as usize) }; - return Ok(groups); - } else if ret == -1 { - // Returns -1 if ngroups is too small, but does not set errno. - // BSD systems will still fill the groups buffer with as many - // groups as possible, but Linux manpages do not mention this - // behavior. - reserve_double_buffer_size(&mut groups, ngroups_max as usize) - .map_err(|_| Errno::EINVAL)?; - } - } -} - -/// Initialize the supplementary group access list. -/// -/// Sets the supplementary group IDs for the calling process using all groups -/// that `user` is a member of. The additional group `group` is also added to -/// the list. -/// -/// [Further reading](https://man7.org/linux/man-pages/man3/initgroups.3.html) -/// -/// **Note:** This function is not available for Apple platforms. On those -/// platforms, group membership management should be achieved via communication -/// with the `opendirectoryd` service. -/// -/// # Examples -/// -/// `initgroups` can be used when dropping privileges from the root user to -/// another user. For example, given the user `www-data`, we could look up the -/// UID and GID for the user in the system's password database (usually found -/// in `/etc/passwd`). If the `www-data` user's UID and GID were `33` and `33`, -/// respectively, one could switch the user as follows: -/// -/// ```rust,no_run -/// # use std::error::Error; -/// # use std::ffi::CString; -/// # use nix::unistd::*; -/// # -/// # fn try_main() -> Result<(), Box> { -/// let user = CString::new("www-data").unwrap(); -/// let uid = Uid::from_raw(33); -/// let gid = Gid::from_raw(33); -/// initgroups(&user, gid)?; -/// setgid(gid)?; -/// setuid(uid)?; -/// # -/// # Ok(()) -/// # } -/// # -/// # try_main().unwrap(); -/// ``` -#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))] -pub fn initgroups(user: &CStr, group: Gid) -> Result<()> { - cfg_if! { - if #[cfg(any(target_os = "ios", target_os = "macos"))] { - type initgroups_group_t = c_int; - } else { - type initgroups_group_t = gid_t; - } - } - let gid: gid_t = group.into(); - let res = unsafe { libc::initgroups(user.as_ptr(), gid as initgroups_group_t) }; - - Errno::result(res).map(drop) -} - -/// Suspend the thread until a signal is received. -/// -/// See also [pause(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pause.html). -#[inline] -#[cfg(not(target_os = "redox"))] -pub fn pause() { - unsafe { libc::pause() }; -} - -pub mod alarm { - //! Alarm signal scheduling. - //! - //! Scheduling an alarm will trigger a `SIGALRM` signal when the time has - //! elapsed, which has to be caught, because the default action for the - //! signal is to terminate the program. This signal also can't be ignored - //! because the system calls like `pause` will not be interrupted, see the - //! second example below. - //! - //! # Examples - //! - //! Canceling an alarm: - //! - //! ``` - //! use nix::unistd::alarm; - //! - //! // Set an alarm for 60 seconds from now. - //! alarm::set(60); - //! - //! // Cancel the above set alarm, which returns the number of seconds left - //! // of the previously set alarm. - //! assert_eq!(alarm::cancel(), Some(60)); - //! ``` - //! - //! Scheduling an alarm and waiting for the signal: - //! -#![cfg_attr(target_os = "redox", doc = " ```rust,ignore")] -#![cfg_attr(not(target_os = "redox"), doc = " ```rust")] - //! use std::time::{Duration, Instant}; - //! - //! use nix::unistd::{alarm, pause}; - //! use nix::sys::signal::*; - //! - //! // We need to setup an empty signal handler to catch the alarm signal, - //! // otherwise the program will be terminated once the signal is delivered. - //! extern fn signal_handler(_: nix::libc::c_int) { } - //! let sa = SigAction::new( - //! SigHandler::Handler(signal_handler), - //! SaFlags::SA_RESTART, - //! SigSet::empty() - //! ); - //! unsafe { - //! sigaction(Signal::SIGALRM, &sa); - //! } - //! - //! let start = Instant::now(); - //! - //! // Set an alarm for 1 second from now. - //! alarm::set(1); - //! - //! // Pause the process until the alarm signal is received. - //! let mut sigset = SigSet::empty(); - //! sigset.add(Signal::SIGALRM); - //! sigset.wait(); - //! - //! assert!(start.elapsed() >= Duration::from_secs(1)); - //! ``` - //! - //! # References - //! - //! See also [alarm(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/alarm.html). - - /// Schedule an alarm signal. - /// - /// This will cause the system to generate a `SIGALRM` signal for the - /// process after the specified number of seconds have elapsed. - /// - /// Returns the leftover time of a previously set alarm if there was one. - pub fn set(secs: libc::c_uint) -> Option { - assert!(secs != 0, "passing 0 to `alarm::set` is not allowed, to cancel an alarm use `alarm::cancel`"); - alarm(secs) - } - - /// Cancel an previously set alarm signal. - /// - /// Returns the leftover time of a previously set alarm if there was one. - pub fn cancel() -> Option { - alarm(0) - } - - fn alarm(secs: libc::c_uint) -> Option { - match unsafe { libc::alarm(secs) } { - 0 => None, - secs => Some(secs), - } - } -} - -/// Suspend execution for an interval of time -/// -/// See also [sleep(2)](https://pubs.opengroup.org/onlinepubs/009695399/functions/sleep.html#tag_03_705_05) -// Per POSIX, does not fail -#[inline] -pub fn sleep(seconds: c_uint) -> c_uint { - unsafe { libc::sleep(seconds) } -} - -#[cfg(not(target_os = "redox"))] -pub mod acct { - use crate::{Result, NixPath}; - use crate::errno::Errno; - use std::ptr; - - /// Enable process accounting - /// - /// See also [acct(2)](https://linux.die.net/man/2/acct) - pub fn enable(filename: &P) -> Result<()> { - let res = filename.with_nix_path(|cstr| { - unsafe { libc::acct(cstr.as_ptr()) } - })?; - - Errno::result(res).map(drop) - } - - /// Disable process accounting - pub fn disable() -> Result<()> { - let res = unsafe { libc::acct(ptr::null()) }; - - Errno::result(res).map(drop) - } -} - -/// Creates a regular file which persists even after process termination -/// -/// * `template`: a path whose 6 rightmost characters must be X, e.g. `/tmp/tmpfile_XXXXXX` -/// * returns: tuple of file descriptor and filename -/// -/// Err is returned either if no temporary filename could be created or the template doesn't -/// end with XXXXXX -/// -/// See also [mkstemp(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkstemp.html) -/// -/// # Example -/// -/// ```rust -/// use nix::unistd; -/// -/// let _ = match unistd::mkstemp("/tmp/tempfile_XXXXXX") { -/// Ok((fd, path)) => { -/// unistd::unlink(path.as_path()).unwrap(); // flag file to be deleted at app termination -/// fd -/// } -/// Err(e) => panic!("mkstemp failed: {}", e) -/// }; -/// // do something with fd -/// ``` -#[inline] -pub fn mkstemp(template: &P) -> Result<(RawFd, PathBuf)> { - let mut path = template.with_nix_path(|path| {path.to_bytes_with_nul().to_owned()})?; - let p = path.as_mut_ptr() as *mut _; - let fd = unsafe { libc::mkstemp(p) }; - let last = path.pop(); // drop the trailing nul - debug_assert!(last == Some(b'\0')); - let pathname = OsString::from_vec(path); - Errno::result(fd)?; - Ok((fd, PathBuf::from(pathname))) -} - -/// Variable names for `pathconf` -/// -/// Nix uses the same naming convention for these variables as the -/// [getconf(1)](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html) utility. -/// That is, `PathconfVar` variables have the same name as the abstract -/// variables shown in the `pathconf(2)` man page. Usually, it's the same as -/// the C variable name without the leading `_PC_`. -/// -/// POSIX 1003.1-2008 standardizes all of these variables, but some OSes choose -/// not to implement variables that cannot change at runtime. -/// -/// # References -/// -/// - [pathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html) -/// - [limits.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html) -/// - [unistd.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html) -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -#[repr(i32)] -#[non_exhaustive] -pub enum PathconfVar { - #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux", - target_os = "netbsd", target_os = "openbsd", target_os = "redox"))] - /// Minimum number of bits needed to represent, as a signed integer value, - /// the maximum size of a regular file allowed in the specified directory. - FILESIZEBITS = libc::_PC_FILESIZEBITS, - /// Maximum number of links to a single file. - LINK_MAX = libc::_PC_LINK_MAX, - /// Maximum number of bytes in a terminal canonical input line. - MAX_CANON = libc::_PC_MAX_CANON, - /// Minimum number of bytes for which space is available in a terminal input - /// queue; therefore, the maximum number of bytes a conforming application - /// may require to be typed as input before reading them. - MAX_INPUT = libc::_PC_MAX_INPUT, - /// Maximum number of bytes in a filename (not including the terminating - /// null of a filename string). - NAME_MAX = libc::_PC_NAME_MAX, - /// Maximum number of bytes the implementation will store as a pathname in a - /// user-supplied buffer of unspecified size, including the terminating null - /// character. Minimum number the implementation will accept as the maximum - /// number of bytes in a pathname. - PATH_MAX = libc::_PC_PATH_MAX, - /// Maximum number of bytes that is guaranteed to be atomic when writing to - /// a pipe. - PIPE_BUF = libc::_PC_PIPE_BUF, - #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "illumos", - target_os = "linux", target_os = "netbsd", target_os = "openbsd", - target_os = "redox", target_os = "solaris"))] - /// Symbolic links can be created. - POSIX2_SYMLINKS = libc::_PC_2_SYMLINKS, - #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", - target_os = "linux", target_os = "openbsd", target_os = "redox"))] - /// Minimum number of bytes of storage actually allocated for any portion of - /// a file. - POSIX_ALLOC_SIZE_MIN = libc::_PC_ALLOC_SIZE_MIN, - #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", - target_os = "linux", target_os = "openbsd"))] - /// Recommended increment for file transfer sizes between the - /// `POSIX_REC_MIN_XFER_SIZE` and `POSIX_REC_MAX_XFER_SIZE` values. - POSIX_REC_INCR_XFER_SIZE = libc::_PC_REC_INCR_XFER_SIZE, - #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", - target_os = "linux", target_os = "openbsd", target_os = "redox"))] - /// Maximum recommended file transfer size. - POSIX_REC_MAX_XFER_SIZE = libc::_PC_REC_MAX_XFER_SIZE, - #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", - target_os = "linux", target_os = "openbsd", target_os = "redox"))] - /// Minimum recommended file transfer size. - POSIX_REC_MIN_XFER_SIZE = libc::_PC_REC_MIN_XFER_SIZE, - #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", - target_os = "linux", target_os = "openbsd", target_os = "redox"))] - /// Recommended file transfer buffer alignment. - POSIX_REC_XFER_ALIGN = libc::_PC_REC_XFER_ALIGN, - #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", - target_os = "illumos", target_os = "linux", target_os = "netbsd", - target_os = "openbsd", target_os = "redox", target_os = "solaris"))] - /// Maximum number of bytes in a symbolic link. - SYMLINK_MAX = libc::_PC_SYMLINK_MAX, - /// The use of `chown` and `fchown` is restricted to a process with - /// appropriate privileges, and to changing the group ID of a file only to - /// the effective group ID of the process or to one of its supplementary - /// group IDs. - _POSIX_CHOWN_RESTRICTED = libc::_PC_CHOWN_RESTRICTED, - /// Pathname components longer than {NAME_MAX} generate an error. - _POSIX_NO_TRUNC = libc::_PC_NO_TRUNC, - /// This symbol shall be defined to be the value of a character that shall - /// disable terminal special character handling. - _POSIX_VDISABLE = libc::_PC_VDISABLE, - #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", - target_os = "illumos", target_os = "linux", target_os = "openbsd", - target_os = "redox", target_os = "solaris"))] - /// Asynchronous input or output operations may be performed for the - /// associated file. - _POSIX_ASYNC_IO = libc::_PC_ASYNC_IO, - #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", - target_os = "illumos", target_os = "linux", target_os = "openbsd", - target_os = "redox", target_os = "solaris"))] - /// Prioritized input or output operations may be performed for the - /// associated file. - _POSIX_PRIO_IO = libc::_PC_PRIO_IO, - #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", - target_os = "illumos", target_os = "linux", target_os = "netbsd", - target_os = "openbsd", target_os = "redox", target_os = "solaris"))] - /// Synchronized input or output operations may be performed for the - /// associated file. - _POSIX_SYNC_IO = libc::_PC_SYNC_IO, - #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] - /// The resolution in nanoseconds for all file timestamps. - _POSIX_TIMESTAMP_RESOLUTION = libc::_PC_TIMESTAMP_RESOLUTION -} - -/// Like `pathconf`, but works with file descriptors instead of paths (see -/// [fpathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html)) -/// -/// # Parameters -/// -/// - `fd`: The file descriptor whose variable should be interrogated -/// - `var`: The pathconf variable to lookup -/// -/// # Returns -/// -/// - `Ok(Some(x))`: the variable's limit (for limit variables) or its -/// implementation level (for option variables). Implementation levels are -/// usually a decimal-coded date, such as 200112 for POSIX 2001.12 -/// - `Ok(None)`: the variable has no limit (for limit variables) or is -/// unsupported (for option variables) -/// - `Err(x)`: an error occurred -pub fn fpathconf(fd: RawFd, var: PathconfVar) -> Result> { - let raw = unsafe { - Errno::clear(); - libc::fpathconf(fd, var as c_int) - }; - if raw == -1 { - if errno::errno() == 0 { - Ok(None) - } else { - Err(Errno::last()) - } - } else { - Ok(Some(raw)) - } -} - -/// Get path-dependent configurable system variables (see -/// [pathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html)) -/// -/// Returns the value of a path-dependent configurable system variable. Most -/// supported variables also have associated compile-time constants, but POSIX -/// allows their values to change at runtime. There are generally two types of -/// `pathconf` variables: options and limits. See [pathconf(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html) for more details. -/// -/// # Parameters -/// -/// - `path`: Lookup the value of `var` for this file or directory -/// - `var`: The `pathconf` variable to lookup -/// -/// # Returns -/// -/// - `Ok(Some(x))`: the variable's limit (for limit variables) or its -/// implementation level (for option variables). Implementation levels are -/// usually a decimal-coded date, such as 200112 for POSIX 2001.12 -/// - `Ok(None)`: the variable has no limit (for limit variables) or is -/// unsupported (for option variables) -/// - `Err(x)`: an error occurred -pub fn pathconf(path: &P, var: PathconfVar) -> Result> { - let raw = path.with_nix_path(|cstr| { - unsafe { - Errno::clear(); - libc::pathconf(cstr.as_ptr(), var as c_int) - } - })?; - if raw == -1 { - if errno::errno() == 0 { - Ok(None) - } else { - Err(Errno::last()) - } - } else { - Ok(Some(raw)) - } -} - -/// Variable names for `sysconf` -/// -/// Nix uses the same naming convention for these variables as the -/// [getconf(1)](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html) utility. -/// That is, `SysconfVar` variables have the same name as the abstract variables -/// shown in the `sysconf(3)` man page. Usually, it's the same as the C -/// variable name without the leading `_SC_`. -/// -/// All of these symbols are standardized by POSIX 1003.1-2008, but haven't been -/// implemented by all platforms. -/// -/// # References -/// -/// - [sysconf(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html) -/// - [unistd.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html) -/// - [limits.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html) -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -#[repr(i32)] -#[non_exhaustive] -pub enum SysconfVar { - /// Maximum number of I/O operations in a single list I/O call supported by - /// the implementation. - #[cfg(not(target_os = "redox"))] - AIO_LISTIO_MAX = libc::_SC_AIO_LISTIO_MAX, - /// Maximum number of outstanding asynchronous I/O operations supported by - /// the implementation. - #[cfg(not(target_os = "redox"))] - AIO_MAX = libc::_SC_AIO_MAX, - #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd"))] - /// The maximum amount by which a process can decrease its asynchronous I/O - /// priority level from its own scheduling priority. - AIO_PRIO_DELTA_MAX = libc::_SC_AIO_PRIO_DELTA_MAX, - /// Maximum length of argument to the exec functions including environment data. - ARG_MAX = libc::_SC_ARG_MAX, - /// Maximum number of functions that may be registered with `atexit`. - #[cfg(not(target_os = "redox"))] - ATEXIT_MAX = libc::_SC_ATEXIT_MAX, - /// Maximum obase values allowed by the bc utility. - #[cfg(not(target_os = "redox"))] - BC_BASE_MAX = libc::_SC_BC_BASE_MAX, - /// Maximum number of elements permitted in an array by the bc utility. - #[cfg(not(target_os = "redox"))] - BC_DIM_MAX = libc::_SC_BC_DIM_MAX, - /// Maximum scale value allowed by the bc utility. - #[cfg(not(target_os = "redox"))] - BC_SCALE_MAX = libc::_SC_BC_SCALE_MAX, - /// Maximum length of a string constant accepted by the bc utility. - #[cfg(not(target_os = "redox"))] - BC_STRING_MAX = libc::_SC_BC_STRING_MAX, - /// Maximum number of simultaneous processes per real user ID. - CHILD_MAX = libc::_SC_CHILD_MAX, - // The number of clock ticks per second. - CLK_TCK = libc::_SC_CLK_TCK, - /// Maximum number of weights that can be assigned to an entry of the - /// LC_COLLATE order keyword in the locale definition file - #[cfg(not(target_os = "redox"))] - COLL_WEIGHTS_MAX = libc::_SC_COLL_WEIGHTS_MAX, - /// Maximum number of timer expiration overruns. - #[cfg(not(target_os = "redox"))] - DELAYTIMER_MAX = libc::_SC_DELAYTIMER_MAX, - /// Maximum number of expressions that can be nested within parentheses by - /// the expr utility. - #[cfg(not(target_os = "redox"))] - EXPR_NEST_MAX = libc::_SC_EXPR_NEST_MAX, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="netbsd", target_os="openbsd", target_os = "solaris"))] - /// Maximum length of a host name (not including the terminating null) as - /// returned from the `gethostname` function - HOST_NAME_MAX = libc::_SC_HOST_NAME_MAX, - /// Maximum number of iovec structures that one process has available for - /// use with `readv` or `writev`. - #[cfg(not(target_os = "redox"))] - IOV_MAX = libc::_SC_IOV_MAX, - /// Unless otherwise noted, the maximum length, in bytes, of a utility's - /// input line (either standard input or another file), when the utility is - /// described as processing text files. The length includes room for the - /// trailing . - #[cfg(not(target_os = "redox"))] - LINE_MAX = libc::_SC_LINE_MAX, - /// Maximum length of a login name. - LOGIN_NAME_MAX = libc::_SC_LOGIN_NAME_MAX, - /// Maximum number of simultaneous supplementary group IDs per process. - NGROUPS_MAX = libc::_SC_NGROUPS_MAX, - /// Initial size of `getgrgid_r` and `getgrnam_r` data buffers - #[cfg(not(target_os = "redox"))] - GETGR_R_SIZE_MAX = libc::_SC_GETGR_R_SIZE_MAX, - /// Initial size of `getpwuid_r` and `getpwnam_r` data buffers - #[cfg(not(target_os = "redox"))] - GETPW_R_SIZE_MAX = libc::_SC_GETPW_R_SIZE_MAX, - /// The maximum number of open message queue descriptors a process may hold. - #[cfg(not(target_os = "redox"))] - MQ_OPEN_MAX = libc::_SC_MQ_OPEN_MAX, - /// The maximum number of message priorities supported by the implementation. - #[cfg(not(target_os = "redox"))] - MQ_PRIO_MAX = libc::_SC_MQ_PRIO_MAX, - /// A value one greater than the maximum value that the system may assign to - /// a newly-created file descriptor. - OPEN_MAX = libc::_SC_OPEN_MAX, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="openbsd"))] - /// The implementation supports the Advisory Information option. - _POSIX_ADVISORY_INFO = libc::_SC_ADVISORY_INFO, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="netbsd", target_os="openbsd", target_os = "solaris"))] - /// The implementation supports barriers. - _POSIX_BARRIERS = libc::_SC_BARRIERS, - /// The implementation supports asynchronous input and output. - #[cfg(not(target_os = "redox"))] - _POSIX_ASYNCHRONOUS_IO = libc::_SC_ASYNCHRONOUS_IO, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="netbsd", target_os="openbsd", target_os = "solaris"))] - /// The implementation supports clock selection. - _POSIX_CLOCK_SELECTION = libc::_SC_CLOCK_SELECTION, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="netbsd", target_os="openbsd", target_os = "solaris"))] - /// The implementation supports the Process CPU-Time Clocks option. - _POSIX_CPUTIME = libc::_SC_CPUTIME, - /// The implementation supports the File Synchronization option. - #[cfg(not(target_os = "redox"))] - _POSIX_FSYNC = libc::_SC_FSYNC, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd", target_os = "solaris"))] - /// The implementation supports the IPv6 option. - _POSIX_IPV6 = libc::_SC_IPV6, - /// The implementation supports job control. - #[cfg(not(target_os = "redox"))] - _POSIX_JOB_CONTROL = libc::_SC_JOB_CONTROL, - /// The implementation supports memory mapped Files. - #[cfg(not(target_os = "redox"))] - _POSIX_MAPPED_FILES = libc::_SC_MAPPED_FILES, - /// The implementation supports the Process Memory Locking option. - #[cfg(not(target_os = "redox"))] - _POSIX_MEMLOCK = libc::_SC_MEMLOCK, - /// The implementation supports the Range Memory Locking option. - #[cfg(not(target_os = "redox"))] - _POSIX_MEMLOCK_RANGE = libc::_SC_MEMLOCK_RANGE, - /// The implementation supports memory protection. - #[cfg(not(target_os = "redox"))] - _POSIX_MEMORY_PROTECTION = libc::_SC_MEMORY_PROTECTION, - /// The implementation supports the Message Passing option. - #[cfg(not(target_os = "redox"))] - _POSIX_MESSAGE_PASSING = libc::_SC_MESSAGE_PASSING, - /// The implementation supports the Monotonic Clock option. - #[cfg(not(target_os = "redox"))] - _POSIX_MONOTONIC_CLOCK = libc::_SC_MONOTONIC_CLOCK, - #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", - target_os = "illumos", target_os = "ios", target_os="linux", - target_os = "macos", target_os="openbsd", target_os = "solaris"))] - /// The implementation supports the Prioritized Input and Output option. - _POSIX_PRIORITIZED_IO = libc::_SC_PRIORITIZED_IO, - /// The implementation supports the Process Scheduling option. - #[cfg(not(target_os = "redox"))] - _POSIX_PRIORITY_SCHEDULING = libc::_SC_PRIORITY_SCHEDULING, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd", target_os = "solaris"))] - /// The implementation supports the Raw Sockets option. - _POSIX_RAW_SOCKETS = libc::_SC_RAW_SOCKETS, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="netbsd", target_os="openbsd", target_os = "solaris"))] - /// The implementation supports read-write locks. - _POSIX_READER_WRITER_LOCKS = libc::_SC_READER_WRITER_LOCKS, - #[cfg(any(target_os = "android", target_os="dragonfly", target_os="freebsd", - target_os = "ios", target_os="linux", target_os = "macos", - target_os = "openbsd"))] - /// The implementation supports realtime signals. - _POSIX_REALTIME_SIGNALS = libc::_SC_REALTIME_SIGNALS, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "illumos", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="netbsd", target_os="openbsd", target_os = "solaris"))] - /// The implementation supports the Regular Expression Handling option. - _POSIX_REGEXP = libc::_SC_REGEXP, - /// Each process has a saved set-user-ID and a saved set-group-ID. - #[cfg(not(target_os = "redox"))] - _POSIX_SAVED_IDS = libc::_SC_SAVED_IDS, - /// The implementation supports semaphores. - #[cfg(not(target_os = "redox"))] - _POSIX_SEMAPHORES = libc::_SC_SEMAPHORES, - /// The implementation supports the Shared Memory Objects option. - #[cfg(not(target_os = "redox"))] - _POSIX_SHARED_MEMORY_OBJECTS = libc::_SC_SHARED_MEMORY_OBJECTS, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="netbsd", - target_os="openbsd"))] - /// The implementation supports the POSIX shell. - _POSIX_SHELL = libc::_SC_SHELL, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="netbsd", - target_os="openbsd"))] - /// The implementation supports the Spawn option. - _POSIX_SPAWN = libc::_SC_SPAWN, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="netbsd", - target_os="openbsd"))] - /// The implementation supports spin locks. - _POSIX_SPIN_LOCKS = libc::_SC_SPIN_LOCKS, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="openbsd"))] - /// The implementation supports the Process Sporadic Server option. - _POSIX_SPORADIC_SERVER = libc::_SC_SPORADIC_SERVER, - #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd"))] - _POSIX_SS_REPL_MAX = libc::_SC_SS_REPL_MAX, - /// The implementation supports the Synchronized Input and Output option. - #[cfg(not(target_os = "redox"))] - _POSIX_SYNCHRONIZED_IO = libc::_SC_SYNCHRONIZED_IO, - /// The implementation supports the Thread Stack Address Attribute option. - #[cfg(not(target_os = "redox"))] - _POSIX_THREAD_ATTR_STACKADDR = libc::_SC_THREAD_ATTR_STACKADDR, - /// The implementation supports the Thread Stack Size Attribute option. - #[cfg(not(target_os = "redox"))] - _POSIX_THREAD_ATTR_STACKSIZE = libc::_SC_THREAD_ATTR_STACKSIZE, - #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos", - target_os="netbsd", target_os="openbsd"))] - /// The implementation supports the Thread CPU-Time Clocks option. - _POSIX_THREAD_CPUTIME = libc::_SC_THREAD_CPUTIME, - /// The implementation supports the Non-Robust Mutex Priority Inheritance - /// option. - #[cfg(not(target_os = "redox"))] - _POSIX_THREAD_PRIO_INHERIT = libc::_SC_THREAD_PRIO_INHERIT, - /// The implementation supports the Non-Robust Mutex Priority Protection option. - #[cfg(not(target_os = "redox"))] - _POSIX_THREAD_PRIO_PROTECT = libc::_SC_THREAD_PRIO_PROTECT, - /// The implementation supports the Thread Execution Scheduling option. - #[cfg(not(target_os = "redox"))] - _POSIX_THREAD_PRIORITY_SCHEDULING = libc::_SC_THREAD_PRIORITY_SCHEDULING, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="netbsd", - target_os="openbsd"))] - /// The implementation supports the Thread Process-Shared Synchronization - /// option. - _POSIX_THREAD_PROCESS_SHARED = libc::_SC_THREAD_PROCESS_SHARED, - #[cfg(any(target_os="dragonfly", target_os="linux", target_os="openbsd"))] - /// The implementation supports the Robust Mutex Priority Inheritance option. - _POSIX_THREAD_ROBUST_PRIO_INHERIT = libc::_SC_THREAD_ROBUST_PRIO_INHERIT, - #[cfg(any(target_os="dragonfly", target_os="linux", target_os="openbsd"))] - /// The implementation supports the Robust Mutex Priority Protection option. - _POSIX_THREAD_ROBUST_PRIO_PROTECT = libc::_SC_THREAD_ROBUST_PRIO_PROTECT, - /// The implementation supports thread-safe functions. - #[cfg(not(target_os = "redox"))] - _POSIX_THREAD_SAFE_FUNCTIONS = libc::_SC_THREAD_SAFE_FUNCTIONS, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="openbsd"))] - /// The implementation supports the Thread Sporadic Server option. - _POSIX_THREAD_SPORADIC_SERVER = libc::_SC_THREAD_SPORADIC_SERVER, - /// The implementation supports threads. - #[cfg(not(target_os = "redox"))] - _POSIX_THREADS = libc::_SC_THREADS, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="openbsd"))] - /// The implementation supports timeouts. - _POSIX_TIMEOUTS = libc::_SC_TIMEOUTS, - /// The implementation supports timers. - #[cfg(not(target_os = "redox"))] - _POSIX_TIMERS = libc::_SC_TIMERS, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="openbsd"))] - /// The implementation supports the Trace option. - _POSIX_TRACE = libc::_SC_TRACE, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="openbsd"))] - /// The implementation supports the Trace Event Filter option. - _POSIX_TRACE_EVENT_FILTER = libc::_SC_TRACE_EVENT_FILTER, - #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd"))] - _POSIX_TRACE_EVENT_NAME_MAX = libc::_SC_TRACE_EVENT_NAME_MAX, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="openbsd"))] - /// The implementation supports the Trace Inherit option. - _POSIX_TRACE_INHERIT = libc::_SC_TRACE_INHERIT, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="openbsd"))] - /// The implementation supports the Trace Log option. - _POSIX_TRACE_LOG = libc::_SC_TRACE_LOG, - #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd"))] - _POSIX_TRACE_NAME_MAX = libc::_SC_TRACE_NAME_MAX, - #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd"))] - _POSIX_TRACE_SYS_MAX = libc::_SC_TRACE_SYS_MAX, - #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd"))] - _POSIX_TRACE_USER_EVENT_MAX = libc::_SC_TRACE_USER_EVENT_MAX, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="openbsd"))] - /// The implementation supports the Typed Memory Objects option. - _POSIX_TYPED_MEMORY_OBJECTS = libc::_SC_TYPED_MEMORY_OBJECTS, - /// Integer value indicating version of this standard (C-language binding) - /// to which the implementation conforms. For implementations conforming to - /// POSIX.1-2008, the value shall be 200809L. - _POSIX_VERSION = libc::_SC_VERSION, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="netbsd", - target_os="openbsd"))] - /// The implementation provides a C-language compilation environment with - /// 32-bit `int`, `long`, `pointer`, and `off_t` types. - _POSIX_V6_ILP32_OFF32 = libc::_SC_V6_ILP32_OFF32, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="netbsd", - target_os="openbsd"))] - /// The implementation provides a C-language compilation environment with - /// 32-bit `int`, `long`, and pointer types and an `off_t` type using at - /// least 64 bits. - _POSIX_V6_ILP32_OFFBIG = libc::_SC_V6_ILP32_OFFBIG, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="netbsd", - target_os="openbsd"))] - /// The implementation provides a C-language compilation environment with - /// 32-bit `int` and 64-bit `long`, `pointer`, and `off_t` types. - _POSIX_V6_LP64_OFF64 = libc::_SC_V6_LP64_OFF64, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="netbsd", - target_os="openbsd"))] - /// The implementation provides a C-language compilation environment with an - /// `int` type using at least 32 bits and `long`, pointer, and `off_t` types - /// using at least 64 bits. - _POSIX_V6_LPBIG_OFFBIG = libc::_SC_V6_LPBIG_OFFBIG, - /// The implementation supports the C-Language Binding option. - #[cfg(not(target_os = "redox"))] - _POSIX2_C_BIND = libc::_SC_2_C_BIND, - /// The implementation supports the C-Language Development Utilities option. - #[cfg(not(target_os = "redox"))] - _POSIX2_C_DEV = libc::_SC_2_C_DEV, - /// The implementation supports the Terminal Characteristics option. - #[cfg(not(target_os = "redox"))] - _POSIX2_CHAR_TERM = libc::_SC_2_CHAR_TERM, - /// The implementation supports the FORTRAN Development Utilities option. - #[cfg(not(target_os = "redox"))] - _POSIX2_FORT_DEV = libc::_SC_2_FORT_DEV, - /// The implementation supports the FORTRAN Runtime Utilities option. - #[cfg(not(target_os = "redox"))] - _POSIX2_FORT_RUN = libc::_SC_2_FORT_RUN, - /// The implementation supports the creation of locales by the localedef - /// utility. - #[cfg(not(target_os = "redox"))] - _POSIX2_LOCALEDEF = libc::_SC_2_LOCALEDEF, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="netbsd", - target_os="openbsd"))] - /// The implementation supports the Batch Environment Services and Utilities - /// option. - _POSIX2_PBS = libc::_SC_2_PBS, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="netbsd", - target_os="openbsd"))] - /// The implementation supports the Batch Accounting option. - _POSIX2_PBS_ACCOUNTING = libc::_SC_2_PBS_ACCOUNTING, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="netbsd", - target_os="openbsd"))] - /// The implementation supports the Batch Checkpoint/Restart option. - _POSIX2_PBS_CHECKPOINT = libc::_SC_2_PBS_CHECKPOINT, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="netbsd", - target_os="openbsd"))] - /// The implementation supports the Locate Batch Job Request option. - _POSIX2_PBS_LOCATE = libc::_SC_2_PBS_LOCATE, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="netbsd", - target_os="openbsd"))] - /// The implementation supports the Batch Job Message Request option. - _POSIX2_PBS_MESSAGE = libc::_SC_2_PBS_MESSAGE, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="netbsd", - target_os="openbsd"))] - /// The implementation supports the Track Batch Job Request option. - _POSIX2_PBS_TRACK = libc::_SC_2_PBS_TRACK, - /// The implementation supports the Software Development Utilities option. - #[cfg(not(target_os = "redox"))] - _POSIX2_SW_DEV = libc::_SC_2_SW_DEV, - /// The implementation supports the User Portability Utilities option. - #[cfg(not(target_os = "redox"))] - _POSIX2_UPE = libc::_SC_2_UPE, - /// Integer value indicating version of the Shell and Utilities volume of - /// POSIX.1 to which the implementation conforms. - #[cfg(not(target_os = "redox"))] - _POSIX2_VERSION = libc::_SC_2_VERSION, - /// The size of a system page in bytes. - /// - /// POSIX also defines an alias named `PAGESIZE`, but Rust does not allow two - /// enum constants to have the same value, so nix omits `PAGESIZE`. - PAGE_SIZE = libc::_SC_PAGE_SIZE, - #[cfg(not(target_os = "redox"))] - PTHREAD_DESTRUCTOR_ITERATIONS = libc::_SC_THREAD_DESTRUCTOR_ITERATIONS, - #[cfg(not(target_os = "redox"))] - PTHREAD_KEYS_MAX = libc::_SC_THREAD_KEYS_MAX, - #[cfg(not(target_os = "redox"))] - PTHREAD_STACK_MIN = libc::_SC_THREAD_STACK_MIN, - #[cfg(not(target_os = "redox"))] - PTHREAD_THREADS_MAX = libc::_SC_THREAD_THREADS_MAX, - RE_DUP_MAX = libc::_SC_RE_DUP_MAX, - #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd"))] - RTSIG_MAX = libc::_SC_RTSIG_MAX, - #[cfg(not(target_os = "redox"))] - SEM_NSEMS_MAX = libc::_SC_SEM_NSEMS_MAX, - #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd"))] - SEM_VALUE_MAX = libc::_SC_SEM_VALUE_MAX, - #[cfg(any(target_os = "android", target_os="dragonfly", target_os="freebsd", - target_os = "ios", target_os="linux", target_os = "macos", - target_os = "openbsd"))] - SIGQUEUE_MAX = libc::_SC_SIGQUEUE_MAX, - STREAM_MAX = libc::_SC_STREAM_MAX, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="netbsd", - target_os="openbsd"))] - SYMLOOP_MAX = libc::_SC_SYMLOOP_MAX, - #[cfg(not(target_os = "redox"))] - TIMER_MAX = libc::_SC_TIMER_MAX, - TTY_NAME_MAX = libc::_SC_TTY_NAME_MAX, - TZNAME_MAX = libc::_SC_TZNAME_MAX, - #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd"))] - /// The implementation supports the X/Open Encryption Option Group. - _XOPEN_CRYPT = libc::_SC_XOPEN_CRYPT, - #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd"))] - /// The implementation supports the Issue 4, Version 2 Enhanced - /// Internationalization Option Group. - _XOPEN_ENH_I18N = libc::_SC_XOPEN_ENH_I18N, - #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd"))] - _XOPEN_LEGACY = libc::_SC_XOPEN_LEGACY, - #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd"))] - /// The implementation supports the X/Open Realtime Option Group. - _XOPEN_REALTIME = libc::_SC_XOPEN_REALTIME, - #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd"))] - /// The implementation supports the X/Open Realtime Threads Option Group. - _XOPEN_REALTIME_THREADS = libc::_SC_XOPEN_REALTIME_THREADS, - /// The implementation supports the Issue 4, Version 2 Shared Memory Option - /// Group. - #[cfg(not(target_os = "redox"))] - _XOPEN_SHM = libc::_SC_XOPEN_SHM, - #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios", - target_os="linux", target_os = "macos", target_os="openbsd"))] - /// The implementation supports the XSI STREAMS Option Group. - _XOPEN_STREAMS = libc::_SC_XOPEN_STREAMS, - #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd"))] - /// The implementation supports the XSI option - _XOPEN_UNIX = libc::_SC_XOPEN_UNIX, - #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd", - target_os = "ios", target_os="linux", target_os = "macos", - target_os="openbsd"))] - /// Integer value indicating version of the X/Open Portability Guide to - /// which the implementation conforms. - _XOPEN_VERSION = libc::_SC_XOPEN_VERSION, -} - -/// Get configurable system variables (see -/// [sysconf(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html)) -/// -/// Returns the value of a configurable system variable. Most supported -/// variables also have associated compile-time constants, but POSIX -/// allows their values to change at runtime. There are generally two types of -/// sysconf variables: options and limits. See sysconf(3) for more details. -/// -/// # Returns -/// -/// - `Ok(Some(x))`: the variable's limit (for limit variables) or its -/// implementation level (for option variables). Implementation levels are -/// usually a decimal-coded date, such as 200112 for POSIX 2001.12 -/// - `Ok(None)`: the variable has no limit (for limit variables) or is -/// unsupported (for option variables) -/// - `Err(x)`: an error occurred -pub fn sysconf(var: SysconfVar) -> Result> { - let raw = unsafe { - Errno::clear(); - libc::sysconf(var as c_int) - }; - if raw == -1 { - if errno::errno() == 0 { - Ok(None) - } else { - Err(Errno::last()) - } - } else { - Ok(Some(raw)) - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -mod pivot_root { - use crate::{Result, NixPath}; - use crate::errno::Errno; - - pub fn pivot_root( - new_root: &P1, put_old: &P2) -> Result<()> { - let res = new_root.with_nix_path(|new_root| { - put_old.with_nix_path(|put_old| { - unsafe { - libc::syscall(libc::SYS_pivot_root, new_root.as_ptr(), put_old.as_ptr()) - } - }) - })??; - - Errno::result(res).map(drop) - } -} - -#[cfg(any(target_os = "android", target_os = "freebsd", - target_os = "linux", target_os = "openbsd"))] -mod setres { - use crate::Result; - use crate::errno::Errno; - use super::{Uid, Gid}; - - /// Sets the real, effective, and saved uid. - /// ([see setresuid(2)](https://man7.org/linux/man-pages/man2/setresuid.2.html)) - /// - /// * `ruid`: real user id - /// * `euid`: effective user id - /// * `suid`: saved user id - /// * returns: Ok or libc error code. - /// - /// Err is returned if the user doesn't have permission to set this UID. - #[inline] - pub fn setresuid(ruid: Uid, euid: Uid, suid: Uid) -> Result<()> { - let res = unsafe { libc::setresuid(ruid.into(), euid.into(), suid.into()) }; - - Errno::result(res).map(drop) - } - - /// Sets the real, effective, and saved gid. - /// ([see setresuid(2)](https://man7.org/linux/man-pages/man2/setresuid.2.html)) - /// - /// * `rgid`: real group id - /// * `egid`: effective group id - /// * `sgid`: saved group id - /// * returns: Ok or libc error code. - /// - /// Err is returned if the user doesn't have permission to set this GID. - #[inline] - pub fn setresgid(rgid: Gid, egid: Gid, sgid: Gid) -> Result<()> { - let res = unsafe { libc::setresgid(rgid.into(), egid.into(), sgid.into()) }; - - Errno::result(res).map(drop) - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -mod getres { - use crate::Result; - use crate::errno::Errno; - use super::{Uid, Gid}; - - /// Real, effective and saved user IDs. - #[derive(Debug, Copy, Clone, Eq, PartialEq)] - pub struct ResUid { - pub real: Uid, - pub effective: Uid, - pub saved: Uid - } - - /// Real, effective and saved group IDs. - #[derive(Debug, Copy, Clone, Eq, PartialEq)] - pub struct ResGid { - pub real: Gid, - pub effective: Gid, - pub saved: Gid - } - - /// Gets the real, effective, and saved user IDs. - /// - /// ([see getresuid(2)](http://man7.org/linux/man-pages/man2/getresuid.2.html)) - /// - /// #Returns - /// - /// - `Ok((Uid, Uid, Uid))`: tuple of real, effective and saved uids on success. - /// - `Err(x)`: libc error code on failure. - /// - #[inline] - pub fn getresuid() -> Result { - let mut ruid = libc::uid_t::max_value(); - let mut euid = libc::uid_t::max_value(); - let mut suid = libc::uid_t::max_value(); - let res = unsafe { libc::getresuid(&mut ruid, &mut euid, &mut suid) }; - - Errno::result(res).map(|_| ResUid{ real: Uid(ruid), effective: Uid(euid), saved: Uid(suid) }) - } - - /// Gets the real, effective, and saved group IDs. - /// - /// ([see getresgid(2)](http://man7.org/linux/man-pages/man2/getresgid.2.html)) - /// - /// #Returns - /// - /// - `Ok((Gid, Gid, Gid))`: tuple of real, effective and saved gids on success. - /// - `Err(x)`: libc error code on failure. - /// - #[inline] - pub fn getresgid() -> Result { - let mut rgid = libc::gid_t::max_value(); - let mut egid = libc::gid_t::max_value(); - let mut sgid = libc::gid_t::max_value(); - let res = unsafe { libc::getresgid(&mut rgid, &mut egid, &mut sgid) }; - - Errno::result(res).map(|_| ResGid { real: Gid(rgid), effective: Gid(egid), saved: Gid(sgid) } ) - } -} - -libc_bitflags!{ - /// Options for access() - pub struct AccessFlags : c_int { - /// Test for existence of file. - F_OK; - /// Test for read permission. - R_OK; - /// Test for write permission. - W_OK; - /// Test for execute (search) permission. - X_OK; - } -} - -/// Checks the file named by `path` for accessibility according to the flags given by `amode` -/// See [access(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/access.html) -pub fn access(path: &P, amode: AccessFlags) -> Result<()> { - let res = path.with_nix_path(|cstr| { - unsafe { - libc::access(cstr.as_ptr(), amode.bits) - } - })?; - Errno::result(res).map(drop) -} - -/// Representation of a User, based on `libc::passwd` -/// -/// The reason some fields in this struct are `String` and others are `CString` is because some -/// fields are based on the user's locale, which could be non-UTF8, while other fields are -/// guaranteed to conform to [`NAME_REGEX`](https://serverfault.com/a/73101/407341), which only -/// contains ASCII. -#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd -#[derive(Debug, Clone, PartialEq)] -pub struct User { - /// Username - pub name: String, - /// User password (probably encrypted) - pub passwd: CString, - /// User ID - pub uid: Uid, - /// Group ID - pub gid: Gid, - /// User information - #[cfg(not(all(target_os = "android", target_pointer_width = "32")))] - pub gecos: CString, - /// Home directory - pub dir: PathBuf, - /// Path to shell - pub shell: PathBuf, - /// Login class - #[cfg(not(any(target_os = "android", - target_os = "fuchsia", - target_os = "illumos", - target_os = "linux", - target_os = "solaris")))] - pub class: CString, - /// Last password change - #[cfg(not(any(target_os = "android", - target_os = "fuchsia", - target_os = "illumos", - target_os = "linux", - target_os = "solaris")))] - pub change: libc::time_t, - /// Expiration time of account - #[cfg(not(any(target_os = "android", - target_os = "fuchsia", - target_os = "illumos", - target_os = "linux", - target_os = "solaris")))] - pub expire: libc::time_t -} - -#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd -impl From<&libc::passwd> for User { - fn from(pw: &libc::passwd) -> User { - unsafe { - User { - name: CStr::from_ptr((*pw).pw_name).to_string_lossy().into_owned(), - passwd: CString::new(CStr::from_ptr((*pw).pw_passwd).to_bytes()).unwrap(), - #[cfg(not(all(target_os = "android", target_pointer_width = "32")))] - gecos: CString::new(CStr::from_ptr((*pw).pw_gecos).to_bytes()).unwrap(), - dir: PathBuf::from(OsStr::from_bytes(CStr::from_ptr((*pw).pw_dir).to_bytes())), - shell: PathBuf::from(OsStr::from_bytes(CStr::from_ptr((*pw).pw_shell).to_bytes())), - uid: Uid::from_raw((*pw).pw_uid), - gid: Gid::from_raw((*pw).pw_gid), - #[cfg(not(any(target_os = "android", - target_os = "fuchsia", - target_os = "illumos", - target_os = "linux", - target_os = "solaris")))] - class: CString::new(CStr::from_ptr((*pw).pw_class).to_bytes()).unwrap(), - #[cfg(not(any(target_os = "android", - target_os = "fuchsia", - target_os = "illumos", - target_os = "linux", - target_os = "solaris")))] - change: (*pw).pw_change, - #[cfg(not(any(target_os = "android", - target_os = "fuchsia", - target_os = "illumos", - target_os = "linux", - target_os = "solaris")))] - expire: (*pw).pw_expire - } - } - } -} - -#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd -impl From for libc::passwd { - fn from(u: User) -> Self { - let name = match CString::new(u.name) { - Ok(n) => n.into_raw(), - Err(_) => CString::new("").unwrap().into_raw(), - }; - let dir = match u.dir.into_os_string().into_string() { - Ok(s) => CString::new(s.as_str()).unwrap().into_raw(), - Err(_) => CString::new("").unwrap().into_raw(), - }; - let shell = match u.shell.into_os_string().into_string() { - Ok(s) => CString::new(s.as_str()).unwrap().into_raw(), - Err(_) => CString::new("").unwrap().into_raw(), - }; - Self { - pw_name: name, - pw_passwd: u.passwd.into_raw(), - #[cfg(not(all(target_os = "android", target_pointer_width = "32")))] - pw_gecos: u.gecos.into_raw(), - pw_dir: dir, - pw_shell: shell, - pw_uid: u.uid.0, - pw_gid: u.gid.0, - #[cfg(not(any(target_os = "android", - target_os = "fuchsia", - target_os = "illumos", - target_os = "linux", - target_os = "solaris")))] - pw_class: u.class.into_raw(), - #[cfg(not(any(target_os = "android", - target_os = "fuchsia", - target_os = "illumos", - target_os = "linux", - target_os = "solaris")))] - pw_change: u.change, - #[cfg(not(any(target_os = "android", - target_os = "fuchsia", - target_os = "illumos", - target_os = "linux", - target_os = "solaris")))] - pw_expire: u.expire, - #[cfg(target_os = "illumos")] - pw_age: CString::new("").unwrap().into_raw(), - #[cfg(target_os = "illumos")] - pw_comment: CString::new("").unwrap().into_raw(), - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - pw_fields: 0, - } - } -} - -#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd -impl User { - fn from_anything(f: F) -> Result> - where - F: Fn(*mut libc::passwd, - *mut libc::c_char, - libc::size_t, - *mut *mut libc::passwd) -> libc::c_int - { - let buflimit = 1048576; - let bufsize = match sysconf(SysconfVar::GETPW_R_SIZE_MAX) { - Ok(Some(n)) => n as usize, - Ok(None) | Err(_) => 16384, - }; - - let mut cbuf = Vec::with_capacity(bufsize); - let mut pwd = mem::MaybeUninit::::uninit(); - let mut res = ptr::null_mut(); - - loop { - let error = f(pwd.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res); - if error == 0 { - if res.is_null() { - return Ok(None); - } else { - let pwd = unsafe { pwd.assume_init() }; - return Ok(Some(User::from(&pwd))); - } - } else if Errno::last() == Errno::ERANGE { - // Trigger the internal buffer resizing logic. - reserve_double_buffer_size(&mut cbuf, buflimit)?; - } else { - return Err(Errno::last()); - } - } - } - - /// Get a user by UID. - /// - /// Internally, this function calls - /// [getpwuid_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html) - /// - /// # Examples - /// - /// ``` - /// use nix::unistd::{Uid, User}; - /// // Returns an Result>, thus the double unwrap. - /// let res = User::from_uid(Uid::from_raw(0)).unwrap().unwrap(); - /// assert!(res.name == "root"); - /// ``` - pub fn from_uid(uid: Uid) -> Result> { - User::from_anything(|pwd, cbuf, cap, res| { - unsafe { libc::getpwuid_r(uid.0, pwd, cbuf, cap, res) } - }) - } - - /// Get a user by name. - /// - /// Internally, this function calls - /// [getpwnam_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html) - /// - /// # Examples - /// - /// ``` - /// use nix::unistd::User; - /// // Returns an Result>, thus the double unwrap. - /// let res = User::from_name("root").unwrap().unwrap(); - /// assert!(res.name == "root"); - /// ``` - pub fn from_name(name: &str) -> Result> { - let name = CString::new(name).unwrap(); - User::from_anything(|pwd, cbuf, cap, res| { - unsafe { libc::getpwnam_r(name.as_ptr(), pwd, cbuf, cap, res) } - }) - } -} - -/// Representation of a Group, based on `libc::group` -#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd -#[derive(Debug, Clone, PartialEq)] -pub struct Group { - /// Group name - pub name: String, - /// Group password - pub passwd: CString, - /// Group ID - pub gid: Gid, - /// List of Group members - pub mem: Vec -} - -#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd -impl From<&libc::group> for Group { - fn from(gr: &libc::group) -> Group { - unsafe { - Group { - name: CStr::from_ptr((*gr).gr_name).to_string_lossy().into_owned(), - passwd: CString::new(CStr::from_ptr((*gr).gr_passwd).to_bytes()).unwrap(), - gid: Gid::from_raw((*gr).gr_gid), - mem: Group::members((*gr).gr_mem) - } - } - } -} - -#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd -impl Group { - unsafe fn members(mem: *mut *mut c_char) -> Vec { - let mut ret = Vec::new(); - - for i in 0.. { - let u = mem.offset(i); - if (*u).is_null() { - break; - } else { - let s = CStr::from_ptr(*u).to_string_lossy().into_owned(); - ret.push(s); - } - } - - ret - } - - fn from_anything(f: F) -> Result> - where - F: Fn(*mut libc::group, - *mut libc::c_char, - libc::size_t, - *mut *mut libc::group) -> libc::c_int - { - let buflimit = 1048576; - let bufsize = match sysconf(SysconfVar::GETGR_R_SIZE_MAX) { - Ok(Some(n)) => n as usize, - Ok(None) | Err(_) => 16384, - }; - - let mut cbuf = Vec::with_capacity(bufsize); - let mut grp = mem::MaybeUninit::::uninit(); - let mut res = ptr::null_mut(); - - loop { - let error = f(grp.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res); - if error == 0 { - if res.is_null() { - return Ok(None); - } else { - let grp = unsafe { grp.assume_init() }; - return Ok(Some(Group::from(&grp))); - } - } else if Errno::last() == Errno::ERANGE { - // Trigger the internal buffer resizing logic. - reserve_double_buffer_size(&mut cbuf, buflimit)?; - } else { - return Err(Errno::last()); - } - } - } - - /// Get a group by GID. - /// - /// Internally, this function calls - /// [getgrgid_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html) - /// - /// # Examples - /// - // Disable this test on all OS except Linux as root group may not exist. - #[cfg_attr(not(target_os = "linux"), doc = " ```no_run")] - #[cfg_attr(target_os = "linux", doc = " ```")] - /// use nix::unistd::{Gid, Group}; - /// // Returns an Result>, thus the double unwrap. - /// let res = Group::from_gid(Gid::from_raw(0)).unwrap().unwrap(); - /// assert!(res.name == "root"); - /// ``` - pub fn from_gid(gid: Gid) -> Result> { - Group::from_anything(|grp, cbuf, cap, res| { - unsafe { libc::getgrgid_r(gid.0, grp, cbuf, cap, res) } - }) - } - - /// Get a group by name. - /// - /// Internally, this function calls - /// [getgrnam_r(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html) - /// - /// # Examples - /// - // Disable this test on all OS except Linux as root group may not exist. - #[cfg_attr(not(target_os = "linux"), doc = " ```no_run")] - #[cfg_attr(target_os = "linux", doc = " ```")] - /// use nix::unistd::Group; - /// // Returns an Result>, thus the double unwrap. - /// let res = Group::from_name("root").unwrap().unwrap(); - /// assert!(res.name == "root"); - /// ``` - pub fn from_name(name: &str) -> Result> { - let name = CString::new(name).unwrap(); - Group::from_anything(|grp, cbuf, cap, res| { - unsafe { libc::getgrnam_r(name.as_ptr(), grp, cbuf, cap, res) } - }) - } -} - -/// Get the name of the terminal device that is open on file descriptor fd -/// (see [`ttyname(3)`](https://man7.org/linux/man-pages/man3/ttyname.3.html)). -#[cfg(not(target_os = "fuchsia"))] -pub fn ttyname(fd: RawFd) -> Result { - const PATH_MAX: usize = libc::PATH_MAX as usize; - let mut buf = vec![0_u8; PATH_MAX]; - let c_buf = buf.as_mut_ptr() as *mut libc::c_char; - - let ret = unsafe { libc::ttyname_r(fd, c_buf, buf.len()) }; - if ret != 0 { - return Err(Errno::from_i32(ret)); - } - - let nul = buf.iter().position(|c| *c == b'\0').unwrap(); - buf.truncate(nul); - Ok(OsString::from_vec(buf).into()) -} - -/// Get the effective user ID and group ID associated with a Unix domain socket. -/// -/// See also [getpeereid(3)](https://www.freebsd.org/cgi/man.cgi?query=getpeereid) -#[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "openbsd", - target_os = "netbsd", - target_os = "dragonfly", -))] -pub fn getpeereid(fd: RawFd) -> Result<(Uid, Gid)> { - let mut uid = 1; - let mut gid = 1; - - let ret = unsafe { libc::getpeereid(fd, &mut uid, &mut gid) }; - - Errno::result(ret).map(|_| (Uid(uid), Gid(gid))) -} diff --git a/vendor/nix-v0.23.1-patched/test/common/mod.rs b/vendor/nix-v0.23.1-patched/test/common/mod.rs deleted file mode 100644 index 84a0b4fa3..000000000 --- a/vendor/nix-v0.23.1-patched/test/common/mod.rs +++ /dev/null @@ -1,141 +0,0 @@ -use cfg_if::cfg_if; - -#[macro_export] macro_rules! skip { - ($($reason: expr),+) => { - use ::std::io::{self, Write}; - - let stderr = io::stderr(); - let mut handle = stderr.lock(); - writeln!(handle, $($reason),+).unwrap(); - return; - } -} - -cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { - #[macro_export] macro_rules! require_capability { - ($name:expr, $capname:ident) => { - use ::caps::{Capability, CapSet, has_cap}; - - if !has_cap(None, CapSet::Effective, Capability::$capname) - .unwrap() - { - skip!("{} requires capability {}. Skipping test.", $name, Capability::$capname); - } - } - } - } else if #[cfg(not(target_os = "redox"))] { - #[macro_export] macro_rules! require_capability { - ($name:expr, $capname:ident) => {} - } - } -} - -/// Skip the test if we don't have the ability to mount file systems. -#[cfg(target_os = "freebsd")] -#[macro_export] macro_rules! require_mount { - ($name:expr) => { - use ::sysctl::CtlValue; - use nix::unistd::Uid; - - if !Uid::current().is_root() && CtlValue::Int(0) == ::sysctl::value("vfs.usermount").unwrap() - { - skip!("{} requires the ability to mount file systems. Skipping test.", $name); - } - } -} - -#[cfg(any(target_os = "linux", target_os= "android"))] -#[macro_export] macro_rules! skip_if_cirrus { - ($reason:expr) => { - if std::env::var_os("CIRRUS_CI").is_some() { - skip!("{}", $reason); - } - } -} - -#[cfg(target_os = "freebsd")] -#[macro_export] macro_rules! skip_if_jailed { - ($name:expr) => { - use ::sysctl::CtlValue; - - if let CtlValue::Int(1) = ::sysctl::value("security.jail.jailed") - .unwrap() - { - skip!("{} cannot run in a jail. Skipping test.", $name); - } - } -} - -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -#[macro_export] macro_rules! skip_if_not_root { - ($name:expr) => { - use nix::unistd::Uid; - - if !Uid::current().is_root() { - skip!("{} requires root privileges. Skipping test.", $name); - } - }; -} - -cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { - #[macro_export] macro_rules! skip_if_seccomp { - ($name:expr) => { - if let Ok(s) = std::fs::read_to_string("/proc/self/status") { - for l in s.lines() { - let mut fields = l.split_whitespace(); - if fields.next() == Some("Seccomp:") && - fields.next() != Some("0") - { - skip!("{} cannot be run in Seccomp mode. Skipping test.", - stringify!($name)); - } - } - } - } - } - } else if #[cfg(not(target_os = "redox"))] { - #[macro_export] macro_rules! skip_if_seccomp { - ($name:expr) => {} - } - } -} - -cfg_if! { - if #[cfg(target_os = "linux")] { - #[macro_export] macro_rules! require_kernel_version { - ($name:expr, $version_requirement:expr) => { - use semver::{Version, VersionReq}; - - let version_requirement = VersionReq::parse($version_requirement) - .expect("Bad match_version provided"); - - let uname = nix::sys::utsname::uname(); - println!("{}", uname.sysname()); - println!("{}", uname.nodename()); - println!("{}", uname.release()); - println!("{}", uname.version()); - println!("{}", uname.machine()); - - // Fix stuff that the semver parser can't handle - let fixed_release = &uname.release().to_string() - // Fedora 33 reports version as 4.18.el8_2.x86_64 or - // 5.18.200-fc33.x86_64. Remove the underscore. - .replace("_", "-") - // Cirrus-CI reports version as 4.19.112+ . Remove the + - .replace("+", ""); - let mut version = Version::parse(fixed_release).unwrap(); - - //Keep only numeric parts - version.pre = semver::Prerelease::EMPTY; - version.build = semver::BuildMetadata::EMPTY; - - if !version_requirement.matches(&version) { - skip!("Skip {} because kernel version `{}` doesn't match the requirement `{}`", - stringify!($name), version, version_requirement); - } - } - } - } -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/mod.rs b/vendor/nix-v0.23.1-patched/test/sys/mod.rs deleted file mode 100644 index e73d9b1dc..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/mod.rs +++ /dev/null @@ -1,47 +0,0 @@ -mod test_signal; - -// NOTE: DragonFly lacks a kernel-level implementation of Posix AIO as of -// this writing. There is an user-level implementation, but whether aio -// works or not heavily depends on which pthread implementation is chosen -// by the user at link time. For this reason we do not want to run aio test -// cases on DragonFly. -#[cfg(any(target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd"))] -mod test_aio; -#[cfg(not(target_os = "redox"))] -mod test_mman; -#[cfg(target_os = "linux")] -mod test_signalfd; -#[cfg(not(target_os = "redox"))] -mod test_socket; -#[cfg(not(target_os = "redox"))] -mod test_sockopt; -#[cfg(not(target_os = "redox"))] -mod test_select; -#[cfg(any(target_os = "android", target_os = "linux"))] -mod test_sysinfo; -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -mod test_termios; -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -mod test_ioctl; -mod test_wait; -mod test_uio; - -#[cfg(target_os = "linux")] -mod test_epoll; -#[cfg(target_os = "linux")] -mod test_inotify; -mod test_pthread; -#[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] -mod test_ptrace; -#[cfg(any(target_os = "android", target_os = "linux"))] -mod test_timerfd; diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_aio.rs b/vendor/nix-v0.23.1-patched/test/sys/test_aio.rs deleted file mode 100644 index b4eb31295..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_aio.rs +++ /dev/null @@ -1,620 +0,0 @@ -use libc::{c_int, c_void}; -use nix::Result; -use nix::errno::*; -use nix::sys::aio::*; -use nix::sys::signal::{SaFlags, SigAction, sigaction, SigevNotify, SigHandler, Signal, SigSet}; -use nix::sys::time::{TimeSpec, TimeValLike}; -use std::io::{Write, Read, Seek, SeekFrom}; -use std::ops::Deref; -use std::os::unix::io::AsRawFd; -use std::pin::Pin; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::{thread, time}; -use tempfile::tempfile; - -// Helper that polls an AioCb for completion or error -fn poll_aio(aiocb: &mut Pin>) -> Result<()> { - loop { - let err = aiocb.error(); - if err != Err(Errno::EINPROGRESS) { return err; }; - thread::sleep(time::Duration::from_millis(10)); - } -} - -// Helper that polls a component of an LioCb for completion or error -#[cfg(not(any(target_os = "ios", target_os = "macos")))] -fn poll_lio(liocb: &mut LioCb, i: usize) -> Result<()> { - loop { - let err = liocb.error(i); - if err != Err(Errno::EINPROGRESS) { return err; }; - thread::sleep(time::Duration::from_millis(10)); - } -} - -#[test] -fn test_accessors() { - let mut rbuf = vec![0; 4]; - let aiocb = AioCb::from_mut_slice( 1001, - 2, //offset - &mut rbuf, - 42, //priority - SigevNotify::SigevSignal { - signal: Signal::SIGUSR2, - si_value: 99 - }, - LioOpcode::LIO_NOP); - assert_eq!(1001, aiocb.fd()); - assert_eq!(Some(LioOpcode::LIO_NOP), aiocb.lio_opcode()); - assert_eq!(4, aiocb.nbytes()); - assert_eq!(2, aiocb.offset()); - assert_eq!(42, aiocb.priority()); - let sev = aiocb.sigevent().sigevent(); - assert_eq!(Signal::SIGUSR2 as i32, sev.sigev_signo); - assert_eq!(99, sev.sigev_value.sival_ptr as i64); -} - -// Tests AioCb.cancel. We aren't trying to test the OS's implementation, only -// our bindings. So it's sufficient to check that AioCb.cancel returned any -// AioCancelStat value. -#[test] -#[cfg_attr(target_env = "musl", ignore)] -fn test_cancel() { - let wbuf: &[u8] = b"CDEF"; - - let f = tempfile().unwrap(); - let mut aiocb = AioCb::from_slice( f.as_raw_fd(), - 0, //offset - wbuf, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_NOP); - aiocb.write().unwrap(); - let err = aiocb.error(); - assert!(err == Ok(()) || err == Err(Errno::EINPROGRESS)); - - let cancelstat = aiocb.cancel(); - assert!(cancelstat.is_ok()); - - // Wait for aiocb to complete, but don't care whether it succeeded - let _ = poll_aio(&mut aiocb); - let _ = aiocb.aio_return(); -} - -// Tests using aio_cancel_all for all outstanding IOs. -#[test] -#[cfg_attr(target_env = "musl", ignore)] -fn test_aio_cancel_all() { - let wbuf: &[u8] = b"CDEF"; - - let f = tempfile().unwrap(); - let mut aiocb = AioCb::from_slice(f.as_raw_fd(), - 0, //offset - wbuf, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_NOP); - aiocb.write().unwrap(); - let err = aiocb.error(); - assert!(err == Ok(()) || err == Err(Errno::EINPROGRESS)); - - let cancelstat = aio_cancel_all(f.as_raw_fd()); - assert!(cancelstat.is_ok()); - - // Wait for aiocb to complete, but don't care whether it succeeded - let _ = poll_aio(&mut aiocb); - let _ = aiocb.aio_return(); -} - -#[test] -#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] -fn test_fsync() { - const INITIAL: &[u8] = b"abcdef123456"; - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - let mut aiocb = AioCb::from_fd( f.as_raw_fd(), - 0, //priority - SigevNotify::SigevNone); - let err = aiocb.fsync(AioFsyncMode::O_SYNC); - assert!(err.is_ok()); - poll_aio(&mut aiocb).unwrap(); - aiocb.aio_return().unwrap(); -} - -/// `AioCb::fsync` should not modify the `AioCb` object if `libc::aio_fsync` returns -/// an error -// Skip on Linux, because Linux's AIO implementation can't detect errors -// synchronously -#[test] -#[cfg(any(target_os = "freebsd", target_os = "macos"))] -fn test_fsync_error() { - use std::mem; - - const INITIAL: &[u8] = b"abcdef123456"; - // Create an invalid AioFsyncMode - let mode = unsafe { mem::transmute(666) }; - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - let mut aiocb = AioCb::from_fd( f.as_raw_fd(), - 0, //priority - SigevNotify::SigevNone); - let err = aiocb.fsync(mode); - assert!(err.is_err()); -} - -#[test] -// On Cirrus on Linux, this test fails due to a glibc bug. -// https://github.com/nix-rust/nix/issues/1099 -#[cfg_attr(target_os = "linux", ignore)] -// On Cirrus, aio_suspend is failing with EINVAL -// https://github.com/nix-rust/nix/issues/1361 -#[cfg_attr(target_os = "macos", ignore)] -fn test_aio_suspend() { - const INITIAL: &[u8] = b"abcdef123456"; - const WBUF: &[u8] = b"CDEFG"; - let timeout = TimeSpec::seconds(10); - let mut rbuf = vec![0; 4]; - let rlen = rbuf.len(); - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - - let mut wcb = AioCb::from_slice( f.as_raw_fd(), - 2, //offset - WBUF, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_WRITE); - - let mut rcb = AioCb::from_mut_slice( f.as_raw_fd(), - 8, //offset - &mut rbuf, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_READ); - wcb.write().unwrap(); - rcb.read().unwrap(); - loop { - { - let cbbuf = [wcb.as_ref(), rcb.as_ref()]; - let r = aio_suspend(&cbbuf[..], Some(timeout)); - match r { - Err(Errno::EINTR) => continue, - Err(e) => panic!("aio_suspend returned {:?}", e), - Ok(_) => () - }; - } - if rcb.error() != Err(Errno::EINPROGRESS) && - wcb.error() != Err(Errno::EINPROGRESS) { - break - } - } - - assert_eq!(wcb.aio_return().unwrap() as usize, WBUF.len()); - assert_eq!(rcb.aio_return().unwrap() as usize, rlen); -} - -// Test a simple aio operation with no completion notification. We must poll -// for completion -#[test] -#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] -fn test_read() { - const INITIAL: &[u8] = b"abcdef123456"; - let mut rbuf = vec![0; 4]; - const EXPECT: &[u8] = b"cdef"; - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - { - let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(), - 2, //offset - &mut rbuf, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_NOP); - aiocb.read().unwrap(); - - let err = poll_aio(&mut aiocb); - assert_eq!(err, Ok(())); - assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len()); - } - - assert_eq!(EXPECT, rbuf.deref().deref()); -} - -/// `AioCb::read` should not modify the `AioCb` object if `libc::aio_read` -/// returns an error -// Skip on Linux, because Linux's AIO implementation can't detect errors -// synchronously -#[test] -#[cfg(any(target_os = "freebsd", target_os = "macos"))] -fn test_read_error() { - const INITIAL: &[u8] = b"abcdef123456"; - let mut rbuf = vec![0; 4]; - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(), - -1, //an invalid offset - &mut rbuf, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_NOP); - assert!(aiocb.read().is_err()); -} - -// Tests from_mut_slice -#[test] -#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] -fn test_read_into_mut_slice() { - const INITIAL: &[u8] = b"abcdef123456"; - let mut rbuf = vec![0; 4]; - const EXPECT: &[u8] = b"cdef"; - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - { - let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(), - 2, //offset - &mut rbuf, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_NOP); - aiocb.read().unwrap(); - - let err = poll_aio(&mut aiocb); - assert_eq!(err, Ok(())); - assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len()); - } - - assert_eq!(rbuf, EXPECT); -} - -// Tests from_ptr -#[test] -#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] -fn test_read_into_pointer() { - const INITIAL: &[u8] = b"abcdef123456"; - let mut rbuf = vec![0; 4]; - const EXPECT: &[u8] = b"cdef"; - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - { - // Safety: ok because rbuf lives until after poll_aio - let mut aiocb = unsafe { - AioCb::from_mut_ptr( f.as_raw_fd(), - 2, //offset - rbuf.as_mut_ptr() as *mut c_void, - rbuf.len(), - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_NOP) - }; - aiocb.read().unwrap(); - - let err = poll_aio(&mut aiocb); - assert_eq!(err, Ok(())); - assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len()); - } - - assert_eq!(rbuf, EXPECT); -} - -// Test reading into an immutable buffer. It should fail -// FIXME: This test fails to panic on Linux/musl -#[test] -#[should_panic(expected = "Can't read into an immutable buffer")] -#[cfg_attr(target_env = "musl", ignore)] -fn test_read_immutable_buffer() { - let rbuf: &[u8] = b"CDEF"; - let f = tempfile().unwrap(); - let mut aiocb = AioCb::from_slice( f.as_raw_fd(), - 2, //offset - rbuf, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_NOP); - aiocb.read().unwrap(); -} - - -// Test a simple aio operation with no completion notification. We must poll -// for completion. Unlike test_aio_read, this test uses AioCb::from_slice -#[test] -#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] -fn test_write() { - const INITIAL: &[u8] = b"abcdef123456"; - let wbuf = "CDEF".to_string().into_bytes(); - let mut rbuf = Vec::new(); - const EXPECT: &[u8] = b"abCDEF123456"; - - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - let mut aiocb = AioCb::from_slice( f.as_raw_fd(), - 2, //offset - &wbuf, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_NOP); - aiocb.write().unwrap(); - - let err = poll_aio(&mut aiocb); - assert_eq!(err, Ok(())); - assert_eq!(aiocb.aio_return().unwrap() as usize, wbuf.len()); - - f.seek(SeekFrom::Start(0)).unwrap(); - let len = f.read_to_end(&mut rbuf).unwrap(); - assert_eq!(len, EXPECT.len()); - assert_eq!(rbuf, EXPECT); -} - -// Tests `AioCb::from_ptr` -#[test] -#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] -fn test_write_from_pointer() { - const INITIAL: &[u8] = b"abcdef123456"; - let wbuf = "CDEF".to_string().into_bytes(); - let mut rbuf = Vec::new(); - const EXPECT: &[u8] = b"abCDEF123456"; - - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - // Safety: ok because aiocb outlives poll_aio - let mut aiocb = unsafe { - AioCb::from_ptr( f.as_raw_fd(), - 2, //offset - wbuf.as_ptr() as *const c_void, - wbuf.len(), - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_NOP) - }; - aiocb.write().unwrap(); - - let err = poll_aio(&mut aiocb); - assert_eq!(err, Ok(())); - assert_eq!(aiocb.aio_return().unwrap() as usize, wbuf.len()); - - f.seek(SeekFrom::Start(0)).unwrap(); - let len = f.read_to_end(&mut rbuf).unwrap(); - assert_eq!(len, EXPECT.len()); - assert_eq!(rbuf, EXPECT); -} - -/// `AioCb::write` should not modify the `AioCb` object if `libc::aio_write` -/// returns an error -// Skip on Linux, because Linux's AIO implementation can't detect errors -// synchronously -#[test] -#[cfg(any(target_os = "freebsd", target_os = "macos"))] -fn test_write_error() { - let wbuf = "CDEF".to_string().into_bytes(); - let mut aiocb = AioCb::from_slice( 666, // An invalid file descriptor - 0, //offset - &wbuf, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_NOP); - assert!(aiocb.write().is_err()); -} - -lazy_static! { - pub static ref SIGNALED: AtomicBool = AtomicBool::new(false); -} - -extern fn sigfunc(_: c_int) { - SIGNALED.store(true, Ordering::Relaxed); -} - -// Test an aio operation with completion delivered by a signal -// FIXME: This test is ignored on mips because of failures in qemu in CI -#[test] -#[cfg_attr(any(all(target_env = "musl", target_arch = "x86_64"), target_arch = "mips", target_arch = "mips64"), ignore)] -fn test_write_sigev_signal() { - let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test"); - let sa = SigAction::new(SigHandler::Handler(sigfunc), - SaFlags::SA_RESETHAND, - SigSet::empty()); - SIGNALED.store(false, Ordering::Relaxed); - unsafe { sigaction(Signal::SIGUSR2, &sa) }.unwrap(); - - const INITIAL: &[u8] = b"abcdef123456"; - const WBUF: &[u8] = b"CDEF"; - let mut rbuf = Vec::new(); - const EXPECT: &[u8] = b"abCDEF123456"; - - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - let mut aiocb = AioCb::from_slice( f.as_raw_fd(), - 2, //offset - WBUF, - 0, //priority - SigevNotify::SigevSignal { - signal: Signal::SIGUSR2, - si_value: 0 //TODO: validate in sigfunc - }, - LioOpcode::LIO_NOP); - aiocb.write().unwrap(); - while !SIGNALED.load(Ordering::Relaxed) { - thread::sleep(time::Duration::from_millis(10)); - } - - assert_eq!(aiocb.aio_return().unwrap() as usize, WBUF.len()); - f.seek(SeekFrom::Start(0)).unwrap(); - let len = f.read_to_end(&mut rbuf).unwrap(); - assert_eq!(len, EXPECT.len()); - assert_eq!(rbuf, EXPECT); -} - -// Test LioCb::listio with LIO_WAIT, so all AIO ops should be complete by the -// time listio returns. -#[test] -#[cfg(not(any(target_os = "ios", target_os = "macos")))] -#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] -fn test_liocb_listio_wait() { - const INITIAL: &[u8] = b"abcdef123456"; - const WBUF: &[u8] = b"CDEF"; - let mut rbuf = vec![0; 4]; - let rlen = rbuf.len(); - let mut rbuf2 = Vec::new(); - const EXPECT: &[u8] = b"abCDEF123456"; - let mut f = tempfile().unwrap(); - - f.write_all(INITIAL).unwrap(); - - { - let mut liocb = LioCbBuilder::with_capacity(2) - .emplace_slice( - f.as_raw_fd(), - 2, //offset - WBUF, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_WRITE - ).emplace_mut_slice( - f.as_raw_fd(), - 8, //offset - &mut rbuf, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_READ - ).finish(); - let err = liocb.listio(LioMode::LIO_WAIT, SigevNotify::SigevNone); - err.expect("lio_listio"); - - assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len()); - assert_eq!(liocb.aio_return(1).unwrap() as usize, rlen); - } - assert_eq!(rbuf.deref().deref(), b"3456"); - - f.seek(SeekFrom::Start(0)).unwrap(); - let len = f.read_to_end(&mut rbuf2).unwrap(); - assert_eq!(len, EXPECT.len()); - assert_eq!(rbuf2, EXPECT); -} - -// Test LioCb::listio with LIO_NOWAIT and no SigEvent, so we must use some other -// mechanism to check for the individual AioCb's completion. -#[test] -#[cfg(not(any(target_os = "ios", target_os = "macos")))] -#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] -fn test_liocb_listio_nowait() { - const INITIAL: &[u8] = b"abcdef123456"; - const WBUF: &[u8] = b"CDEF"; - let mut rbuf = vec![0; 4]; - let rlen = rbuf.len(); - let mut rbuf2 = Vec::new(); - const EXPECT: &[u8] = b"abCDEF123456"; - let mut f = tempfile().unwrap(); - - f.write_all(INITIAL).unwrap(); - - { - let mut liocb = LioCbBuilder::with_capacity(2) - .emplace_slice( - f.as_raw_fd(), - 2, //offset - WBUF, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_WRITE - ).emplace_mut_slice( - f.as_raw_fd(), - 8, //offset - &mut rbuf, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_READ - ).finish(); - let err = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone); - err.expect("lio_listio"); - - poll_lio(&mut liocb, 0).unwrap(); - poll_lio(&mut liocb, 1).unwrap(); - assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len()); - assert_eq!(liocb.aio_return(1).unwrap() as usize, rlen); - } - assert_eq!(rbuf.deref().deref(), b"3456"); - - f.seek(SeekFrom::Start(0)).unwrap(); - let len = f.read_to_end(&mut rbuf2).unwrap(); - assert_eq!(len, EXPECT.len()); - assert_eq!(rbuf2, EXPECT); -} - -// Test LioCb::listio with LIO_NOWAIT and a SigEvent to indicate when all -// AioCb's are complete. -// FIXME: This test is ignored on mips/mips64 because of failures in qemu in CI. -#[test] -#[cfg(not(any(target_os = "ios", target_os = "macos")))] -#[cfg_attr(any(target_arch = "mips", target_arch = "mips64", target_env = "musl"), ignore)] -fn test_liocb_listio_signal() { - let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test"); - const INITIAL: &[u8] = b"abcdef123456"; - const WBUF: &[u8] = b"CDEF"; - let mut rbuf = vec![0; 4]; - let rlen = rbuf.len(); - let mut rbuf2 = Vec::new(); - const EXPECT: &[u8] = b"abCDEF123456"; - let mut f = tempfile().unwrap(); - let sa = SigAction::new(SigHandler::Handler(sigfunc), - SaFlags::SA_RESETHAND, - SigSet::empty()); - let sigev_notify = SigevNotify::SigevSignal { signal: Signal::SIGUSR2, - si_value: 0 }; - - f.write_all(INITIAL).unwrap(); - - { - let mut liocb = LioCbBuilder::with_capacity(2) - .emplace_slice( - f.as_raw_fd(), - 2, //offset - WBUF, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_WRITE - ).emplace_mut_slice( - f.as_raw_fd(), - 8, //offset - &mut rbuf, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_READ - ).finish(); - SIGNALED.store(false, Ordering::Relaxed); - unsafe { sigaction(Signal::SIGUSR2, &sa) }.unwrap(); - let err = liocb.listio(LioMode::LIO_NOWAIT, sigev_notify); - err.expect("lio_listio"); - while !SIGNALED.load(Ordering::Relaxed) { - thread::sleep(time::Duration::from_millis(10)); - } - - assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len()); - assert_eq!(liocb.aio_return(1).unwrap() as usize, rlen); - } - assert_eq!(rbuf.deref().deref(), b"3456"); - - f.seek(SeekFrom::Start(0)).unwrap(); - let len = f.read_to_end(&mut rbuf2).unwrap(); - assert_eq!(len, EXPECT.len()); - assert_eq!(rbuf2, EXPECT); -} - -// Try to use LioCb::listio to read into an immutable buffer. It should fail -// FIXME: This test fails to panic on Linux/musl -#[test] -#[cfg(not(any(target_os = "ios", target_os = "macos")))] -#[should_panic(expected = "Can't read into an immutable buffer")] -#[cfg_attr(target_env = "musl", ignore)] -fn test_liocb_listio_read_immutable() { - let rbuf: &[u8] = b"abcd"; - let f = tempfile().unwrap(); - - - let mut liocb = LioCbBuilder::with_capacity(1) - .emplace_slice( - f.as_raw_fd(), - 2, //offset - rbuf, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_READ - ).finish(); - let _ = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone); -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_aio_drop.rs b/vendor/nix-v0.23.1-patched/test/sys/test_aio_drop.rs deleted file mode 100644 index 71a2183bc..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_aio_drop.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Test dropping an AioCb that hasn't yet finished. -// This must happen in its own process, because on OSX this test seems to hose -// the AIO subsystem and causes subsequent tests to fail -#[test] -#[should_panic(expected = "Dropped an in-progress AioCb")] -#[cfg(all(not(target_env = "musl"), - any(target_os = "linux", - target_os = "ios", - target_os = "macos", - target_os = "freebsd", - target_os = "netbsd")))] -fn test_drop() { - use nix::sys::aio::*; - use nix::sys::signal::*; - use std::os::unix::io::AsRawFd; - use tempfile::tempfile; - - const WBUF: &[u8] = b"CDEF"; - - let f = tempfile().unwrap(); - f.set_len(6).unwrap(); - let mut aiocb = AioCb::from_slice( f.as_raw_fd(), - 2, //offset - WBUF, - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_NOP); - aiocb.write().unwrap(); -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_epoll.rs b/vendor/nix-v0.23.1-patched/test/sys/test_epoll.rs deleted file mode 100644 index 8d44cd08f..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_epoll.rs +++ /dev/null @@ -1,23 +0,0 @@ -use nix::sys::epoll::{EpollCreateFlags, EpollFlags, EpollOp, EpollEvent}; -use nix::sys::epoll::{epoll_create1, epoll_ctl}; -use nix::errno::Errno; - -#[test] -pub fn test_epoll_errno() { - let efd = epoll_create1(EpollCreateFlags::empty()).unwrap(); - let result = epoll_ctl(efd, EpollOp::EpollCtlDel, 1, None); - assert!(result.is_err()); - assert_eq!(result.unwrap_err(), Errno::ENOENT); - - let result = epoll_ctl(efd, EpollOp::EpollCtlAdd, 1, None); - assert!(result.is_err()); - assert_eq!(result.unwrap_err(), Errno::EINVAL); -} - -#[test] -pub fn test_epoll_ctl() { - let efd = epoll_create1(EpollCreateFlags::empty()).unwrap(); - let mut event = EpollEvent::new(EpollFlags::EPOLLIN | EpollFlags::EPOLLERR, 1); - epoll_ctl(efd, EpollOp::EpollCtlAdd, 1, &mut event).unwrap(); - epoll_ctl(efd, EpollOp::EpollCtlDel, 1, None).unwrap(); -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_inotify.rs b/vendor/nix-v0.23.1-patched/test/sys/test_inotify.rs deleted file mode 100644 index 137816a35..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_inotify.rs +++ /dev/null @@ -1,63 +0,0 @@ -use nix::sys::inotify::{AddWatchFlags,InitFlags,Inotify}; -use nix::errno::Errno; -use std::ffi::OsString; -use std::fs::{rename, File}; - -#[test] -pub fn test_inotify() { - let instance = Inotify::init(InitFlags::IN_NONBLOCK) - .unwrap(); - let tempdir = tempfile::tempdir().unwrap(); - - instance.add_watch(tempdir.path(), AddWatchFlags::IN_ALL_EVENTS).unwrap(); - - let events = instance.read_events(); - assert_eq!(events.unwrap_err(), Errno::EAGAIN); - - File::create(tempdir.path().join("test")).unwrap(); - - let events = instance.read_events().unwrap(); - assert_eq!(events[0].name, Some(OsString::from("test"))); -} - -#[test] -pub fn test_inotify_multi_events() { - let instance = Inotify::init(InitFlags::IN_NONBLOCK) - .unwrap(); - let tempdir = tempfile::tempdir().unwrap(); - - instance.add_watch(tempdir.path(), AddWatchFlags::IN_ALL_EVENTS).unwrap(); - - let events = instance.read_events(); - assert_eq!(events.unwrap_err(), Errno::EAGAIN); - - File::create(tempdir.path().join("test")).unwrap(); - rename(tempdir.path().join("test"), tempdir.path().join("test2")).unwrap(); - - // Now there should be 5 events in queue: - // - IN_CREATE on test - // - IN_OPEN on test - // - IN_CLOSE_WRITE on test - // - IN_MOVED_FROM on test with a cookie - // - IN_MOVED_TO on test2 with the same cookie - - let events = instance.read_events().unwrap(); - assert_eq!(events.len(), 5); - - assert_eq!(events[0].mask, AddWatchFlags::IN_CREATE); - assert_eq!(events[0].name, Some(OsString::from("test"))); - - assert_eq!(events[1].mask, AddWatchFlags::IN_OPEN); - assert_eq!(events[1].name, Some(OsString::from("test"))); - - assert_eq!(events[2].mask, AddWatchFlags::IN_CLOSE_WRITE); - assert_eq!(events[2].name, Some(OsString::from("test"))); - - assert_eq!(events[3].mask, AddWatchFlags::IN_MOVED_FROM); - assert_eq!(events[3].name, Some(OsString::from("test"))); - - assert_eq!(events[4].mask, AddWatchFlags::IN_MOVED_TO); - assert_eq!(events[4].name, Some(OsString::from("test2"))); - - assert_eq!(events[3].cookie, events[4].cookie); -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_ioctl.rs b/vendor/nix-v0.23.1-patched/test/sys/test_ioctl.rs deleted file mode 100644 index 236d24268..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_ioctl.rs +++ /dev/null @@ -1,337 +0,0 @@ -#![allow(dead_code)] - -// Simple tests to ensure macro generated fns compile -ioctl_none_bad!(do_bad, 0x1234); -ioctl_read_bad!(do_bad_read, 0x1234, u16); -ioctl_write_int_bad!(do_bad_write_int, 0x1234); -ioctl_write_ptr_bad!(do_bad_write_ptr, 0x1234, u8); -ioctl_readwrite_bad!(do_bad_readwrite, 0x1234, u32); -ioctl_none!(do_none, 0, 0); -ioctl_read!(read_test, 0, 0, u32); -ioctl_write_int!(write_ptr_int, 0, 0); -ioctl_write_ptr!(write_ptr_u8, 0, 0, u8); -ioctl_write_ptr!(write_ptr_u32, 0, 0, u32); -ioctl_write_ptr!(write_ptr_u64, 0, 0, u64); -ioctl_readwrite!(readwrite_test, 0, 0, u64); -ioctl_read_buf!(readbuf_test, 0, 0, u32); -const SPI_IOC_MAGIC: u8 = b'k'; -const SPI_IOC_MESSAGE: u8 = 0; -ioctl_write_buf!(writebuf_test_consts, SPI_IOC_MAGIC, SPI_IOC_MESSAGE, u8); -ioctl_write_buf!(writebuf_test_u8, 0, 0, u8); -ioctl_write_buf!(writebuf_test_u32, 0, 0, u32); -ioctl_write_buf!(writebuf_test_u64, 0, 0, u64); -ioctl_readwrite_buf!(readwritebuf_test, 0, 0, u32); - -// See C code for source of values for op calculations (does NOT work for mips/powerpc): -// https://gist.github.com/posborne/83ea6880770a1aef332e -// -// TODO: Need a way to compute these constants at test time. Using precomputed -// values is fragile and needs to be maintained. - -#[cfg(any(target_os = "linux", target_os = "android"))] -mod linux { - #[test] - fn test_op_none() { - if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){ - assert_eq!(request_code_none!(b'q', 10) as u32, 0x2000_710A); - assert_eq!(request_code_none!(b'a', 255) as u32, 0x2000_61FF); - } else { - assert_eq!(request_code_none!(b'q', 10) as u32, 0x0000_710A); - assert_eq!(request_code_none!(b'a', 255) as u32, 0x0000_61FF); - } - } - - #[test] - fn test_op_write() { - if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){ - assert_eq!(request_code_write!(b'z', 10, 1) as u32, 0x8001_7A0A); - assert_eq!(request_code_write!(b'z', 10, 512) as u32, 0x8200_7A0A); - } else { - assert_eq!(request_code_write!(b'z', 10, 1) as u32, 0x4001_7A0A); - assert_eq!(request_code_write!(b'z', 10, 512) as u32, 0x4200_7A0A); - } - } - - #[cfg(target_pointer_width = "64")] - #[test] - fn test_op_write_64() { - if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){ - assert_eq!(request_code_write!(b'z', 10, 1u64 << 32) as u32, - 0x8000_7A0A); - } else { - assert_eq!(request_code_write!(b'z', 10, 1u64 << 32) as u32, - 0x4000_7A0A); - } - - } - - #[test] - fn test_op_read() { - if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){ - assert_eq!(request_code_read!(b'z', 10, 1) as u32, 0x4001_7A0A); - assert_eq!(request_code_read!(b'z', 10, 512) as u32, 0x4200_7A0A); - } else { - assert_eq!(request_code_read!(b'z', 10, 1) as u32, 0x8001_7A0A); - assert_eq!(request_code_read!(b'z', 10, 512) as u32, 0x8200_7A0A); - } - } - - #[cfg(target_pointer_width = "64")] - #[test] - fn test_op_read_64() { - if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){ - assert_eq!(request_code_read!(b'z', 10, 1u64 << 32) as u32, - 0x4000_7A0A); - } else { - assert_eq!(request_code_read!(b'z', 10, 1u64 << 32) as u32, - 0x8000_7A0A); - } - } - - #[test] - fn test_op_read_write() { - assert_eq!(request_code_readwrite!(b'z', 10, 1) as u32, 0xC001_7A0A); - assert_eq!(request_code_readwrite!(b'z', 10, 512) as u32, 0xC200_7A0A); - } - - #[cfg(target_pointer_width = "64")] - #[test] - fn test_op_read_write_64() { - assert_eq!(request_code_readwrite!(b'z', 10, 1u64 << 32) as u32, - 0xC000_7A0A); - } -} - -#[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd"))] -mod bsd { - #[test] - fn test_op_none() { - assert_eq!(request_code_none!(b'q', 10), 0x2000_710A); - assert_eq!(request_code_none!(b'a', 255), 0x2000_61FF); - } - - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - #[test] - fn test_op_write_int() { - assert_eq!(request_code_write_int!(b'v', 4), 0x2004_7604); - assert_eq!(request_code_write_int!(b'p', 2), 0x2004_7002); - } - - #[test] - fn test_op_write() { - assert_eq!(request_code_write!(b'z', 10, 1), 0x8001_7A0A); - assert_eq!(request_code_write!(b'z', 10, 512), 0x8200_7A0A); - } - - #[cfg(target_pointer_width = "64")] - #[test] - fn test_op_write_64() { - assert_eq!(request_code_write!(b'z', 10, 1u64 << 32), 0x8000_7A0A); - } - - #[test] - fn test_op_read() { - assert_eq!(request_code_read!(b'z', 10, 1), 0x4001_7A0A); - assert_eq!(request_code_read!(b'z', 10, 512), 0x4200_7A0A); - } - - #[cfg(target_pointer_width = "64")] - #[test] - fn test_op_read_64() { - assert_eq!(request_code_read!(b'z', 10, 1u64 << 32), 0x4000_7A0A); - } - - #[test] - fn test_op_read_write() { - assert_eq!(request_code_readwrite!(b'z', 10, 1), 0xC001_7A0A); - assert_eq!(request_code_readwrite!(b'z', 10, 512), 0xC200_7A0A); - } - - #[cfg(target_pointer_width = "64")] - #[test] - fn test_op_read_write_64() { - assert_eq!(request_code_readwrite!(b'z', 10, 1u64 << 32), 0xC000_7A0A); - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -mod linux_ioctls { - use std::mem; - use std::os::unix::io::AsRawFd; - - use tempfile::tempfile; - use libc::{TCGETS, TCSBRK, TCSETS, TIOCNXCL, termios}; - - use nix::errno::Errno; - - ioctl_none_bad!(tiocnxcl, TIOCNXCL); - #[test] - fn test_ioctl_none_bad() { - let file = tempfile().unwrap(); - let res = unsafe { tiocnxcl(file.as_raw_fd()) }; - assert_eq!(res, Err(Errno::ENOTTY)); - } - - ioctl_read_bad!(tcgets, TCGETS, termios); - #[test] - fn test_ioctl_read_bad() { - let file = tempfile().unwrap(); - let mut termios = unsafe { mem::zeroed() }; - let res = unsafe { tcgets(file.as_raw_fd(), &mut termios) }; - assert_eq!(res, Err(Errno::ENOTTY)); - } - - ioctl_write_int_bad!(tcsbrk, TCSBRK); - #[test] - fn test_ioctl_write_int_bad() { - let file = tempfile().unwrap(); - let res = unsafe { tcsbrk(file.as_raw_fd(), 0) }; - assert_eq!(res, Err(Errno::ENOTTY)); - } - - ioctl_write_ptr_bad!(tcsets, TCSETS, termios); - #[test] - fn test_ioctl_write_ptr_bad() { - let file = tempfile().unwrap(); - let termios: termios = unsafe { mem::zeroed() }; - let res = unsafe { tcsets(file.as_raw_fd(), &termios) }; - assert_eq!(res, Err(Errno::ENOTTY)); - } - - // FIXME: Find a suitable example for `ioctl_readwrite_bad` - - // From linux/videodev2.h - ioctl_none!(log_status, b'V', 70); - #[test] - fn test_ioctl_none() { - let file = tempfile().unwrap(); - let res = unsafe { log_status(file.as_raw_fd()) }; - assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS)); - } - - #[repr(C)] - pub struct v4l2_audio { - index: u32, - name: [u8; 32], - capability: u32, - mode: u32, - reserved: [u32; 2], - } - - // From linux/videodev2.h - ioctl_write_ptr!(s_audio, b'V', 34, v4l2_audio); - #[test] - fn test_ioctl_write_ptr() { - let file = tempfile().unwrap(); - let data: v4l2_audio = unsafe { mem::zeroed() }; - let res = unsafe { s_audio(file.as_raw_fd(), &data) }; - assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS)); - } - - // From linux/net/bluetooth/hci_sock.h - const HCI_IOC_MAGIC: u8 = b'H'; - const HCI_IOC_HCIDEVUP: u8 = 201; - ioctl_write_int!(hcidevup, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP); - #[test] - fn test_ioctl_write_int() { - let file = tempfile().unwrap(); - let res = unsafe { hcidevup(file.as_raw_fd(), 0) }; - assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS)); - } - - // From linux/videodev2.h - ioctl_read!(g_audio, b'V', 33, v4l2_audio); - #[test] - fn test_ioctl_read() { - let file = tempfile().unwrap(); - let mut data: v4l2_audio = unsafe { mem::zeroed() }; - let res = unsafe { g_audio(file.as_raw_fd(), &mut data) }; - assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS)); - } - - // From linux/videodev2.h - ioctl_readwrite!(enum_audio, b'V', 65, v4l2_audio); - #[test] - fn test_ioctl_readwrite() { - let file = tempfile().unwrap(); - let mut data: v4l2_audio = unsafe { mem::zeroed() }; - let res = unsafe { enum_audio(file.as_raw_fd(), &mut data) }; - assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS)); - } - - // FIXME: Find a suitable example for `ioctl_read_buf`. - - #[repr(C)] - pub struct spi_ioc_transfer { - tx_buf: u64, - rx_buf: u64, - len: u32, - speed_hz: u32, - delay_usecs: u16, - bits_per_word: u8, - cs_change: u8, - tx_nbits: u8, - rx_nbits: u8, - pad: u16, - } - - // From linux/spi/spidev.h - ioctl_write_buf!(spi_ioc_message, super::SPI_IOC_MAGIC, super::SPI_IOC_MESSAGE, spi_ioc_transfer); - #[test] - fn test_ioctl_write_buf() { - let file = tempfile().unwrap(); - let data: [spi_ioc_transfer; 4] = unsafe { mem::zeroed() }; - let res = unsafe { spi_ioc_message(file.as_raw_fd(), &data[..]) }; - assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS)); - } - - // FIXME: Find a suitable example for `ioctl_readwrite_buf`. -} - -#[cfg(target_os = "freebsd")] -mod freebsd_ioctls { - use std::mem; - use std::os::unix::io::AsRawFd; - - use tempfile::tempfile; - use libc::termios; - - use nix::errno::Errno; - - // From sys/sys/ttycom.h - const TTY_IOC_MAGIC: u8 = b't'; - const TTY_IOC_TYPE_NXCL: u8 = 14; - const TTY_IOC_TYPE_GETA: u8 = 19; - const TTY_IOC_TYPE_SETA: u8 = 20; - - ioctl_none!(tiocnxcl, TTY_IOC_MAGIC, TTY_IOC_TYPE_NXCL); - #[test] - fn test_ioctl_none() { - let file = tempfile().unwrap(); - let res = unsafe { tiocnxcl(file.as_raw_fd()) }; - assert_eq!(res, Err(Errno::ENOTTY)); - } - - ioctl_read!(tiocgeta, TTY_IOC_MAGIC, TTY_IOC_TYPE_GETA, termios); - #[test] - fn test_ioctl_read() { - let file = tempfile().unwrap(); - let mut termios = unsafe { mem::zeroed() }; - let res = unsafe { tiocgeta(file.as_raw_fd(), &mut termios) }; - assert_eq!(res, Err(Errno::ENOTTY)); - } - - ioctl_write_ptr!(tiocseta, TTY_IOC_MAGIC, TTY_IOC_TYPE_SETA, termios); - #[test] - fn test_ioctl_write_ptr() { - let file = tempfile().unwrap(); - let termios: termios = unsafe { mem::zeroed() }; - let res = unsafe { tiocseta(file.as_raw_fd(), &termios) }; - assert_eq!(res, Err(Errno::ENOTTY)); - } -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_lio_listio_resubmit.rs b/vendor/nix-v0.23.1-patched/test/sys/test_lio_listio_resubmit.rs deleted file mode 100644 index c9077891c..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_lio_listio_resubmit.rs +++ /dev/null @@ -1,106 +0,0 @@ -// vim: tw=80 - -// Annoyingly, Cargo is unable to conditionally build an entire test binary. So -// we must disable the test here rather than in Cargo.toml -#![cfg(target_os = "freebsd")] - -use nix::errno::*; -use nix::libc::off_t; -use nix::sys::aio::*; -use nix::sys::signal::SigevNotify; -use nix::unistd::{SysconfVar, sysconf}; -use std::os::unix::io::AsRawFd; -use std::{thread, time}; -use sysctl::CtlValue; -use tempfile::tempfile; - -const BYTES_PER_OP: usize = 512; - -/// Attempt to collect final status for all of `liocb`'s operations, freeing -/// system resources -fn finish_liocb(liocb: &mut LioCb) { - for j in 0..liocb.len() { - loop { - let e = liocb.error(j); - match e { - Ok(()) => break, - Err(Errno::EINPROGRESS) => - thread::sleep(time::Duration::from_millis(10)), - Err(x) => panic!("aio_error({:?})", x) - } - } - assert_eq!(liocb.aio_return(j).unwrap(), BYTES_PER_OP as isize); - } -} - -// Deliberately exceed system resource limits, causing lio_listio to return EIO. -// This test must run in its own process since it deliberately uses all AIO -// resources. ATM it is only enabled on FreeBSD, because I don't know how to -// check system AIO limits on other operating systems. -#[test] -fn test_lio_listio_resubmit() { - let mut resubmit_count = 0; - - // Lookup system resource limits - let alm = sysconf(SysconfVar::AIO_LISTIO_MAX) - .expect("sysconf").unwrap() as usize; - let maqpp = if let CtlValue::Int(x) = sysctl::value( - "vfs.aio.max_aio_queue_per_proc").unwrap(){ - x as usize - } else { - panic!("unknown sysctl"); - }; - - // Find lio_listio sizes that satisfy the AIO_LISTIO_MAX constraint and also - // result in a final lio_listio call that can only partially be queued - let target_ops = maqpp + alm / 2; - let num_listios = (target_ops + alm - 3) / (alm - 2); - let ops_per_listio = (target_ops + num_listios - 1) / num_listios; - assert!((num_listios - 1) * ops_per_listio < maqpp, - "the last lio_listio won't make any progress; fix the algorithm"); - println!("Using {:?} LioCbs of {:?} operations apiece", num_listios, - ops_per_listio); - - let f = tempfile().unwrap(); - let buffer_set = (0..num_listios).map(|_| { - (0..ops_per_listio).map(|_| { - vec![0u8; BYTES_PER_OP] - }).collect::>() - }).collect::>(); - - let mut liocbs = (0..num_listios).map(|i| { - let mut builder = LioCbBuilder::with_capacity(ops_per_listio); - for j in 0..ops_per_listio { - let offset = (BYTES_PER_OP * (i * ops_per_listio + j)) as off_t; - builder = builder.emplace_slice(f.as_raw_fd(), - offset, - &buffer_set[i][j][..], - 0, //priority - SigevNotify::SigevNone, - LioOpcode::LIO_WRITE); - } - let mut liocb = builder.finish(); - let mut err = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone); - while err == Err(Errno::EIO) || - err == Err(Errno::EAGAIN) || - err == Err(Errno::EINTR) { - // - thread::sleep(time::Duration::from_millis(10)); - resubmit_count += 1; - err = liocb.listio_resubmit(LioMode::LIO_NOWAIT, - SigevNotify::SigevNone); - } - liocb - }).collect::>(); - - // Ensure that every AioCb completed - for liocb in liocbs.iter_mut() { - finish_liocb(liocb); - } - - if resubmit_count > 0 { - println!("Resubmitted {:?} times, test passed", resubmit_count); - } else { - println!("Never resubmitted. Test ambiguous"); - } -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_mman.rs b/vendor/nix-v0.23.1-patched/test/sys/test_mman.rs deleted file mode 100644 index a7ceedcbd..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_mman.rs +++ /dev/null @@ -1,92 +0,0 @@ -use nix::sys::mman::{mmap, MapFlags, ProtFlags}; - -#[test] -fn test_mmap_anonymous() { - unsafe { - let ptr = mmap(std::ptr::null_mut(), 1, - ProtFlags::PROT_READ | ProtFlags::PROT_WRITE, - MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS, -1, 0) - .unwrap() as *mut u8; - assert_eq !(*ptr, 0x00u8); - *ptr = 0xffu8; - assert_eq !(*ptr, 0xffu8); - } -} - -#[test] -#[cfg(any(target_os = "linux", target_os = "netbsd"))] -fn test_mremap_grow() { - use nix::sys::mman::{mremap, MRemapFlags}; - use nix::libc::{c_void, size_t}; - - const ONE_K : size_t = 1024; - let slice : &mut[u8] = unsafe { - let mem = mmap(std::ptr::null_mut(), ONE_K, - ProtFlags::PROT_READ | ProtFlags::PROT_WRITE, - MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE, -1, 0) - .unwrap(); - std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K) - }; - assert_eq !(slice[ONE_K - 1], 0x00); - slice[ONE_K - 1] = 0xFF; - assert_eq !(slice[ONE_K - 1], 0xFF); - - let slice : &mut[u8] = unsafe { - #[cfg(target_os = "linux")] - let mem = mremap(slice.as_mut_ptr() as * mut c_void, ONE_K, 10 * ONE_K, - MRemapFlags::MREMAP_MAYMOVE, None) - .unwrap(); - #[cfg(target_os = "netbsd")] - let mem = mremap(slice.as_mut_ptr() as * mut c_void, ONE_K, 10 * ONE_K, - MRemapFlags::MAP_REMAPDUP, None) - .unwrap(); - std::slice::from_raw_parts_mut(mem as * mut u8, 10 * ONE_K) - }; - - // The first KB should still have the old data in it. - assert_eq !(slice[ONE_K - 1], 0xFF); - - // The additional range should be zero-init'd and accessible. - assert_eq !(slice[10 * ONE_K - 1], 0x00); - slice[10 * ONE_K - 1] = 0xFF; - assert_eq !(slice[10 * ONE_K - 1], 0xFF); -} - -#[test] -#[cfg(any(target_os = "linux", target_os = "netbsd"))] -// Segfaults for unknown reasons under QEMU for 32-bit targets -#[cfg_attr(all(target_pointer_width = "32", qemu), ignore)] -fn test_mremap_shrink() { - use nix::sys::mman::{mremap, MRemapFlags}; - use nix::libc::{c_void, size_t}; - - const ONE_K : size_t = 1024; - let slice : &mut[u8] = unsafe { - let mem = mmap(std::ptr::null_mut(), 10 * ONE_K, - ProtFlags::PROT_READ | ProtFlags::PROT_WRITE, - MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE, -1, 0) - .unwrap(); - std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K) - }; - assert_eq !(slice[ONE_K - 1], 0x00); - slice[ONE_K - 1] = 0xFF; - assert_eq !(slice[ONE_K - 1], 0xFF); - - let slice : &mut[u8] = unsafe { - #[cfg(target_os = "linux")] - let mem = mremap(slice.as_mut_ptr() as * mut c_void, 10 * ONE_K, ONE_K, - MRemapFlags::empty(), None) - .unwrap(); - // Since we didn't supply MREMAP_MAYMOVE, the address should be the - // same. - #[cfg(target_os = "netbsd")] - let mem = mremap(slice.as_mut_ptr() as * mut c_void, 10 * ONE_K, ONE_K, - MRemapFlags::MAP_FIXED, None) - .unwrap(); - assert_eq !(mem, slice.as_mut_ptr() as * mut c_void); - std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K) - }; - - // The first KB should still be accessible and have the old data in it. - assert_eq !(slice[ONE_K - 1], 0xFF); -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_pthread.rs b/vendor/nix-v0.23.1-patched/test/sys/test_pthread.rs deleted file mode 100644 index fa9b510e8..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_pthread.rs +++ /dev/null @@ -1,22 +0,0 @@ -use nix::sys::pthread::*; - -#[cfg(any(target_env = "musl", target_os = "redox"))] -#[test] -fn test_pthread_self() { - let tid = pthread_self(); - assert!(tid != ::std::ptr::null_mut()); -} - -#[cfg(not(any(target_env = "musl", target_os = "redox")))] -#[test] -fn test_pthread_self() { - let tid = pthread_self(); - assert!(tid != 0); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_pthread_kill_none() { - pthread_kill(pthread_self(), None) - .expect("Should be able to send signal to my thread."); -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_ptrace.rs b/vendor/nix-v0.23.1-patched/test/sys/test_ptrace.rs deleted file mode 100644 index 1c72e7c2e..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_ptrace.rs +++ /dev/null @@ -1,219 +0,0 @@ -use nix::errno::Errno; -use nix::unistd::getpid; -use nix::sys::ptrace; -#[cfg(any(target_os = "android", target_os = "linux"))] -use nix::sys::ptrace::Options; - -#[cfg(any(target_os = "android", target_os = "linux"))] -use std::mem; - -use crate::*; - -#[test] -fn test_ptrace() { - // Just make sure ptrace can be called at all, for now. - // FIXME: qemu-user doesn't implement ptrace on all arches, so permit ENOSYS - require_capability!("test_ptrace", CAP_SYS_PTRACE); - let err = ptrace::attach(getpid()).unwrap_err(); - assert!(err == Errno::EPERM || err == Errno::EINVAL || - err == Errno::ENOSYS); -} - -// Just make sure ptrace_setoptions can be called at all, for now. -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptrace_setoptions() { - require_capability!("test_ptrace_setoptions", CAP_SYS_PTRACE); - let err = ptrace::setoptions(getpid(), Options::PTRACE_O_TRACESYSGOOD).unwrap_err(); - assert!(err != Errno::EOPNOTSUPP); -} - -// Just make sure ptrace_getevent can be called at all, for now. -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptrace_getevent() { - require_capability!("test_ptrace_getevent", CAP_SYS_PTRACE); - let err = ptrace::getevent(getpid()).unwrap_err(); - assert!(err != Errno::EOPNOTSUPP); -} - -// Just make sure ptrace_getsiginfo can be called at all, for now. -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptrace_getsiginfo() { - require_capability!("test_ptrace_getsiginfo", CAP_SYS_PTRACE); - if let Err(Errno::EOPNOTSUPP) = ptrace::getsiginfo(getpid()) { - panic!("ptrace_getsiginfo returns Errno::EOPNOTSUPP!"); - } -} - -// Just make sure ptrace_setsiginfo can be called at all, for now. -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptrace_setsiginfo() { - require_capability!("test_ptrace_setsiginfo", CAP_SYS_PTRACE); - let siginfo = unsafe { mem::zeroed() }; - if let Err(Errno::EOPNOTSUPP) = ptrace::setsiginfo(getpid(), &siginfo) { - panic!("ptrace_setsiginfo returns Errno::EOPNOTSUPP!"); - } -} - - -#[test] -fn test_ptrace_cont() { - use nix::sys::ptrace; - use nix::sys::signal::{raise, Signal}; - use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus}; - use nix::unistd::fork; - use nix::unistd::ForkResult::*; - - require_capability!("test_ptrace_cont", CAP_SYS_PTRACE); - - let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test"); - - // FIXME: qemu-user doesn't implement ptrace on all architectures - // and retunrs ENOSYS in this case. - // We (ab)use this behavior to detect the affected platforms - // and skip the test then. - // On valid platforms the ptrace call should return Errno::EPERM, this - // is already tested by `test_ptrace`. - let err = ptrace::attach(getpid()).unwrap_err(); - if err == Errno::ENOSYS { - return; - } - - match unsafe{fork()}.expect("Error: Fork Failed") { - Child => { - ptrace::traceme().unwrap(); - // As recommended by ptrace(2), raise SIGTRAP to pause the child - // until the parent is ready to continue - loop { - raise(Signal::SIGTRAP).unwrap(); - } - - }, - Parent { child } => { - assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTRAP))); - ptrace::cont(child, None).unwrap(); - assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTRAP))); - ptrace::cont(child, Some(Signal::SIGKILL)).unwrap(); - match waitpid(child, None) { - Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => { - // FIXME It's been observed on some systems (apple) the - // tracee may not be killed but remain as a zombie process - // affecting other wait based tests. Add an extra kill just - // to make sure there are no zombies. - let _ = waitpid(child, Some(WaitPidFlag::WNOHANG)); - while ptrace::cont(child, Some(Signal::SIGKILL)).is_ok() { - let _ = waitpid(child, Some(WaitPidFlag::WNOHANG)); - } - } - _ => panic!("The process should have been killed"), - } - }, - } -} - -#[cfg(target_os = "linux")] -#[test] -fn test_ptrace_interrupt() { - use nix::sys::ptrace; - use nix::sys::signal::Signal; - use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus}; - use nix::unistd::fork; - use nix::unistd::ForkResult::*; - use std::thread::sleep; - use std::time::Duration; - - require_capability!("test_ptrace_interrupt", CAP_SYS_PTRACE); - - let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test"); - - match unsafe{fork()}.expect("Error: Fork Failed") { - Child => { - loop { - sleep(Duration::from_millis(1000)); - } - - }, - Parent { child } => { - ptrace::seize(child, ptrace::Options::PTRACE_O_TRACESYSGOOD).unwrap(); - ptrace::interrupt(child).unwrap(); - assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceEvent(child, Signal::SIGTRAP, 128))); - ptrace::syscall(child, None).unwrap(); - assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child))); - ptrace::detach(child, Some(Signal::SIGKILL)).unwrap(); - match waitpid(child, None) { - Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => { - let _ = waitpid(child, Some(WaitPidFlag::WNOHANG)); - while ptrace::cont(child, Some(Signal::SIGKILL)).is_ok() { - let _ = waitpid(child, Some(WaitPidFlag::WNOHANG)); - } - } - _ => panic!("The process should have been killed"), - } - }, - } -} - -// ptrace::{setoptions, getregs} are only available in these platforms -#[cfg(all(target_os = "linux", - any(target_arch = "x86_64", - target_arch = "x86"), - target_env = "gnu"))] -#[test] -fn test_ptrace_syscall() { - use nix::sys::signal::kill; - use nix::sys::ptrace; - use nix::sys::signal::Signal; - use nix::sys::wait::{waitpid, WaitStatus}; - use nix::unistd::fork; - use nix::unistd::getpid; - use nix::unistd::ForkResult::*; - - require_capability!("test_ptrace_syscall", CAP_SYS_PTRACE); - - let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test"); - - match unsafe{fork()}.expect("Error: Fork Failed") { - Child => { - ptrace::traceme().unwrap(); - // first sigstop until parent is ready to continue - let pid = getpid(); - kill(pid, Signal::SIGSTOP).unwrap(); - kill(pid, Signal::SIGTERM).unwrap(); - unsafe { ::libc::_exit(0); } - }, - - Parent { child } => { - assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGSTOP))); - - // set this option to recognize syscall-stops - ptrace::setoptions(child, ptrace::Options::PTRACE_O_TRACESYSGOOD).unwrap(); - - #[cfg(target_arch = "x86_64")] - let get_syscall_id = || ptrace::getregs(child).unwrap().orig_rax as libc::c_long; - - #[cfg(target_arch = "x86")] - let get_syscall_id = || ptrace::getregs(child).unwrap().orig_eax as libc::c_long; - - // kill entry - ptrace::syscall(child, None).unwrap(); - assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child))); - assert_eq!(get_syscall_id(), ::libc::SYS_kill); - - // kill exit - ptrace::syscall(child, None).unwrap(); - assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child))); - assert_eq!(get_syscall_id(), ::libc::SYS_kill); - - // receive signal - ptrace::syscall(child, None).unwrap(); - assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTERM))); - - // inject signal - ptrace::syscall(child, Signal::SIGTERM).unwrap(); - assert_eq!(waitpid(child, None), Ok(WaitStatus::Signaled(child, Signal::SIGTERM, false))); - }, - } -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_select.rs b/vendor/nix-v0.23.1-patched/test/sys/test_select.rs deleted file mode 100644 index db0794561..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_select.rs +++ /dev/null @@ -1,82 +0,0 @@ -use nix::sys::select::*; -use nix::unistd::{pipe, write}; -use nix::sys::signal::SigSet; -use nix::sys::time::{TimeSpec, TimeValLike}; - -#[test] -pub fn test_pselect() { - let _mtx = crate::SIGNAL_MTX - .lock() - .expect("Mutex got poisoned by another test"); - - let (r1, w1) = pipe().unwrap(); - write(w1, b"hi!").unwrap(); - let (r2, _w2) = pipe().unwrap(); - - let mut fd_set = FdSet::new(); - fd_set.insert(r1); - fd_set.insert(r2); - - let timeout = TimeSpec::seconds(10); - let sigmask = SigSet::empty(); - assert_eq!( - 1, - pselect(None, &mut fd_set, None, None, &timeout, &sigmask).unwrap() - ); - assert!(fd_set.contains(r1)); - assert!(!fd_set.contains(r2)); -} - -#[test] -pub fn test_pselect_nfds2() { - let (r1, w1) = pipe().unwrap(); - write(w1, b"hi!").unwrap(); - let (r2, _w2) = pipe().unwrap(); - - let mut fd_set = FdSet::new(); - fd_set.insert(r1); - fd_set.insert(r2); - - let timeout = TimeSpec::seconds(10); - assert_eq!( - 1, - pselect( - ::std::cmp::max(r1, r2) + 1, - &mut fd_set, - None, - None, - &timeout, - None - ).unwrap() - ); - assert!(fd_set.contains(r1)); - assert!(!fd_set.contains(r2)); -} - -macro_rules! generate_fdset_bad_fd_tests { - ($fd:expr, $($method:ident),* $(,)?) => { - $( - #[test] - #[should_panic] - fn $method() { - FdSet::new().$method($fd); - } - )* - } -} - -mod test_fdset_negative_fd { - use super::*; - generate_fdset_bad_fd_tests!(-1, insert, remove, contains); -} - -mod test_fdset_too_large_fd { - use super::*; - use std::convert::TryInto; - generate_fdset_bad_fd_tests!( - FD_SETSIZE.try_into().unwrap(), - insert, - remove, - contains, - ); -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_signal.rs b/vendor/nix-v0.23.1-patched/test/sys/test_signal.rs deleted file mode 100644 index 1b89af573..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_signal.rs +++ /dev/null @@ -1,121 +0,0 @@ -#[cfg(not(target_os = "redox"))] -use nix::errno::Errno; -use nix::sys::signal::*; -use nix::unistd::*; -use std::convert::TryFrom; -use std::sync::atomic::{AtomicBool, Ordering}; - -#[test] -fn test_kill_none() { - kill(getpid(), None).expect("Should be able to send signal to myself."); -} - -#[test] -#[cfg(not(target_os = "fuchsia"))] -fn test_killpg_none() { - killpg(getpgrp(), None) - .expect("Should be able to send signal to my process group."); -} - -#[test] -fn test_old_sigaction_flags() { - let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test"); - - extern "C" fn handler(_: ::libc::c_int) {} - let act = SigAction::new( - SigHandler::Handler(handler), - SaFlags::empty(), - SigSet::empty(), - ); - let oact = unsafe { sigaction(SIGINT, &act) }.unwrap(); - let _flags = oact.flags(); - let oact = unsafe { sigaction(SIGINT, &act) }.unwrap(); - let _flags = oact.flags(); -} - -#[test] -fn test_sigprocmask_noop() { - sigprocmask(SigmaskHow::SIG_BLOCK, None, None) - .expect("this should be an effective noop"); -} - -#[test] -fn test_sigprocmask() { - let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test"); - - // This needs to be a signal that rust doesn't use in the test harness. - const SIGNAL: Signal = Signal::SIGCHLD; - - let mut old_signal_set = SigSet::empty(); - sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set)) - .expect("expect to be able to retrieve old signals"); - - // Make sure the old set doesn't contain the signal, otherwise the following - // test don't make sense. - assert!(!old_signal_set.contains(SIGNAL), - "the {:?} signal is already blocked, please change to a \ - different one", SIGNAL); - - // Now block the signal. - let mut signal_set = SigSet::empty(); - signal_set.add(SIGNAL); - sigprocmask(SigmaskHow::SIG_BLOCK, Some(&signal_set), None) - .expect("expect to be able to block signals"); - - // And test it again, to make sure the change was effective. - old_signal_set.clear(); - sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set)) - .expect("expect to be able to retrieve old signals"); - assert!(old_signal_set.contains(SIGNAL), - "expected the {:?} to be blocked", SIGNAL); - - // Reset the signal. - sigprocmask(SigmaskHow::SIG_UNBLOCK, Some(&signal_set), None) - .expect("expect to be able to block signals"); -} - -lazy_static! { - static ref SIGNALED: AtomicBool = AtomicBool::new(false); -} - -extern fn test_sigaction_handler(signal: libc::c_int) { - let signal = Signal::try_from(signal).unwrap(); - SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed); -} - -#[cfg(not(target_os = "redox"))] -extern fn test_sigaction_action(_: libc::c_int, _: *mut libc::siginfo_t, _: *mut libc::c_void) {} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_signal_sigaction() { - let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test"); - - let action_handler = SigHandler::SigAction(test_sigaction_action); - assert_eq!(unsafe { signal(Signal::SIGINT, action_handler) }.unwrap_err(), Errno::ENOTSUP); -} - -#[test] -fn test_signal() { - let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test"); - - unsafe { signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap(); - raise(Signal::SIGINT).unwrap(); - assert_eq!(unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), SigHandler::SigIgn); - - let handler = SigHandler::Handler(test_sigaction_handler); - assert_eq!(unsafe { signal(Signal::SIGINT, handler) }.unwrap(), SigHandler::SigDfl); - raise(Signal::SIGINT).unwrap(); - assert!(SIGNALED.load(Ordering::Relaxed)); - - #[cfg(not(any(target_os = "illumos", target_os = "solaris")))] - assert_eq!(unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), handler); - - // System V based OSes (e.g. illumos and Solaris) always resets the - // disposition to SIG_DFL prior to calling the signal handler - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - assert_eq!(unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), SigHandler::SigDfl); - - // Restore default signal handler - unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(); -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_signalfd.rs b/vendor/nix-v0.23.1-patched/test/sys/test_signalfd.rs deleted file mode 100644 index af04c2228..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_signalfd.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::convert::TryFrom; - -#[test] -fn test_signalfd() { - use nix::sys::signalfd::SignalFd; - use nix::sys::signal::{self, raise, Signal, SigSet}; - - // Grab the mutex for altering signals so we don't interfere with other tests. - let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test"); - - // Block the SIGUSR1 signal from automatic processing for this thread - let mut mask = SigSet::empty(); - mask.add(signal::SIGUSR1); - mask.thread_block().unwrap(); - - let mut fd = SignalFd::new(&mask).unwrap(); - - // Send a SIGUSR1 signal to the current process. Note that this uses `raise` instead of `kill` - // because `kill` with `getpid` isn't correct during multi-threaded execution like during a - // cargo test session. Instead use `raise` which does the correct thing by default. - raise(signal::SIGUSR1).expect("Error: raise(SIGUSR1) failed"); - - // And now catch that same signal. - let res = fd.read_signal().unwrap().unwrap(); - let signo = Signal::try_from(res.ssi_signo as i32).unwrap(); - assert_eq!(signo, signal::SIGUSR1); -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_socket.rs b/vendor/nix-v0.23.1-patched/test/sys/test_socket.rs deleted file mode 100644 index 0f6fac666..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_socket.rs +++ /dev/null @@ -1,1941 +0,0 @@ -use nix::sys::socket::{AddressFamily, InetAddr, SockAddr, UnixAddr, getsockname, sockaddr, sockaddr_in6, sockaddr_storage_to_addr}; -use std::collections::hash_map::DefaultHasher; -use std::hash::{Hash, Hasher}; -use std::mem::{self, MaybeUninit}; -use std::net::{self, Ipv6Addr, SocketAddr, SocketAddrV6}; -use std::os::unix::io::RawFd; -use std::path::Path; -use std::slice; -use std::str::FromStr; -use libc::{c_char, sockaddr_storage}; -#[cfg(any(target_os = "linux", target_os= "android"))] -use crate::*; - -#[test] -pub fn test_inetv4_addr_to_sock_addr() { - let actual: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap(); - let addr = InetAddr::from_std(&actual); - - match addr { - InetAddr::V4(addr) => { - let ip: u32 = 0x7f00_0001; - let port: u16 = 3000; - let saddr = addr.sin_addr.s_addr; - - assert_eq!(saddr, ip.to_be()); - assert_eq!(addr.sin_port, port.to_be()); - } - _ => panic!("nope"), - } - - assert_eq!(addr.to_string(), "127.0.0.1:3000"); - - let inet = addr.to_std(); - assert_eq!(actual, inet); -} - -#[test] -pub fn test_inetv4_addr_roundtrip_sockaddr_storage_to_addr() { - let actual: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap(); - let addr = InetAddr::from_std(&actual); - let sockaddr = SockAddr::new_inet(addr); - - let (storage, ffi_size) = { - let mut storage = MaybeUninit::::zeroed(); - let storage_ptr = storage.as_mut_ptr().cast::(); - let (ffi_ptr, ffi_size) = sockaddr.as_ffi_pair(); - assert_eq!(mem::size_of::(), ffi_size as usize); - unsafe { - storage_ptr.copy_from_nonoverlapping(ffi_ptr as *const sockaddr, 1); - (storage.assume_init(), ffi_size) - } - }; - - let from_storage = sockaddr_storage_to_addr(&storage, ffi_size as usize).unwrap(); - assert_eq!(from_storage, sockaddr); - let from_storage = sockaddr_storage_to_addr(&storage, mem::size_of::()).unwrap(); - assert_eq!(from_storage, sockaddr); -} - -#[test] -pub fn test_inetv6_addr_to_sock_addr() { - let port: u16 = 3000; - let flowinfo: u32 = 1; - let scope_id: u32 = 2; - let ip: Ipv6Addr = "fe80::1".parse().unwrap(); - - let actual = SocketAddr::V6(SocketAddrV6::new(ip, port, flowinfo, scope_id)); - let addr = InetAddr::from_std(&actual); - - match addr { - InetAddr::V6(addr) => { - assert_eq!(addr.sin6_port, port.to_be()); - assert_eq!(addr.sin6_flowinfo, flowinfo); - assert_eq!(addr.sin6_scope_id, scope_id); - } - _ => panic!("nope"), - } - - assert_eq!(actual, addr.to_std()); -} -#[test] -pub fn test_inetv6_addr_roundtrip_sockaddr_storage_to_addr() { - let port: u16 = 3000; - let flowinfo: u32 = 1; - let scope_id: u32 = 2; - let ip: Ipv6Addr = "fe80::1".parse().unwrap(); - - let actual = SocketAddr::V6(SocketAddrV6::new(ip, port, flowinfo, scope_id)); - let addr = InetAddr::from_std(&actual); - let sockaddr = SockAddr::new_inet(addr); - - let (storage, ffi_size) = { - let mut storage = MaybeUninit::::zeroed(); - let storage_ptr = storage.as_mut_ptr().cast::(); - let (ffi_ptr, ffi_size) = sockaddr.as_ffi_pair(); - assert_eq!(mem::size_of::(), ffi_size as usize); - unsafe { - storage_ptr.copy_from_nonoverlapping((ffi_ptr as *const sockaddr).cast::(), 1); - (storage.assume_init(), ffi_size) - } - }; - - let from_storage = sockaddr_storage_to_addr(&storage, ffi_size as usize).unwrap(); - assert_eq!(from_storage, sockaddr); - let from_storage = sockaddr_storage_to_addr(&storage, mem::size_of::()).unwrap(); - assert_eq!(from_storage, sockaddr); -} - -#[test] -pub fn test_path_to_sock_addr() { - let path = "/foo/bar"; - let actual = Path::new(path); - let addr = UnixAddr::new(actual).unwrap(); - - let expect: &[c_char] = unsafe { - slice::from_raw_parts(path.as_ptr() as *const c_char, path.len()) - }; - assert_eq!(unsafe { &(*addr.as_ptr()).sun_path[..8] }, expect); - - assert_eq!(addr.path(), Some(actual)); -} - -fn calculate_hash(t: &T) -> u64 { - let mut s = DefaultHasher::new(); - t.hash(&mut s); - s.finish() -} - -#[test] -pub fn test_addr_equality_path() { - let path = "/foo/bar"; - let actual = Path::new(path); - let addr1 = UnixAddr::new(actual).unwrap(); - let mut addr2 = addr1; - - unsafe { (*addr2.as_mut_ptr()).sun_path[10] = 127 }; - - assert_eq!(addr1, addr2); - assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2)); -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[test] -pub fn test_abstract_sun_path_too_long() { - let name = String::from("nix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0testttttnix\0abstract\0test\0make\0sure\0this\0is\0long\0enough"); - let addr = UnixAddr::new_abstract(name.as_bytes()); - assert!(addr.is_err()); -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[test] -pub fn test_addr_equality_abstract() { - let name = String::from("nix\0abstract\0test"); - let addr1 = UnixAddr::new_abstract(name.as_bytes()).unwrap(); - let mut addr2 = addr1; - - assert_eq!(addr1, addr2); - assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2)); - - unsafe { (*addr2.as_mut_ptr()).sun_path[17] = 127 }; - assert_ne!(addr1, addr2); - assert_ne!(calculate_hash(&addr1), calculate_hash(&addr2)); -} - -// Test getting/setting abstract addresses (without unix socket creation) -#[cfg(target_os = "linux")] -#[test] -pub fn test_abstract_uds_addr() { - let empty = String::new(); - let addr = UnixAddr::new_abstract(empty.as_bytes()).unwrap(); - let sun_path: [u8; 0] = []; - assert_eq!(addr.as_abstract(), Some(&sun_path[..])); - - let name = String::from("nix\0abstract\0test"); - let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap(); - let sun_path = [ - 110u8, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116 - ]; - assert_eq!(addr.as_abstract(), Some(&sun_path[..])); - assert_eq!(addr.path(), None); - - // Internally, name is null-prefixed (abstract namespace) - assert_eq!(unsafe { (*addr.as_ptr()).sun_path[0] }, 0); -} - -#[test] -pub fn test_getsockname() { - use nix::sys::socket::{socket, AddressFamily, SockType, SockFlag}; - use nix::sys::socket::{bind, SockAddr}; - - let tempdir = tempfile::tempdir().unwrap(); - let sockname = tempdir.path().join("sock"); - let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None) - .expect("socket failed"); - let sockaddr = SockAddr::new_unix(&sockname).unwrap(); - bind(sock, &sockaddr).expect("bind failed"); - assert_eq!(sockaddr, getsockname(sock).expect("getsockname failed")); -} - -#[test] -pub fn test_socketpair() { - use nix::unistd::{read, write}; - use nix::sys::socket::{socketpair, AddressFamily, SockType, SockFlag}; - - let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()) - .unwrap(); - write(fd1, b"hello").unwrap(); - let mut buf = [0;5]; - read(fd2, &mut buf).unwrap(); - - assert_eq!(&buf[..], b"hello"); -} - -mod recvfrom { - use nix::Result; - use nix::sys::socket::*; - use std::thread; - use super::*; - - const MSG: &[u8] = b"Hello, World!"; - - fn sendrecv(rsock: RawFd, ssock: RawFd, f_send: Fs, mut f_recv: Fr) -> Option - where - Fs: Fn(RawFd, &[u8], MsgFlags) -> Result + Send + 'static, - Fr: FnMut(usize, Option), - { - let mut buf: [u8; 13] = [0u8; 13]; - let mut l = 0; - let mut from = None; - - let send_thread = thread::spawn(move || { - let mut l = 0; - while l < std::mem::size_of_val(MSG) { - l += f_send(ssock, &MSG[l..], MsgFlags::empty()).unwrap(); - } - }); - - while l < std::mem::size_of_val(MSG) { - let (len, from_) = recvfrom(rsock, &mut buf[l..]).unwrap(); - f_recv(len, from_); - from = from_; - l += len; - } - assert_eq!(&buf, MSG); - send_thread.join().unwrap(); - from - } - - #[test] - pub fn stream() { - let (fd2, fd1) = socketpair(AddressFamily::Unix, SockType::Stream, - None, SockFlag::empty()).unwrap(); - // Ignore from for stream sockets - let _ = sendrecv(fd1, fd2, |s, m, flags| { - send(s, m, flags) - }, |_, _| {}); - } - - #[test] - pub fn udp() { - let std_sa = SocketAddr::from_str("127.0.0.1:6789").unwrap(); - let inet_addr = InetAddr::from_std(&std_sa); - let sock_addr = SockAddr::new_inet(inet_addr); - let rsock = socket(AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None - ).unwrap(); - bind(rsock, &sock_addr).unwrap(); - let ssock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ).expect("send socket failed"); - let from = sendrecv(rsock, ssock, move |s, m, flags| { - sendto(s, m, &sock_addr, flags) - },|_, _| {}); - // UDP sockets should set the from address - assert_eq!(AddressFamily::Inet, from.unwrap().family()); - } - - #[cfg(target_os = "linux")] - mod udp_offload { - use super::*; - use nix::sys::uio::IoVec; - use nix::sys::socket::sockopt::{UdpGroSegment, UdpGsoSegment}; - - #[test] - // Disable the test under emulation because it fails in Cirrus-CI. Lack - // of QEMU support is suspected. - #[cfg_attr(qemu, ignore)] - pub fn gso() { - require_kernel_version!(udp_offload::gso, ">= 4.18"); - - // In this test, we send the data and provide a GSO segment size. - // Since we are sending the buffer of size 13, six UDP packets - // with size 2 and two UDP packet with size 1 will be sent. - let segment_size: u16 = 2; - - let std_sa = SocketAddr::from_str("127.0.0.1:6791").unwrap(); - let inet_addr = InetAddr::from_std(&std_sa); - let sock_addr = SockAddr::new_inet(inet_addr); - let rsock = socket(AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None - ).unwrap(); - - setsockopt(rsock, UdpGsoSegment, &(segment_size as _)) - .expect("setsockopt UDP_SEGMENT failed"); - - bind(rsock, &sock_addr).unwrap(); - let ssock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ).expect("send socket failed"); - - let mut num_packets_received: i32 = 0; - - sendrecv(rsock, ssock, move |s, m, flags| { - let iov = [IoVec::from_slice(m)]; - let cmsg = ControlMessage::UdpGsoSegments(&segment_size); - sendmsg(s, &iov, &[cmsg], flags, Some(&sock_addr)) - }, { - let num_packets_received_ref = &mut num_packets_received; - - move |len, _| { - // check that we receive UDP packets with payload size - // less or equal to segment size - assert!(len <= segment_size as usize); - *num_packets_received_ref += 1; - } - }); - - // Buffer size is 13, we will receive six packets of size 2, - // and one packet of size 1. - assert_eq!(7, num_packets_received); - } - - #[test] - // Disable the test on emulated platforms because it fails in Cirrus-CI. - // Lack of QEMU support is suspected. - #[cfg_attr(qemu, ignore)] - pub fn gro() { - require_kernel_version!(udp_offload::gro, ">= 5.3"); - - // It's hard to guarantee receiving GRO packets. Just checking - // that `setsockopt` doesn't fail with error - - let rsock = socket(AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None - ).unwrap(); - - setsockopt(rsock, UdpGroSegment, &true) - .expect("setsockopt UDP_GRO failed"); - } - } - - #[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", - ))] - #[test] - pub fn udp_sendmmsg() { - use nix::sys::uio::IoVec; - - let std_sa = SocketAddr::from_str("127.0.0.1:6793").unwrap(); - let std_sa2 = SocketAddr::from_str("127.0.0.1:6794").unwrap(); - let inet_addr = InetAddr::from_std(&std_sa); - let inet_addr2 = InetAddr::from_std(&std_sa2); - let sock_addr = SockAddr::new_inet(inet_addr); - let sock_addr2 = SockAddr::new_inet(inet_addr2); - - let rsock = socket(AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None - ).unwrap(); - bind(rsock, &sock_addr).unwrap(); - let ssock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ).expect("send socket failed"); - - let from = sendrecv(rsock, ssock, move |s, m, flags| { - let iov = [IoVec::from_slice(m)]; - let mut msgs = vec![ - SendMmsgData { - iov: &iov, - cmsgs: &[], - addr: Some(sock_addr), - _lt: Default::default(), - } - ]; - - let batch_size = 15; - - for _ in 0..batch_size { - msgs.push( - SendMmsgData { - iov: &iov, - cmsgs: &[], - addr: Some(sock_addr2), - _lt: Default::default(), - } - ); - } - sendmmsg(s, msgs.iter(), flags) - .map(move |sent_bytes| { - assert!(!sent_bytes.is_empty()); - for sent in &sent_bytes { - assert_eq!(*sent, m.len()); - } - sent_bytes.len() - }) - }, |_, _ | {}); - // UDP sockets should set the from address - assert_eq!(AddressFamily::Inet, from.unwrap().family()); - } - - #[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", - ))] - #[test] - pub fn udp_recvmmsg() { - use nix::sys::uio::IoVec; - use nix::sys::socket::{MsgFlags, recvmmsg}; - - const NUM_MESSAGES_SENT: usize = 2; - const DATA: [u8; 2] = [1,2]; - - let std_sa = SocketAddr::from_str("127.0.0.1:6798").unwrap(); - let inet_addr = InetAddr::from_std(&std_sa); - let sock_addr = SockAddr::new_inet(inet_addr); - - let rsock = socket(AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None - ).unwrap(); - bind(rsock, &sock_addr).unwrap(); - let ssock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ).expect("send socket failed"); - - let send_thread = thread::spawn(move || { - for _ in 0..NUM_MESSAGES_SENT { - sendto(ssock, &DATA[..], &sock_addr, MsgFlags::empty()).unwrap(); - } - }); - - let mut msgs = std::collections::LinkedList::new(); - - // Buffers to receive exactly `NUM_MESSAGES_SENT` messages - let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT]; - let iovs: Vec<_> = receive_buffers.iter_mut().map(|buf| { - [IoVec::from_mut_slice(&mut buf[..])] - }).collect(); - - for iov in &iovs { - msgs.push_back(RecvMmsgData { - iov, - cmsg_buffer: None, - }) - }; - - let res = recvmmsg(rsock, &mut msgs, MsgFlags::empty(), None).expect("recvmmsg"); - assert_eq!(res.len(), DATA.len()); - - for RecvMsg { address, bytes, .. } in res.into_iter() { - assert_eq!(AddressFamily::Inet, address.unwrap().family()); - assert_eq!(DATA.len(), bytes); - } - - for buf in &receive_buffers { - assert_eq!(&buf[..DATA.len()], DATA); - } - - send_thread.join().unwrap(); - } - - #[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", - ))] - #[test] - pub fn udp_recvmmsg_dontwait_short_read() { - use nix::sys::uio::IoVec; - use nix::sys::socket::{MsgFlags, recvmmsg}; - - const NUM_MESSAGES_SENT: usize = 2; - const DATA: [u8; 4] = [1,2,3,4]; - - let std_sa = SocketAddr::from_str("127.0.0.1:6799").unwrap(); - let inet_addr = InetAddr::from_std(&std_sa); - let sock_addr = SockAddr::new_inet(inet_addr); - - let rsock = socket(AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None - ).unwrap(); - bind(rsock, &sock_addr).unwrap(); - let ssock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ).expect("send socket failed"); - - let send_thread = thread::spawn(move || { - for _ in 0..NUM_MESSAGES_SENT { - sendto(ssock, &DATA[..], &sock_addr, MsgFlags::empty()).unwrap(); - } - }); - // Ensure we've sent all the messages before continuing so `recvmmsg` - // will return right away - send_thread.join().unwrap(); - - let mut msgs = std::collections::LinkedList::new(); - - // Buffers to receive >`NUM_MESSAGES_SENT` messages to ensure `recvmmsg` - // will return when there are fewer than requested messages in the - // kernel buffers when using `MSG_DONTWAIT`. - let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT + 2]; - let iovs: Vec<_> = receive_buffers.iter_mut().map(|buf| { - [IoVec::from_mut_slice(&mut buf[..])] - }).collect(); - - for iov in &iovs { - msgs.push_back(RecvMmsgData { - iov, - cmsg_buffer: None, - }) - }; - - let res = recvmmsg(rsock, &mut msgs, MsgFlags::MSG_DONTWAIT, None).expect("recvmmsg"); - assert_eq!(res.len(), NUM_MESSAGES_SENT); - - for RecvMsg { address, bytes, .. } in res.into_iter() { - assert_eq!(AddressFamily::Inet, address.unwrap().family()); - assert_eq!(DATA.len(), bytes); - } - - for buf in &receive_buffers[..NUM_MESSAGES_SENT] { - assert_eq!(&buf[..DATA.len()], DATA); - } - } -} - -// Test error handling of our recvmsg wrapper -#[test] -pub fn test_recvmsg_ebadf() { - use nix::errno::Errno; - use nix::sys::socket::{MsgFlags, recvmsg}; - use nix::sys::uio::IoVec; - - let mut buf = [0u8; 5]; - let iov = [IoVec::from_mut_slice(&mut buf[..])]; - let fd = -1; // Bad file descriptor - let r = recvmsg(fd, &iov, None, MsgFlags::empty()); - assert_eq!(r.err().unwrap(), Errno::EBADF); -} - -// Disable the test on emulated platforms due to a bug in QEMU versions < -// 2.12.0. https://bugs.launchpad.net/qemu/+bug/1701808 -#[cfg_attr(qemu, ignore)] -#[test] -pub fn test_scm_rights() { - use nix::sys::uio::IoVec; - use nix::unistd::{pipe, read, write, close}; - use nix::sys::socket::{socketpair, sendmsg, recvmsg, - AddressFamily, SockType, SockFlag, - ControlMessage, ControlMessageOwned, MsgFlags}; - - let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()) - .unwrap(); - let (r, w) = pipe().unwrap(); - let mut received_r: Option = None; - - { - let iov = [IoVec::from_slice(b"hello")]; - let fds = [r]; - let cmsg = ControlMessage::ScmRights(&fds); - assert_eq!(sendmsg(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5); - close(r).unwrap(); - close(fd1).unwrap(); - } - - { - let mut buf = [0u8; 5]; - let iov = [IoVec::from_mut_slice(&mut buf[..])]; - let mut cmsgspace = cmsg_space!([RawFd; 1]); - let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap(); - - for cmsg in msg.cmsgs() { - if let ControlMessageOwned::ScmRights(fd) = cmsg { - assert_eq!(received_r, None); - assert_eq!(fd.len(), 1); - received_r = Some(fd[0]); - } else { - panic!("unexpected cmsg"); - } - } - assert_eq!(msg.bytes, 5); - assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)); - close(fd2).unwrap(); - } - - let received_r = received_r.expect("Did not receive passed fd"); - // Ensure that the received file descriptor works - write(w, b"world").unwrap(); - let mut buf = [0u8; 5]; - read(received_r, &mut buf).unwrap(); - assert_eq!(&buf[..], b"world"); - close(received_r).unwrap(); - close(w).unwrap(); -} - -// Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross -#[cfg(any(target_os = "linux", target_os= "android"))] -#[cfg_attr(qemu, ignore)] -#[test] -pub fn test_af_alg_cipher() { - use nix::sys::uio::IoVec; - use nix::unistd::read; - use nix::sys::socket::{socket, sendmsg, bind, accept, setsockopt, - AddressFamily, SockType, SockFlag, SockAddr, - ControlMessage, MsgFlags}; - use nix::sys::socket::sockopt::AlgSetKey; - - skip_if_cirrus!("Fails for an unknown reason Cirrus CI. Bug #1352"); - // Travis's seccomp profile blocks AF_ALG - // https://docs.docker.com/engine/security/seccomp/ - skip_if_seccomp!(test_af_alg_cipher); - - let alg_type = "skcipher"; - let alg_name = "ctr-aes-aesni"; - // 256-bits secret key - let key = vec![0u8; 32]; - // 16-bytes IV - let iv_len = 16; - let iv = vec![1u8; iv_len]; - // 256-bytes plain payload - let payload_len = 256; - let payload = vec![2u8; payload_len]; - - let sock = socket(AddressFamily::Alg, SockType::SeqPacket, SockFlag::empty(), None) - .expect("socket failed"); - - let sockaddr = SockAddr::new_alg(alg_type, alg_name); - bind(sock, &sockaddr).expect("bind failed"); - - if let SockAddr::Alg(alg) = sockaddr { - assert_eq!(alg.alg_name().to_string_lossy(), alg_name); - assert_eq!(alg.alg_type().to_string_lossy(), alg_type); - } else { - panic!("unexpected SockAddr"); - } - - setsockopt(sock, AlgSetKey::default(), &key).expect("setsockopt"); - let session_socket = accept(sock).expect("accept failed"); - - let msgs = [ControlMessage::AlgSetOp(&libc::ALG_OP_ENCRYPT), ControlMessage::AlgSetIv(iv.as_slice())]; - let iov = IoVec::from_slice(&payload); - sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg encrypt"); - - // allocate buffer for encrypted data - let mut encrypted = vec![0u8; payload_len]; - let num_bytes = read(session_socket, &mut encrypted).expect("read encrypt"); - assert_eq!(num_bytes, payload_len); - - let iov = IoVec::from_slice(&encrypted); - - let iv = vec![1u8; iv_len]; - - let msgs = [ControlMessage::AlgSetOp(&libc::ALG_OP_DECRYPT), ControlMessage::AlgSetIv(iv.as_slice())]; - sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg decrypt"); - - // allocate buffer for decrypted data - let mut decrypted = vec![0u8; payload_len]; - let num_bytes = read(session_socket, &mut decrypted).expect("read decrypt"); - - assert_eq!(num_bytes, payload_len); - assert_eq!(decrypted, payload); -} - -// Disable the test on emulated platforms due to not enabled support of AF_ALG -// in QEMU from rust cross -#[cfg(any(target_os = "linux", target_os= "android"))] -#[cfg_attr(qemu, ignore)] -#[test] -pub fn test_af_alg_aead() { - use libc::{ALG_OP_DECRYPT, ALG_OP_ENCRYPT}; - use nix::fcntl::{fcntl, FcntlArg, OFlag}; - use nix::sys::uio::IoVec; - use nix::unistd::{read, close}; - use nix::sys::socket::{socket, sendmsg, bind, accept, setsockopt, - AddressFamily, SockType, SockFlag, SockAddr, - ControlMessage, MsgFlags}; - use nix::sys::socket::sockopt::{AlgSetKey, AlgSetAeadAuthSize}; - - skip_if_cirrus!("Fails for an unknown reason Cirrus CI. Bug #1352"); - // Travis's seccomp profile blocks AF_ALG - // https://docs.docker.com/engine/security/seccomp/ - skip_if_seccomp!(test_af_alg_aead); - - let auth_size = 4usize; - let assoc_size = 16u32; - - let alg_type = "aead"; - let alg_name = "gcm(aes)"; - // 256-bits secret key - let key = vec![0u8; 32]; - // 12-bytes IV - let iv_len = 12; - let iv = vec![1u8; iv_len]; - // 256-bytes plain payload - let payload_len = 256; - let mut payload = vec![2u8; payload_len + (assoc_size as usize) + auth_size]; - - for i in 0..assoc_size { - payload[i as usize] = 10; - } - - let len = payload.len(); - - for i in 0..auth_size { - payload[len - 1 - i] = 0; - } - - let sock = socket(AddressFamily::Alg, SockType::SeqPacket, SockFlag::empty(), None) - .expect("socket failed"); - - let sockaddr = SockAddr::new_alg(alg_type, alg_name); - bind(sock, &sockaddr).expect("bind failed"); - - setsockopt(sock, AlgSetAeadAuthSize, &auth_size).expect("setsockopt AlgSetAeadAuthSize"); - setsockopt(sock, AlgSetKey::default(), &key).expect("setsockopt AlgSetKey"); - let session_socket = accept(sock).expect("accept failed"); - - let msgs = [ - ControlMessage::AlgSetOp(&ALG_OP_ENCRYPT), - ControlMessage::AlgSetIv(iv.as_slice()), - ControlMessage::AlgSetAeadAssoclen(&assoc_size)]; - let iov = IoVec::from_slice(&payload); - sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg encrypt"); - - // allocate buffer for encrypted data - let mut encrypted = vec![0u8; (assoc_size as usize) + payload_len + auth_size]; - let num_bytes = read(session_socket, &mut encrypted).expect("read encrypt"); - assert_eq!(num_bytes, payload_len + auth_size + (assoc_size as usize)); - close(session_socket).expect("close"); - - for i in 0..assoc_size { - encrypted[i as usize] = 10; - } - - let iov = IoVec::from_slice(&encrypted); - - let iv = vec![1u8; iv_len]; - - let session_socket = accept(sock).expect("accept failed"); - - let msgs = [ - ControlMessage::AlgSetOp(&ALG_OP_DECRYPT), - ControlMessage::AlgSetIv(iv.as_slice()), - ControlMessage::AlgSetAeadAssoclen(&assoc_size), - ]; - sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg decrypt"); - - // allocate buffer for decrypted data - let mut decrypted = vec![0u8; payload_len + (assoc_size as usize) + auth_size]; - // Starting with kernel 4.9, the interface changed slightly such that the - // authentication tag memory is only needed in the output buffer for encryption - // and in the input buffer for decryption. - // Do not block on read, as we may have fewer bytes than buffer size - fcntl(session_socket,FcntlArg::F_SETFL(OFlag::O_NONBLOCK)).expect("fcntl non_blocking"); - let num_bytes = read(session_socket, &mut decrypted).expect("read decrypt"); - - assert!(num_bytes >= payload_len + (assoc_size as usize)); - assert_eq!(decrypted[(assoc_size as usize)..(payload_len + (assoc_size as usize))], payload[(assoc_size as usize)..payload_len + (assoc_size as usize)]); -} - -// Verify `ControlMessage::Ipv4PacketInfo` for `sendmsg`. -// This creates a (udp) socket bound to localhost, then sends a message to -// itself but uses Ipv4PacketInfo to force the source address to be localhost. -// -// This would be a more interesting test if we could assume that the test host -// has more than one IP address (since we could select a different address to -// test from). -#[cfg(any(target_os = "linux", - target_os = "macos", - target_os = "netbsd"))] -#[test] -pub fn test_sendmsg_ipv4packetinfo() { - use cfg_if::cfg_if; - use nix::sys::uio::IoVec; - use nix::sys::socket::{socket, sendmsg, bind, - AddressFamily, SockType, SockFlag, SockAddr, - ControlMessage, MsgFlags}; - - let sock = socket(AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None) - .expect("socket failed"); - - let std_sa = SocketAddr::from_str("127.0.0.1:4000").unwrap(); - let inet_addr = InetAddr::from_std(&std_sa); - let sock_addr = SockAddr::new_inet(inet_addr); - - bind(sock, &sock_addr).expect("bind failed"); - - let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoVec::from_slice(&slice)]; - - if let InetAddr::V4(sin) = inet_addr { - cfg_if! { - if #[cfg(target_os = "netbsd")] { - let _dontcare = sin; - let pi = libc::in_pktinfo { - ipi_ifindex: 0, /* Unspecified interface */ - ipi_addr: libc::in_addr { s_addr: 0 }, - }; - } else { - let pi = libc::in_pktinfo { - ipi_ifindex: 0, /* Unspecified interface */ - ipi_addr: libc::in_addr { s_addr: 0 }, - ipi_spec_dst: sin.sin_addr, - }; - } - } - - let cmsg = [ControlMessage::Ipv4PacketInfo(&pi)]; - - sendmsg(sock, &iov, &cmsg, MsgFlags::empty(), Some(&sock_addr)) - .expect("sendmsg"); - } else { - panic!("No IPv4 addresses available for testing?"); - } -} - -// Verify `ControlMessage::Ipv6PacketInfo` for `sendmsg`. -// This creates a (udp) socket bound to ip6-localhost, then sends a message to -// itself but uses Ipv6PacketInfo to force the source address to be -// ip6-localhost. -// -// This would be a more interesting test if we could assume that the test host -// has more than one IP address (since we could select a different address to -// test from). -#[cfg(any(target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "freebsd"))] -#[test] -pub fn test_sendmsg_ipv6packetinfo() { - use nix::errno::Errno; - use nix::sys::uio::IoVec; - use nix::sys::socket::{socket, sendmsg, bind, - AddressFamily, SockType, SockFlag, SockAddr, - ControlMessage, MsgFlags}; - - let sock = socket(AddressFamily::Inet6, - SockType::Datagram, - SockFlag::empty(), - None) - .expect("socket failed"); - - let std_sa = SocketAddr::from_str("[::1]:6000").unwrap(); - let inet_addr = InetAddr::from_std(&std_sa); - let sock_addr = SockAddr::new_inet(inet_addr); - - if let Err(Errno::EADDRNOTAVAIL) = bind(sock, &sock_addr) { - println!("IPv6 not available, skipping test."); - return; - } - - let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoVec::from_slice(&slice)]; - - if let InetAddr::V6(sin) = inet_addr { - let pi = libc::in6_pktinfo { - ipi6_ifindex: 0, /* Unspecified interface */ - ipi6_addr: sin.sin6_addr, - }; - - let cmsg = [ControlMessage::Ipv6PacketInfo(&pi)]; - - sendmsg(sock, &iov, &cmsg, MsgFlags::empty(), Some(&sock_addr)) - .expect("sendmsg"); - } else { - println!("No IPv6 addresses available for testing: skipping testing Ipv6PacketInfo"); - } -} - -/// Tests that passing multiple fds using a single `ControlMessage` works. -// Disable the test on emulated platforms due to a bug in QEMU versions < -// 2.12.0. https://bugs.launchpad.net/qemu/+bug/1701808 -#[cfg_attr(qemu, ignore)] -#[test] -fn test_scm_rights_single_cmsg_multiple_fds() { - use std::os::unix::net::UnixDatagram; - use std::os::unix::io::{RawFd, AsRawFd}; - use std::thread; - use nix::sys::socket::{ControlMessage, ControlMessageOwned, MsgFlags, - sendmsg, recvmsg}; - use nix::sys::uio::IoVec; - - let (send, receive) = UnixDatagram::pair().unwrap(); - let thread = thread::spawn(move || { - let mut buf = [0u8; 8]; - let iovec = [IoVec::from_mut_slice(&mut buf)]; - let mut space = cmsg_space!([RawFd; 2]); - let msg = recvmsg( - receive.as_raw_fd(), - &iovec, - Some(&mut space), - MsgFlags::empty() - ).unwrap(); - assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)); - - let mut cmsgs = msg.cmsgs(); - match cmsgs.next() { - Some(ControlMessageOwned::ScmRights(fds)) => { - assert_eq!(fds.len(), 2, - "unexpected fd count (expected 2 fds, got {})", - fds.len()); - }, - _ => panic!(), - } - assert!(cmsgs.next().is_none(), "unexpected control msg"); - - assert_eq!(msg.bytes, 8); - assert_eq!(iovec[0].as_slice(), [1u8, 2, 3, 4, 5, 6, 7, 8]); - }); - - let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoVec::from_slice(&slice)]; - let fds = [libc::STDIN_FILENO, libc::STDOUT_FILENO]; // pass stdin and stdout - let cmsg = [ControlMessage::ScmRights(&fds)]; - sendmsg(send.as_raw_fd(), &iov, &cmsg, MsgFlags::empty(), None).unwrap(); - thread.join().unwrap(); -} - -// Verify `sendmsg` builds a valid `msghdr` when passing an empty -// `cmsgs` argument. This should result in a msghdr with a nullptr -// msg_control field and a msg_controllen of 0 when calling into the -// raw `sendmsg`. -#[test] -pub fn test_sendmsg_empty_cmsgs() { - use nix::sys::uio::IoVec; - use nix::unistd::close; - use nix::sys::socket::{socketpair, sendmsg, recvmsg, - AddressFamily, SockType, SockFlag, MsgFlags}; - - let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()) - .unwrap(); - - { - let iov = [IoVec::from_slice(b"hello")]; - assert_eq!(sendmsg(fd1, &iov, &[], MsgFlags::empty(), None).unwrap(), 5); - close(fd1).unwrap(); - } - - { - let mut buf = [0u8; 5]; - let iov = [IoVec::from_mut_slice(&mut buf[..])]; - let mut cmsgspace = cmsg_space!([RawFd; 1]); - let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap(); - - for _ in msg.cmsgs() { - panic!("unexpected cmsg"); - } - assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)); - assert_eq!(msg.bytes, 5); - close(fd2).unwrap(); - } -} - -#[cfg(any( - target_os = "android", - target_os = "linux", - target_os = "freebsd", - target_os = "dragonfly", -))] -#[test] -fn test_scm_credentials() { - use nix::sys::uio::IoVec; - use nix::unistd::{close, getpid, getuid, getgid}; - use nix::sys::socket::{socketpair, sendmsg, recvmsg, - AddressFamily, SockType, SockFlag, - ControlMessage, ControlMessageOwned, MsgFlags, - UnixCredentials}; - #[cfg(any(target_os = "android", target_os = "linux"))] - use nix::sys::socket::{setsockopt, sockopt::PassCred}; - - let (send, recv) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()) - .unwrap(); - #[cfg(any(target_os = "android", target_os = "linux"))] - setsockopt(recv, PassCred, &true).unwrap(); - - { - let iov = [IoVec::from_slice(b"hello")]; - #[cfg(any(target_os = "android", target_os = "linux"))] - let cred = UnixCredentials::new(); - #[cfg(any(target_os = "android", target_os = "linux"))] - let cmsg = ControlMessage::ScmCredentials(&cred); - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - let cmsg = ControlMessage::ScmCreds; - assert_eq!(sendmsg(send, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5); - close(send).unwrap(); - } - - { - let mut buf = [0u8; 5]; - let iov = [IoVec::from_mut_slice(&mut buf[..])]; - let mut cmsgspace = cmsg_space!(UnixCredentials); - let msg = recvmsg(recv, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap(); - let mut received_cred = None; - - for cmsg in msg.cmsgs() { - let cred = match cmsg { - #[cfg(any(target_os = "android", target_os = "linux"))] - ControlMessageOwned::ScmCredentials(cred) => cred, - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - ControlMessageOwned::ScmCreds(cred) => cred, - other => panic!("unexpected cmsg {:?}", other), - }; - assert!(received_cred.is_none()); - assert_eq!(cred.pid(), getpid().as_raw()); - assert_eq!(cred.uid(), getuid().as_raw()); - assert_eq!(cred.gid(), getgid().as_raw()); - received_cred = Some(cred); - } - received_cred.expect("no creds received"); - assert_eq!(msg.bytes, 5); - assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)); - close(recv).unwrap(); - } -} - -/// Ensure that we can send `SCM_CREDENTIALS` and `SCM_RIGHTS` with a single -/// `sendmsg` call. -#[cfg(any(target_os = "android", target_os = "linux"))] -// qemu's handling of multiple cmsgs is bugged, ignore tests under emulation -// see https://bugs.launchpad.net/qemu/+bug/1781280 -#[cfg_attr(qemu, ignore)] -#[test] -fn test_scm_credentials_and_rights() { - let space = cmsg_space!(libc::ucred, RawFd); - test_impl_scm_credentials_and_rights(space); -} - -/// Ensure that passing a an oversized control message buffer to recvmsg -/// still works. -#[cfg(any(target_os = "android", target_os = "linux"))] -// qemu's handling of multiple cmsgs is bugged, ignore tests under emulation -// see https://bugs.launchpad.net/qemu/+bug/1781280 -#[cfg_attr(qemu, ignore)] -#[test] -fn test_too_large_cmsgspace() { - let space = vec![0u8; 1024]; - test_impl_scm_credentials_and_rights(space); -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_impl_scm_credentials_and_rights(mut space: Vec) { - use libc::ucred; - use nix::sys::uio::IoVec; - use nix::unistd::{pipe, write, close, getpid, getuid, getgid}; - use nix::sys::socket::{socketpair, sendmsg, recvmsg, setsockopt, - SockType, SockFlag, - ControlMessage, ControlMessageOwned, MsgFlags}; - use nix::sys::socket::sockopt::PassCred; - - let (send, recv) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()) - .unwrap(); - setsockopt(recv, PassCred, &true).unwrap(); - - let (r, w) = pipe().unwrap(); - let mut received_r: Option = None; - - { - let iov = [IoVec::from_slice(b"hello")]; - let cred = ucred { - pid: getpid().as_raw(), - uid: getuid().as_raw(), - gid: getgid().as_raw(), - }.into(); - let fds = [r]; - let cmsgs = [ - ControlMessage::ScmCredentials(&cred), - ControlMessage::ScmRights(&fds), - ]; - assert_eq!(sendmsg(send, &iov, &cmsgs, MsgFlags::empty(), None).unwrap(), 5); - close(r).unwrap(); - close(send).unwrap(); - } - - { - let mut buf = [0u8; 5]; - let iov = [IoVec::from_mut_slice(&mut buf[..])]; - let msg = recvmsg(recv, &iov, Some(&mut space), MsgFlags::empty()).unwrap(); - let mut received_cred = None; - - assert_eq!(msg.cmsgs().count(), 2, "expected 2 cmsgs"); - - for cmsg in msg.cmsgs() { - match cmsg { - ControlMessageOwned::ScmRights(fds) => { - assert_eq!(received_r, None, "already received fd"); - assert_eq!(fds.len(), 1); - received_r = Some(fds[0]); - } - ControlMessageOwned::ScmCredentials(cred) => { - assert!(received_cred.is_none()); - assert_eq!(cred.pid(), getpid().as_raw()); - assert_eq!(cred.uid(), getuid().as_raw()); - assert_eq!(cred.gid(), getgid().as_raw()); - received_cred = Some(cred); - } - _ => panic!("unexpected cmsg"), - } - } - received_cred.expect("no creds received"); - assert_eq!(msg.bytes, 5); - assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)); - close(recv).unwrap(); - } - - let received_r = received_r.expect("Did not receive passed fd"); - // Ensure that the received file descriptor works - write(w, b"world").unwrap(); - let mut buf = [0u8; 5]; - read(received_r, &mut buf).unwrap(); - assert_eq!(&buf[..], b"world"); - close(received_r).unwrap(); - close(w).unwrap(); -} - -// Test creating and using named unix domain sockets -#[test] -pub fn test_unixdomain() { - use nix::sys::socket::{SockType, SockFlag}; - use nix::sys::socket::{bind, socket, connect, listen, accept, SockAddr}; - use nix::unistd::{read, write, close}; - use std::thread; - - let tempdir = tempfile::tempdir().unwrap(); - let sockname = tempdir.path().join("sock"); - let s1 = socket(AddressFamily::Unix, SockType::Stream, - SockFlag::empty(), None).expect("socket failed"); - let sockaddr = SockAddr::new_unix(&sockname).unwrap(); - bind(s1, &sockaddr).expect("bind failed"); - listen(s1, 10).expect("listen failed"); - - let thr = thread::spawn(move || { - let s2 = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None) - .expect("socket failed"); - connect(s2, &sockaddr).expect("connect failed"); - write(s2, b"hello").expect("write failed"); - close(s2).unwrap(); - }); - - let s3 = accept(s1).expect("accept failed"); - - let mut buf = [0;5]; - read(s3, &mut buf).unwrap(); - close(s3).unwrap(); - close(s1).unwrap(); - thr.join().unwrap(); - - assert_eq!(&buf[..], b"hello"); -} - -// Test creating and using named system control sockets -#[cfg(any(target_os = "macos", target_os = "ios"))] -#[test] -pub fn test_syscontrol() { - use nix::errno::Errno; - use nix::sys::socket::{socket, SockAddr, SockType, SockFlag, SockProtocol}; - - let fd = socket(AddressFamily::System, SockType::Datagram, - SockFlag::empty(), SockProtocol::KextControl) - .expect("socket failed"); - let _sockaddr = SockAddr::new_sys_control(fd, "com.apple.net.utun_control", 0).expect("resolving sys_control name failed"); - assert_eq!(SockAddr::new_sys_control(fd, "foo.bar.lol", 0).err(), Some(Errno::ENOENT)); - - // requires root privileges - // connect(fd, &sockaddr).expect("connect failed"); -} - -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -))] -fn loopback_address(family: AddressFamily) -> Option { - use std::io; - use std::io::Write; - use nix::ifaddrs::getifaddrs; - use nix::net::if_::*; - - let addrs = match getifaddrs() { - Ok(iter) => iter, - Err(e) => { - let stdioerr = io::stderr(); - let mut handle = stdioerr.lock(); - writeln!(handle, "getifaddrs: {:?}", e).unwrap(); - return None; - }, - }; - // return first address matching family - for ifaddr in addrs { - if ifaddr.flags.contains(InterfaceFlags::IFF_LOOPBACK) { - match ifaddr.address { - Some(SockAddr::Inet(InetAddr::V4(..))) => { - match family { - AddressFamily::Inet => return Some(ifaddr), - _ => continue - } - }, - Some(SockAddr::Inet(InetAddr::V6(..))) => { - match family { - AddressFamily::Inet6 => return Some(ifaddr), - _ => continue - } - }, - _ => continue, - } - } - } - None -} - -#[cfg(any( - target_os = "android", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", -))] -// qemu doesn't seem to be emulating this correctly in these architectures -#[cfg_attr(all( - qemu, - any( - target_arch = "mips", - target_arch = "mips64", - target_arch = "powerpc64", - ) -), ignore)] -#[test] -pub fn test_recv_ipv4pktinfo() { - use nix::sys::socket::sockopt::Ipv4PacketInfo; - use nix::sys::socket::{bind, SockFlag, SockType}; - use nix::sys::socket::{getsockname, setsockopt, socket}; - use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags}; - use nix::sys::uio::IoVec; - use nix::net::if_::*; - - let lo_ifaddr = loopback_address(AddressFamily::Inet); - let (lo_name, lo) = match lo_ifaddr { - Some(ifaddr) => (ifaddr.interface_name, - ifaddr.address.expect("Expect IPv4 address on interface")), - None => return, - }; - let receive = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ).expect("receive socket failed"); - bind(receive, &lo).expect("bind failed"); - let sa = getsockname(receive).expect("getsockname failed"); - setsockopt(receive, Ipv4PacketInfo, &true).expect("setsockopt failed"); - - { - let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoVec::from_slice(&slice)]; - - let send = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ).expect("send socket failed"); - sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)).expect("sendmsg failed"); - } - - { - let mut buf = [0u8; 8]; - let iovec = [IoVec::from_mut_slice(&mut buf)]; - let mut space = cmsg_space!(libc::in_pktinfo); - let msg = recvmsg( - receive, - &iovec, - Some(&mut space), - MsgFlags::empty(), - ).expect("recvmsg failed"); - assert!( - !msg.flags - .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC) - ); - - let mut cmsgs = msg.cmsgs(); - if let Some(ControlMessageOwned::Ipv4PacketInfo(pktinfo)) = cmsgs.next() { - let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex"); - assert_eq!( - pktinfo.ipi_ifindex as libc::c_uint, - i, - "unexpected ifindex (expected {}, got {})", - i, - pktinfo.ipi_ifindex - ); - } - assert!(cmsgs.next().is_none(), "unexpected additional control msg"); - assert_eq!(msg.bytes, 8); - assert_eq!( - iovec[0].as_slice(), - [1u8, 2, 3, 4, 5, 6, 7, 8] - ); - } -} - -#[cfg(any( - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -))] -// qemu doesn't seem to be emulating this correctly in these architectures -#[cfg_attr(all( - qemu, - any( - target_arch = "mips", - target_arch = "mips64", - target_arch = "powerpc64", - ) -), ignore)] -#[test] -pub fn test_recvif() { - use nix::net::if_::*; - use nix::sys::socket::sockopt::{Ipv4RecvIf, Ipv4RecvDstAddr}; - use nix::sys::socket::{bind, SockFlag, SockType}; - use nix::sys::socket::{getsockname, setsockopt, socket, SockAddr}; - use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags}; - use nix::sys::uio::IoVec; - - let lo_ifaddr = loopback_address(AddressFamily::Inet); - let (lo_name, lo) = match lo_ifaddr { - Some(ifaddr) => (ifaddr.interface_name, - ifaddr.address.expect("Expect IPv4 address on interface")), - None => return, - }; - let receive = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ).expect("receive socket failed"); - bind(receive, &lo).expect("bind failed"); - let sa = getsockname(receive).expect("getsockname failed"); - setsockopt(receive, Ipv4RecvIf, &true).expect("setsockopt IP_RECVIF failed"); - setsockopt(receive, Ipv4RecvDstAddr, &true).expect("setsockopt IP_RECVDSTADDR failed"); - - { - let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoVec::from_slice(&slice)]; - - let send = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ).expect("send socket failed"); - sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)).expect("sendmsg failed"); - } - - { - let mut buf = [0u8; 8]; - let iovec = [IoVec::from_mut_slice(&mut buf)]; - let mut space = cmsg_space!(libc::sockaddr_dl, libc::in_addr); - let msg = recvmsg( - receive, - &iovec, - Some(&mut space), - MsgFlags::empty(), - ).expect("recvmsg failed"); - assert!( - !msg.flags - .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC) - ); - assert_eq!(msg.cmsgs().count(), 2, "expected 2 cmsgs"); - - let mut rx_recvif = false; - let mut rx_recvdstaddr = false; - for cmsg in msg.cmsgs() { - match cmsg { - ControlMessageOwned::Ipv4RecvIf(dl) => { - rx_recvif = true; - let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex"); - assert_eq!( - dl.sdl_index as libc::c_uint, - i, - "unexpected ifindex (expected {}, got {})", - i, - dl.sdl_index - ); - }, - ControlMessageOwned::Ipv4RecvDstAddr(addr) => { - rx_recvdstaddr = true; - if let SockAddr::Inet(InetAddr::V4(a)) = lo { - assert_eq!(a.sin_addr.s_addr, - addr.s_addr, - "unexpected destination address (expected {}, got {})", - a.sin_addr.s_addr, - addr.s_addr); - } else { - panic!("unexpected Sockaddr"); - } - }, - _ => panic!("unexpected additional control msg"), - } - } - assert!(rx_recvif); - assert!(rx_recvdstaddr); - assert_eq!(msg.bytes, 8); - assert_eq!( - iovec[0].as_slice(), - [1u8, 2, 3, 4, 5, 6, 7, 8] - ); - } -} - -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -))] -// qemu doesn't seem to be emulating this correctly in these architectures -#[cfg_attr(all( - qemu, - any( - target_arch = "mips", - target_arch = "mips64", - target_arch = "powerpc64", - ) -), ignore)] -#[test] -pub fn test_recv_ipv6pktinfo() { - use nix::net::if_::*; - use nix::sys::socket::sockopt::Ipv6RecvPacketInfo; - use nix::sys::socket::{bind, SockFlag, SockType}; - use nix::sys::socket::{getsockname, setsockopt, socket}; - use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags}; - use nix::sys::uio::IoVec; - - let lo_ifaddr = loopback_address(AddressFamily::Inet6); - let (lo_name, lo) = match lo_ifaddr { - Some(ifaddr) => (ifaddr.interface_name, - ifaddr.address.expect("Expect IPv4 address on interface")), - None => return, - }; - let receive = socket( - AddressFamily::Inet6, - SockType::Datagram, - SockFlag::empty(), - None, - ).expect("receive socket failed"); - bind(receive, &lo).expect("bind failed"); - let sa = getsockname(receive).expect("getsockname failed"); - setsockopt(receive, Ipv6RecvPacketInfo, &true).expect("setsockopt failed"); - - { - let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoVec::from_slice(&slice)]; - - let send = socket( - AddressFamily::Inet6, - SockType::Datagram, - SockFlag::empty(), - None, - ).expect("send socket failed"); - sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)).expect("sendmsg failed"); - } - - { - let mut buf = [0u8; 8]; - let iovec = [IoVec::from_mut_slice(&mut buf)]; - let mut space = cmsg_space!(libc::in6_pktinfo); - let msg = recvmsg( - receive, - &iovec, - Some(&mut space), - MsgFlags::empty(), - ).expect("recvmsg failed"); - assert!( - !msg.flags - .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC) - ); - - let mut cmsgs = msg.cmsgs(); - if let Some(ControlMessageOwned::Ipv6PacketInfo(pktinfo)) = cmsgs.next() - { - let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex"); - assert_eq!( - pktinfo.ipi6_ifindex as libc::c_uint, - i, - "unexpected ifindex (expected {}, got {})", - i, - pktinfo.ipi6_ifindex - ); - } - assert!(cmsgs.next().is_none(), "unexpected additional control msg"); - assert_eq!(msg.bytes, 8); - assert_eq!( - iovec[0].as_slice(), - [1u8, 2, 3, 4, 5, 6, 7, 8] - ); - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[cfg_attr(graviton, ignore = "Not supported by the CI environment")] -#[test] -pub fn test_vsock() { - use nix::errno::Errno; - use nix::sys::socket::{AddressFamily, socket, bind, connect, listen, - SockAddr, SockType, SockFlag}; - use nix::unistd::{close}; - use std::thread; - - let port: u32 = 3000; - - let s1 = socket(AddressFamily::Vsock, SockType::Stream, - SockFlag::empty(), None) - .expect("socket failed"); - - // VMADDR_CID_HYPERVISOR is reserved, so we expect an EADDRNOTAVAIL error. - let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_HYPERVISOR, port); - assert_eq!(bind(s1, &sockaddr).err(), - Some(Errno::EADDRNOTAVAIL)); - - let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_ANY, port); - assert_eq!(bind(s1, &sockaddr), Ok(())); - listen(s1, 10).expect("listen failed"); - - let thr = thread::spawn(move || { - let cid: u32 = libc::VMADDR_CID_HOST; - - let s2 = socket(AddressFamily::Vsock, SockType::Stream, - SockFlag::empty(), None) - .expect("socket failed"); - - let sockaddr = SockAddr::new_vsock(cid, port); - - // The current implementation does not support loopback devices, so, - // for now, we expect a failure on the connect. - assert_ne!(connect(s2, &sockaddr), Ok(())); - - close(s2).unwrap(); - }); - - close(s1).unwrap(); - thr.join().unwrap(); -} - -// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack -// of QEMU support is suspected. -#[cfg_attr(qemu, ignore)] -#[cfg(all(target_os = "linux"))] -#[test] -fn test_recvmsg_timestampns() { - use nix::sys::socket::*; - use nix::sys::uio::IoVec; - use nix::sys::time::*; - use std::time::*; - - // Set up - let message = "Ohayō!".as_bytes(); - let in_socket = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None).unwrap(); - setsockopt(in_socket, sockopt::ReceiveTimestampns, &true).unwrap(); - let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0); - bind(in_socket, &SockAddr::new_inet(localhost)).unwrap(); - let address = getsockname(in_socket).unwrap(); - // Get initial time - let time0 = SystemTime::now(); - // Send the message - let iov = [IoVec::from_slice(message)]; - let flags = MsgFlags::empty(); - let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap(); - assert_eq!(message.len(), l); - // Receive the message - let mut buffer = vec![0u8; message.len()]; - let mut cmsgspace = nix::cmsg_space!(TimeSpec); - let iov = [IoVec::from_mut_slice(&mut buffer)]; - let r = recvmsg(in_socket, &iov, Some(&mut cmsgspace), flags).unwrap(); - let rtime = match r.cmsgs().next() { - Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime, - Some(_) => panic!("Unexpected control message"), - None => panic!("No control message") - }; - // Check the final time - let time1 = SystemTime::now(); - // the packet's received timestamp should lie in-between the two system - // times, unless the system clock was adjusted in the meantime. - let rduration = Duration::new(rtime.tv_sec() as u64, - rtime.tv_nsec() as u32); - assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration); - assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap()); - // Close socket - nix::unistd::close(in_socket).unwrap(); -} - -// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack -// of QEMU support is suspected. -#[cfg_attr(qemu, ignore)] -#[cfg(all(target_os = "linux"))] -#[test] -fn test_recvmmsg_timestampns() { - use nix::sys::socket::*; - use nix::sys::uio::IoVec; - use nix::sys::time::*; - use std::time::*; - - // Set up - let message = "Ohayō!".as_bytes(); - let in_socket = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None).unwrap(); - setsockopt(in_socket, sockopt::ReceiveTimestampns, &true).unwrap(); - let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0); - bind(in_socket, &SockAddr::new_inet(localhost)).unwrap(); - let address = getsockname(in_socket).unwrap(); - // Get initial time - let time0 = SystemTime::now(); - // Send the message - let iov = [IoVec::from_slice(message)]; - let flags = MsgFlags::empty(); - let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap(); - assert_eq!(message.len(), l); - // Receive the message - let mut buffer = vec![0u8; message.len()]; - let mut cmsgspace = nix::cmsg_space!(TimeSpec); - let iov = [IoVec::from_mut_slice(&mut buffer)]; - let mut data = vec![ - RecvMmsgData { - iov, - cmsg_buffer: Some(&mut cmsgspace), - }, - ]; - let r = recvmmsg(in_socket, &mut data, flags, None).unwrap(); - let rtime = match r[0].cmsgs().next() { - Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime, - Some(_) => panic!("Unexpected control message"), - None => panic!("No control message") - }; - // Check the final time - let time1 = SystemTime::now(); - // the packet's received timestamp should lie in-between the two system - // times, unless the system clock was adjusted in the meantime. - let rduration = Duration::new(rtime.tv_sec() as u64, - rtime.tv_nsec() as u32); - assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration); - assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap()); - // Close socket - nix::unistd::close(in_socket).unwrap(); -} - -// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack -// of QEMU support is suspected. -#[cfg_attr(qemu, ignore)] -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] -#[test] -fn test_recvmsg_rxq_ovfl() { - use nix::Error; - use nix::sys::socket::*; - use nix::sys::uio::IoVec; - use nix::sys::socket::sockopt::{RxqOvfl, RcvBuf}; - - let message = [0u8; 2048]; - let bufsize = message.len() * 2; - - let in_socket = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None).unwrap(); - let out_socket = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None).unwrap(); - - let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0); - bind(in_socket, &SockAddr::new_inet(localhost)).unwrap(); - - let address = getsockname(in_socket).unwrap(); - connect(out_socket, &address).unwrap(); - - // Set SO_RXQ_OVFL flag. - setsockopt(in_socket, RxqOvfl, &1).unwrap(); - - // Set the receiver buffer size to hold only 2 messages. - setsockopt(in_socket, RcvBuf, &bufsize).unwrap(); - - let mut drop_counter = 0; - - for _ in 0..2 { - let iov = [IoVec::from_slice(&message)]; - let flags = MsgFlags::empty(); - - // Send the 3 messages (the receiver buffer can only hold 2 messages) - // to create an overflow. - for _ in 0..3 { - let l = sendmsg(out_socket, &iov, &[], flags, Some(&address)).unwrap(); - assert_eq!(message.len(), l); - } - - // Receive the message and check the drop counter if any. - loop { - let mut buffer = vec![0u8; message.len()]; - let mut cmsgspace = nix::cmsg_space!(u32); - - let iov = [IoVec::from_mut_slice(&mut buffer)]; - - match recvmsg( - in_socket, - &iov, - Some(&mut cmsgspace), - MsgFlags::MSG_DONTWAIT) { - Ok(r) => { - drop_counter = match r.cmsgs().next() { - Some(ControlMessageOwned::RxqOvfl(drop_counter)) => drop_counter, - Some(_) => panic!("Unexpected control message"), - None => 0, - }; - }, - Err(Error::EAGAIN) => { break; }, - _ => { panic!("unknown recvmsg() error"); }, - } - } - } - - // One packet lost. - assert_eq!(drop_counter, 1); - - // Close sockets - nix::unistd::close(in_socket).unwrap(); - nix::unistd::close(out_socket).unwrap(); -} - -#[cfg(any( - target_os = "linux", - target_os = "android", -))] -mod linux_errqueue { - use nix::sys::socket::*; - use super::{FromStr, SocketAddr}; - - // Send a UDP datagram to a bogus destination address and observe an ICMP error (v4). - // - // Disable the test on QEMU because QEMU emulation of IP_RECVERR is broken (as documented on PR - // #1514). - #[cfg_attr(qemu, ignore)] - #[test] - fn test_recverr_v4() { - #[repr(u8)] - enum IcmpTypes { - DestUnreach = 3, // ICMP_DEST_UNREACH - } - #[repr(u8)] - enum IcmpUnreachCodes { - PortUnreach = 3, // ICMP_PORT_UNREACH - } - - test_recverr_impl::( - "127.0.0.1:6800", - AddressFamily::Inet, - sockopt::Ipv4RecvErr, - libc::SO_EE_ORIGIN_ICMP, - IcmpTypes::DestUnreach as u8, - IcmpUnreachCodes::PortUnreach as u8, - // Closure handles protocol-specific testing and returns generic sock_extended_err for - // protocol-independent test impl. - |cmsg| { - if let ControlMessageOwned::Ipv4RecvErr(ext_err, err_addr) = cmsg { - if let Some(origin) = err_addr { - // Validate that our network error originated from 127.0.0.1:0. - assert_eq!(origin.sin_family, AddressFamily::Inet as _); - assert_eq!(Ipv4Addr(origin.sin_addr), Ipv4Addr::new(127, 0, 0, 1)); - assert_eq!(origin.sin_port, 0); - } else { - panic!("Expected some error origin"); - } - *ext_err - } else { - panic!("Unexpected control message {:?}", cmsg); - } - }, - ) - } - - // Essentially the same test as v4. - // - // Disable the test on QEMU because QEMU emulation of IPV6_RECVERR is broken (as documented on - // PR #1514). - #[cfg_attr(qemu, ignore)] - #[test] - fn test_recverr_v6() { - #[repr(u8)] - enum IcmpV6Types { - DestUnreach = 1, // ICMPV6_DEST_UNREACH - } - #[repr(u8)] - enum IcmpV6UnreachCodes { - PortUnreach = 4, // ICMPV6_PORT_UNREACH - } - - test_recverr_impl::( - "[::1]:6801", - AddressFamily::Inet6, - sockopt::Ipv6RecvErr, - libc::SO_EE_ORIGIN_ICMP6, - IcmpV6Types::DestUnreach as u8, - IcmpV6UnreachCodes::PortUnreach as u8, - // Closure handles protocol-specific testing and returns generic sock_extended_err for - // protocol-independent test impl. - |cmsg| { - if let ControlMessageOwned::Ipv6RecvErr(ext_err, err_addr) = cmsg { - if let Some(origin) = err_addr { - // Validate that our network error originated from localhost:0. - assert_eq!(origin.sin6_family, AddressFamily::Inet6 as _); - assert_eq!( - Ipv6Addr(origin.sin6_addr), - Ipv6Addr::from_std(&"::1".parse().unwrap()), - ); - assert_eq!(origin.sin6_port, 0); - } else { - panic!("Expected some error origin"); - } - *ext_err - } else { - panic!("Unexpected control message {:?}", cmsg); - } - }, - ) - } - - fn test_recverr_impl(sa: &str, - af: AddressFamily, - opt: OPT, - ee_origin: u8, - ee_type: u8, - ee_code: u8, - testf: TESTF) - where - OPT: SetSockOpt, - TESTF: FnOnce(&ControlMessageOwned) -> libc::sock_extended_err, - { - use nix::errno::Errno; - use nix::sys::uio::IoVec; - - const MESSAGE_CONTENTS: &str = "ABCDEF"; - - let sock_addr = { - let std_sa = SocketAddr::from_str(sa).unwrap(); - let inet_addr = InetAddr::from_std(&std_sa); - SockAddr::new_inet(inet_addr) - }; - let sock = socket(af, SockType::Datagram, SockFlag::SOCK_CLOEXEC, None).unwrap(); - setsockopt(sock, opt, &true).unwrap(); - if let Err(e) = sendto(sock, MESSAGE_CONTENTS.as_bytes(), &sock_addr, MsgFlags::empty()) { - assert_eq!(e, Errno::EADDRNOTAVAIL); - println!("{:?} not available, skipping test.", af); - return; - } - - let mut buf = [0u8; 8]; - let iovec = [IoVec::from_mut_slice(&mut buf)]; - let mut cspace = cmsg_space!(libc::sock_extended_err, SA); - - let msg = recvmsg(sock, &iovec, Some(&mut cspace), MsgFlags::MSG_ERRQUEUE).unwrap(); - // The sent message / destination associated with the error is returned: - assert_eq!(msg.bytes, MESSAGE_CONTENTS.as_bytes().len()); - assert_eq!(&buf[..msg.bytes], MESSAGE_CONTENTS.as_bytes()); - // recvmsg(2): "The original destination address of the datagram that caused the error is - // supplied via msg_name;" however, this is not literally true. E.g., an earlier version - // of this test used 0.0.0.0 (::0) as the destination address, which was mutated into - // 127.0.0.1 (::1). - assert_eq!(msg.address, Some(sock_addr)); - - // Check for expected control message. - let ext_err = match msg.cmsgs().next() { - Some(cmsg) => testf(&cmsg), - None => panic!("No control message"), - }; - - assert_eq!(ext_err.ee_errno, libc::ECONNREFUSED as u32); - assert_eq!(ext_err.ee_origin, ee_origin); - // ip(7): ee_type and ee_code are set from the type and code fields of the ICMP (ICMPv6) - // header. - assert_eq!(ext_err.ee_type, ee_type); - assert_eq!(ext_err.ee_code, ee_code); - // ip(7): ee_info contains the discovered MTU for EMSGSIZE errors. - assert_eq!(ext_err.ee_info, 0); - } -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_sockopt.rs b/vendor/nix-v0.23.1-patched/test/sys/test_sockopt.rs deleted file mode 100644 index 01920fd40..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_sockopt.rs +++ /dev/null @@ -1,199 +0,0 @@ -use rand::{thread_rng, Rng}; -use nix::sys::socket::{socket, sockopt, getsockopt, setsockopt, AddressFamily, SockType, SockFlag, SockProtocol}; -#[cfg(any(target_os = "android", target_os = "linux"))] -use crate::*; - -// NB: FreeBSD supports LOCAL_PEERCRED for SOCK_SEQPACKET, but OSX does not. -#[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", -))] -#[test] -pub fn test_local_peercred_seqpacket() { - use nix::{ - unistd::{Gid, Uid}, - sys::socket::socketpair - }; - - let (fd1, _fd2) = socketpair(AddressFamily::Unix, SockType::SeqPacket, None, - SockFlag::empty()).unwrap(); - let xucred = getsockopt(fd1, sockopt::LocalPeerCred).unwrap(); - assert_eq!(xucred.version(), 0); - assert_eq!(Uid::from_raw(xucred.uid()), Uid::current()); - assert_eq!(Gid::from_raw(xucred.groups()[0]), Gid::current()); -} - -#[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "ios" -))] -#[test] -pub fn test_local_peercred_stream() { - use nix::{ - unistd::{Gid, Uid}, - sys::socket::socketpair - }; - - let (fd1, _fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, - SockFlag::empty()).unwrap(); - let xucred = getsockopt(fd1, sockopt::LocalPeerCred).unwrap(); - assert_eq!(xucred.version(), 0); - assert_eq!(Uid::from_raw(xucred.uid()), Uid::current()); - assert_eq!(Gid::from_raw(xucred.groups()[0]), Gid::current()); -} - -#[cfg(target_os = "linux")] -#[test] -fn is_so_mark_functional() { - use nix::sys::socket::sockopt; - - require_capability!("is_so_mark_functional", CAP_NET_ADMIN); - - let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap(); - setsockopt(s, sockopt::Mark, &1337).unwrap(); - let mark = getsockopt(s, sockopt::Mark).unwrap(); - assert_eq!(mark, 1337); -} - -#[test] -fn test_so_buf() { - let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), SockProtocol::Udp) - .unwrap(); - let bufsize: usize = thread_rng().gen_range(4096..131_072); - setsockopt(fd, sockopt::SndBuf, &bufsize).unwrap(); - let actual = getsockopt(fd, sockopt::SndBuf).unwrap(); - assert!(actual >= bufsize); - setsockopt(fd, sockopt::RcvBuf, &bufsize).unwrap(); - let actual = getsockopt(fd, sockopt::RcvBuf).unwrap(); - assert!(actual >= bufsize); -} - -#[test] -fn test_so_tcp_maxseg() { - use std::net::SocketAddr; - use std::str::FromStr; - use nix::sys::socket::{accept, bind, connect, listen, InetAddr, SockAddr}; - use nix::unistd::{close, write}; - - let std_sa = SocketAddr::from_str("127.0.0.1:4001").unwrap(); - let inet_addr = InetAddr::from_std(&std_sa); - let sock_addr = SockAddr::new_inet(inet_addr); - - let rsock = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), SockProtocol::Tcp) - .unwrap(); - bind(rsock, &sock_addr).unwrap(); - listen(rsock, 10).unwrap(); - let initial = getsockopt(rsock, sockopt::TcpMaxSeg).unwrap(); - // Initial MSS is expected to be 536 (https://tools.ietf.org/html/rfc879#section-1) but some - // platforms keep it even lower. This might fail if you've tuned your initial MSS to be larger - // than 700 - cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { - let segsize: u32 = 873; - assert!(initial < segsize); - setsockopt(rsock, sockopt::TcpMaxSeg, &segsize).unwrap(); - } else { - assert!(initial < 700); - } - } - - // Connect and check the MSS that was advertised - let ssock = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), SockProtocol::Tcp) - .unwrap(); - connect(ssock, &sock_addr).unwrap(); - let rsess = accept(rsock).unwrap(); - write(rsess, b"hello").unwrap(); - let actual = getsockopt(ssock, sockopt::TcpMaxSeg).unwrap(); - // Actual max segment size takes header lengths into account, max IPv4 options (60 bytes) + max - // TCP options (40 bytes) are subtracted from the requested maximum as a lower boundary. - cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { - assert!((segsize - 100) <= actual); - assert!(actual <= segsize); - } else { - assert!(initial < actual); - assert!(536 < actual); - } - } - close(rsock).unwrap(); - close(ssock).unwrap(); -} - -// The CI doesn't supported getsockopt and setsockopt on emulated processors. -// It's beleived that a QEMU issue, the tests run ok on a fully emulated system. -// Current CI just run the binary with QEMU but the Kernel remains the same as the host. -// So the syscall doesn't work properly unless the kernel is also emulated. -#[test] -#[cfg(all( - any(target_arch = "x86", target_arch = "x86_64"), - any(target_os = "freebsd", target_os = "linux") -))] -fn test_tcp_congestion() { - use std::ffi::OsString; - - let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap(); - - let val = getsockopt(fd, sockopt::TcpCongestion).unwrap(); - setsockopt(fd, sockopt::TcpCongestion, &val).unwrap(); - - setsockopt(fd, sockopt::TcpCongestion, &OsString::from("tcp_congestion_does_not_exist")).unwrap_err(); - - assert_eq!( - getsockopt(fd, sockopt::TcpCongestion).unwrap(), - val - ); -} - -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_bindtodevice() { - skip_if_not_root!("test_bindtodevice"); - - let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap(); - - let val = getsockopt(fd, sockopt::BindToDevice).unwrap(); - setsockopt(fd, sockopt::BindToDevice, &val).unwrap(); - - assert_eq!( - getsockopt(fd, sockopt::BindToDevice).unwrap(), - val - ); -} - -#[test] -fn test_so_tcp_keepalive() { - let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), SockProtocol::Tcp).unwrap(); - setsockopt(fd, sockopt::KeepAlive, &true).unwrap(); - assert!(getsockopt(fd, sockopt::KeepAlive).unwrap()); - - #[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux", - target_os = "nacl"))] { - let x = getsockopt(fd, sockopt::TcpKeepIdle).unwrap(); - setsockopt(fd, sockopt::TcpKeepIdle, &(x + 1)).unwrap(); - assert_eq!(getsockopt(fd, sockopt::TcpKeepIdle).unwrap(), x + 1); - - let x = getsockopt(fd, sockopt::TcpKeepCount).unwrap(); - setsockopt(fd, sockopt::TcpKeepCount, &(x + 1)).unwrap(); - assert_eq!(getsockopt(fd, sockopt::TcpKeepCount).unwrap(), x + 1); - - let x = getsockopt(fd, sockopt::TcpKeepInterval).unwrap(); - setsockopt(fd, sockopt::TcpKeepInterval, &(x + 1)).unwrap(); - assert_eq!(getsockopt(fd, sockopt::TcpKeepInterval).unwrap(), x + 1); - } -} - -#[test] -#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] -fn test_ttl_opts() { - let fd4 = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap(); - setsockopt(fd4, sockopt::Ipv4Ttl, &1) - .expect("setting ipv4ttl on an inet socket should succeed"); - let fd6 = socket(AddressFamily::Inet6, SockType::Datagram, SockFlag::empty(), None).unwrap(); - setsockopt(fd6, sockopt::Ipv6Ttl, &1) - .expect("setting ipv6ttl on an inet6 socket should succeed"); -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_sysinfo.rs b/vendor/nix-v0.23.1-patched/test/sys/test_sysinfo.rs deleted file mode 100644 index 73e6586f6..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_sysinfo.rs +++ /dev/null @@ -1,18 +0,0 @@ -use nix::sys::sysinfo::*; - -#[test] -fn sysinfo_works() { - let info = sysinfo().unwrap(); - - let (l1, l5, l15) = info.load_average(); - assert!(l1 >= 0.0); - assert!(l5 >= 0.0); - assert!(l15 >= 0.0); - - info.uptime(); // just test Duration construction - - assert!(info.swap_free() <= info.swap_total(), - "more swap available than installed (free: {}, total: {})", - info.swap_free(), - info.swap_total()); -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_termios.rs b/vendor/nix-v0.23.1-patched/test/sys/test_termios.rs deleted file mode 100644 index 63d6a51fa..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_termios.rs +++ /dev/null @@ -1,130 +0,0 @@ -use std::os::unix::prelude::*; -use tempfile::tempfile; - -use nix::fcntl; -use nix::errno::Errno; -use nix::pty::openpty; -use nix::sys::termios::{self, LocalFlags, OutputFlags, tcgetattr}; -use nix::unistd::{read, write, close}; - -/// Helper function analogous to `std::io::Write::write_all`, but for `RawFd`s -fn write_all(f: RawFd, buf: &[u8]) { - let mut len = 0; - while len < buf.len() { - len += write(f, &buf[len..]).unwrap(); - } -} - -// Test tcgetattr on a terminal -#[test] -fn test_tcgetattr_pty() { - // openpty uses ptname(3) internally - let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test"); - - let pty = openpty(None, None).expect("openpty failed"); - assert!(termios::tcgetattr(pty.slave).is_ok()); - close(pty.master).expect("closing the master failed"); - close(pty.slave).expect("closing the slave failed"); -} - -// Test tcgetattr on something that isn't a terminal -#[test] -fn test_tcgetattr_enotty() { - let file = tempfile().unwrap(); - assert_eq!(termios::tcgetattr(file.as_raw_fd()).err(), - Some(Errno::ENOTTY)); -} - -// Test tcgetattr on an invalid file descriptor -#[test] -fn test_tcgetattr_ebadf() { - assert_eq!(termios::tcgetattr(-1).err(), - Some(Errno::EBADF)); -} - -// Test modifying output flags -#[test] -fn test_output_flags() { - // openpty uses ptname(3) internally - let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test"); - - // Open one pty to get attributes for the second one - let mut termios = { - let pty = openpty(None, None).expect("openpty failed"); - assert!(pty.master > 0); - assert!(pty.slave > 0); - let termios = tcgetattr(pty.slave).expect("tcgetattr failed"); - close(pty.master).unwrap(); - close(pty.slave).unwrap(); - termios - }; - - // Make sure postprocessing '\r' isn't specified by default or this test is useless. - assert!(!termios.output_flags.contains(OutputFlags::OPOST | OutputFlags::OCRNL)); - - // Specify that '\r' characters should be transformed to '\n' - // OPOST is specified to enable post-processing - termios.output_flags.insert(OutputFlags::OPOST | OutputFlags::OCRNL); - - // Open a pty - let pty = openpty(None, &termios).unwrap(); - assert!(pty.master > 0); - assert!(pty.slave > 0); - - // Write into the master - let string = "foofoofoo\r"; - write_all(pty.master, string.as_bytes()); - - // Read from the slave verifying that the output has been properly transformed - let mut buf = [0u8; 10]; - crate::read_exact(pty.slave, &mut buf); - let transformed_string = "foofoofoo\n"; - close(pty.master).unwrap(); - close(pty.slave).unwrap(); - assert_eq!(&buf, transformed_string.as_bytes()); -} - -// Test modifying local flags -#[test] -fn test_local_flags() { - // openpty uses ptname(3) internally - let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test"); - - // Open one pty to get attributes for the second one - let mut termios = { - let pty = openpty(None, None).unwrap(); - assert!(pty.master > 0); - assert!(pty.slave > 0); - let termios = tcgetattr(pty.slave).unwrap(); - close(pty.master).unwrap(); - close(pty.slave).unwrap(); - termios - }; - - // Make sure echo is specified by default or this test is useless. - assert!(termios.local_flags.contains(LocalFlags::ECHO)); - - // Disable local echo - termios.local_flags.remove(LocalFlags::ECHO); - - // Open a new pty with our modified termios settings - let pty = openpty(None, &termios).unwrap(); - assert!(pty.master > 0); - assert!(pty.slave > 0); - - // Set the master is in nonblocking mode or reading will never return. - let flags = fcntl::fcntl(pty.master, fcntl::F_GETFL).unwrap(); - let new_flags = fcntl::OFlag::from_bits_truncate(flags) | fcntl::OFlag::O_NONBLOCK; - fcntl::fcntl(pty.master, fcntl::F_SETFL(new_flags)).unwrap(); - - // Write into the master - let string = "foofoofoo\r"; - write_all(pty.master, string.as_bytes()); - - // Try to read from the master, which should not have anything as echoing was disabled. - let mut buf = [0u8; 10]; - let read = read(pty.master, &mut buf).unwrap_err(); - close(pty.master).unwrap(); - close(pty.slave).unwrap(); - assert_eq!(read, Errno::EAGAIN); -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_timerfd.rs b/vendor/nix-v0.23.1-patched/test/sys/test_timerfd.rs deleted file mode 100644 index 24fb2ac00..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_timerfd.rs +++ /dev/null @@ -1,61 +0,0 @@ -use nix::sys::time::{TimeSpec, TimeValLike}; -use nix::sys::timerfd::{ClockId, Expiration, TimerFd, TimerFlags, TimerSetTimeFlags}; -use std::time::Instant; - -#[test] -pub fn test_timerfd_oneshot() { - let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap(); - - let before = Instant::now(); - - timer - .set( - Expiration::OneShot(TimeSpec::seconds(1)), - TimerSetTimeFlags::empty(), - ) - .unwrap(); - - timer.wait().unwrap(); - - let millis = before.elapsed().as_millis(); - assert!(millis > 900); -} - -#[test] -pub fn test_timerfd_interval() { - let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap(); - - let before = Instant::now(); - timer - .set( - Expiration::IntervalDelayed(TimeSpec::seconds(1), TimeSpec::seconds(2)), - TimerSetTimeFlags::empty(), - ) - .unwrap(); - - timer.wait().unwrap(); - - let start_delay = before.elapsed().as_millis(); - assert!(start_delay > 900); - - timer.wait().unwrap(); - - let interval_delay = before.elapsed().as_millis(); - assert!(interval_delay > 2900); -} - -#[test] -pub fn test_timerfd_unset() { - let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap(); - - timer - .set( - Expiration::OneShot(TimeSpec::seconds(1)), - TimerSetTimeFlags::empty(), - ) - .unwrap(); - - timer.unset().unwrap(); - - assert!(timer.get().unwrap() == None); -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_uio.rs b/vendor/nix-v0.23.1-patched/test/sys/test_uio.rs deleted file mode 100644 index 24df04355..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_uio.rs +++ /dev/null @@ -1,255 +0,0 @@ -use nix::sys::uio::*; -use nix::unistd::*; -use rand::{thread_rng, Rng}; -use rand::distributions::Alphanumeric; -use std::{cmp, iter}; -use std::fs::{OpenOptions}; -use std::os::unix::io::AsRawFd; - -#[cfg(not(target_os = "redox"))] -use tempfile::tempfile; -use tempfile::tempdir; - -#[test] -fn test_writev() { - let mut to_write = Vec::with_capacity(16 * 128); - for _ in 0..16 { - let s: String = thread_rng() - .sample_iter(&Alphanumeric) - .map(char::from) - .take(128) - .collect(); - let b = s.as_bytes(); - to_write.extend(b.iter().cloned()); - } - // Allocate and fill iovecs - let mut iovecs = Vec::new(); - let mut consumed = 0; - while consumed < to_write.len() { - let left = to_write.len() - consumed; - let slice_len = if left <= 64 { left } else { thread_rng().gen_range(64..cmp::min(256, left)) }; - let b = &to_write[consumed..consumed+slice_len]; - iovecs.push(IoVec::from_slice(b)); - consumed += slice_len; - } - let pipe_res = pipe(); - assert!(pipe_res.is_ok()); - let (reader, writer) = pipe_res.ok().unwrap(); - // FileDesc will close its filedesc (reader). - let mut read_buf: Vec = iter::repeat(0u8).take(128 * 16).collect(); - // Blocking io, should write all data. - let write_res = writev(writer, &iovecs); - // Successful write - assert!(write_res.is_ok()); - let written = write_res.ok().unwrap(); - // Check whether we written all data - assert_eq!(to_write.len(), written); - let read_res = read(reader, &mut read_buf[..]); - // Successful read - assert!(read_res.is_ok()); - let read = read_res.ok().unwrap() as usize; - // Check we have read as much as we written - assert_eq!(read, written); - // Check equality of written and read data - assert_eq!(&to_write, &read_buf); - let close_res = close(writer); - assert!(close_res.is_ok()); - let close_res = close(reader); - assert!(close_res.is_ok()); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_readv() { - let s:String = thread_rng() - .sample_iter(&Alphanumeric) - .map(char::from) - .take(128) - .collect(); - let to_write = s.as_bytes().to_vec(); - let mut storage = Vec::new(); - let mut allocated = 0; - while allocated < to_write.len() { - let left = to_write.len() - allocated; - let vec_len = if left <= 64 { left } else { thread_rng().gen_range(64..cmp::min(256, left)) }; - let v: Vec = iter::repeat(0u8).take(vec_len).collect(); - storage.push(v); - allocated += vec_len; - } - let mut iovecs = Vec::with_capacity(storage.len()); - for v in &mut storage { - iovecs.push(IoVec::from_mut_slice(&mut v[..])); - } - let pipe_res = pipe(); - assert!(pipe_res.is_ok()); - let (reader, writer) = pipe_res.ok().unwrap(); - // Blocking io, should write all data. - let write_res = write(writer, &to_write); - // Successful write - assert!(write_res.is_ok()); - let read_res = readv(reader, &mut iovecs[..]); - assert!(read_res.is_ok()); - let read = read_res.ok().unwrap(); - // Check whether we've read all data - assert_eq!(to_write.len(), read); - // Cccumulate data from iovecs - let mut read_buf = Vec::with_capacity(to_write.len()); - for iovec in &iovecs { - read_buf.extend(iovec.as_slice().iter().cloned()); - } - // Check whether iovecs contain all written data - assert_eq!(read_buf.len(), to_write.len()); - // Check equality of written and read data - assert_eq!(&read_buf, &to_write); - let close_res = close(reader); - assert!(close_res.is_ok()); - let close_res = close(writer); - assert!(close_res.is_ok()); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_pwrite() { - use std::io::Read; - - let mut file = tempfile().unwrap(); - let buf = [1u8;8]; - assert_eq!(Ok(8), pwrite(file.as_raw_fd(), &buf, 8)); - let mut file_content = Vec::new(); - file.read_to_end(&mut file_content).unwrap(); - let mut expected = vec![0u8;8]; - expected.extend(vec![1;8]); - assert_eq!(file_content, expected); -} - -#[test] -fn test_pread() { - use std::io::Write; - - let tempdir = tempdir().unwrap(); - - let path = tempdir.path().join("pread_test_file"); - let mut file = OpenOptions::new().write(true).read(true).create(true) - .truncate(true).open(path).unwrap(); - let file_content: Vec = (0..64).collect(); - file.write_all(&file_content).unwrap(); - - let mut buf = [0u8;16]; - assert_eq!(Ok(16), pread(file.as_raw_fd(), &mut buf, 16)); - let expected: Vec<_> = (16..32).collect(); - assert_eq!(&buf[..], &expected[..]); -} - -#[test] -#[cfg(not(any(target_os = "macos", target_os = "redox")))] -fn test_pwritev() { - use std::io::Read; - - let to_write: Vec = (0..128).collect(); - let expected: Vec = [vec![0;100], to_write.clone()].concat(); - - let iovecs = [ - IoVec::from_slice(&to_write[0..17]), - IoVec::from_slice(&to_write[17..64]), - IoVec::from_slice(&to_write[64..128]), - ]; - - let tempdir = tempdir().unwrap(); - - // pwritev them into a temporary file - let path = tempdir.path().join("pwritev_test_file"); - let mut file = OpenOptions::new().write(true).read(true).create(true) - .truncate(true).open(path).unwrap(); - - let written = pwritev(file.as_raw_fd(), &iovecs, 100).ok().unwrap(); - assert_eq!(written, to_write.len()); - - // Read the data back and make sure it matches - let mut contents = Vec::new(); - file.read_to_end(&mut contents).unwrap(); - assert_eq!(contents, expected); -} - -#[test] -#[cfg(not(any(target_os = "macos", target_os = "redox")))] -fn test_preadv() { - use std::io::Write; - - let to_write: Vec = (0..200).collect(); - let expected: Vec = (100..200).collect(); - - let tempdir = tempdir().unwrap(); - - let path = tempdir.path().join("preadv_test_file"); - - let mut file = OpenOptions::new().read(true).write(true).create(true) - .truncate(true).open(path).unwrap(); - file.write_all(&to_write).unwrap(); - - let mut buffers: Vec> = vec![ - vec![0; 24], - vec![0; 1], - vec![0; 75], - ]; - - { - // Borrow the buffers into IoVecs and preadv into them - let iovecs: Vec<_> = buffers.iter_mut().map( - |buf| IoVec::from_mut_slice(&mut buf[..])).collect(); - assert_eq!(Ok(100), preadv(file.as_raw_fd(), &iovecs, 100)); - } - - let all = buffers.concat(); - assert_eq!(all, expected); -} - -#[test] -#[cfg(target_os = "linux")] -// qemu-user doesn't implement process_vm_readv/writev on most arches -#[cfg_attr(qemu, ignore)] -fn test_process_vm_readv() { - use nix::unistd::ForkResult::*; - use nix::sys::signal::*; - use nix::sys::wait::*; - use crate::*; - - require_capability!("test_process_vm_readv", CAP_SYS_PTRACE); - let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test"); - - // Pre-allocate memory in the child, since allocation isn't safe - // post-fork (~= async-signal-safe) - let mut vector = vec![1u8, 2, 3, 4, 5]; - - let (r, w) = pipe().unwrap(); - match unsafe{fork()}.expect("Error: Fork Failed") { - Parent { child } => { - close(w).unwrap(); - // wait for child - read(r, &mut [0u8]).unwrap(); - close(r).unwrap(); - - let ptr = vector.as_ptr() as usize; - let remote_iov = RemoteIoVec { base: ptr, len: 5 }; - let mut buf = vec![0u8; 5]; - - let ret = process_vm_readv(child, - &[IoVec::from_mut_slice(&mut buf)], - &[remote_iov]); - - kill(child, SIGTERM).unwrap(); - waitpid(child, None).unwrap(); - - assert_eq!(Ok(5), ret); - assert_eq!(20u8, buf.iter().sum()); - }, - Child => { - let _ = close(r); - for i in &mut vector { - *i += 1; - } - let _ = write(w, b"\0"); - let _ = close(w); - loop { let _ = pause(); } - }, - } -} diff --git a/vendor/nix-v0.23.1-patched/test/sys/test_wait.rs b/vendor/nix-v0.23.1-patched/test/sys/test_wait.rs deleted file mode 100644 index 4a5b9661f..000000000 --- a/vendor/nix-v0.23.1-patched/test/sys/test_wait.rs +++ /dev/null @@ -1,107 +0,0 @@ -use nix::errno::Errno; -use nix::unistd::*; -use nix::unistd::ForkResult::*; -use nix::sys::signal::*; -use nix::sys::wait::*; -use libc::_exit; - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_wait_signal() { - let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test"); - - // Safe: The child only calls `pause` and/or `_exit`, which are async-signal-safe. - match unsafe{fork()}.expect("Error: Fork Failed") { - Child => { - pause(); - unsafe { _exit(123) } - }, - Parent { child } => { - kill(child, Some(SIGKILL)).expect("Error: Kill Failed"); - assert_eq!(waitpid(child, None), Ok(WaitStatus::Signaled(child, SIGKILL, false))); - }, - } -} - -#[test] -fn test_wait_exit() { - let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test"); - - // Safe: Child only calls `_exit`, which is async-signal-safe. - match unsafe{fork()}.expect("Error: Fork Failed") { - Child => unsafe { _exit(12); }, - Parent { child } => { - assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 12))); - }, - } -} - -#[test] -fn test_waitstatus_from_raw() { - let pid = Pid::from_raw(1); - assert_eq!(WaitStatus::from_raw(pid, 0x0002), Ok(WaitStatus::Signaled(pid, Signal::SIGINT, false))); - assert_eq!(WaitStatus::from_raw(pid, 0x0200), Ok(WaitStatus::Exited(pid, 2))); - assert_eq!(WaitStatus::from_raw(pid, 0x7f7f), Err(Errno::EINVAL)); -} - -#[test] -fn test_waitstatus_pid() { - let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test"); - - match unsafe{fork()}.unwrap() { - Child => unsafe { _exit(0) }, - Parent { child } => { - let status = waitpid(child, None).unwrap(); - assert_eq!(status.pid(), Some(child)); - } - } -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -// FIXME: qemu-user doesn't implement ptrace on most arches -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -mod ptrace { - use nix::sys::ptrace::{self, Options, Event}; - use nix::sys::signal::*; - use nix::sys::wait::*; - use nix::unistd::*; - use nix::unistd::ForkResult::*; - use libc::_exit; - use crate::*; - - fn ptrace_child() -> ! { - ptrace::traceme().unwrap(); - // As recommended by ptrace(2), raise SIGTRAP to pause the child - // until the parent is ready to continue - raise(SIGTRAP).unwrap(); - unsafe { _exit(0) } - } - - fn ptrace_parent(child: Pid) { - // Wait for the raised SIGTRAP - assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, SIGTRAP))); - // We want to test a syscall stop and a PTRACE_EVENT stop - assert!(ptrace::setoptions(child, Options::PTRACE_O_TRACESYSGOOD | Options::PTRACE_O_TRACEEXIT).is_ok()); - - // First, stop on the next system call, which will be exit() - assert!(ptrace::syscall(child, None).is_ok()); - assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child))); - // Then get the ptrace event for the process exiting - assert!(ptrace::cont(child, None).is_ok()); - assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceEvent(child, SIGTRAP, Event::PTRACE_EVENT_EXIT as i32))); - // Finally get the normal wait() result, now that the process has exited - assert!(ptrace::cont(child, None).is_ok()); - assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 0))); - } - - #[test] - fn test_wait_ptrace() { - require_capability!("test_wait_ptrace", CAP_SYS_PTRACE); - let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test"); - - match unsafe{fork()}.expect("Error: Fork Failed") { - Child => ptrace_child(), - Parent { child } => ptrace_parent(child), - } - } -} diff --git a/vendor/nix-v0.23.1-patched/test/test.rs b/vendor/nix-v0.23.1-patched/test/test.rs deleted file mode 100644 index b882d1748..000000000 --- a/vendor/nix-v0.23.1-patched/test/test.rs +++ /dev/null @@ -1,103 +0,0 @@ -#[macro_use] -extern crate cfg_if; -#[cfg_attr(not(target_os = "redox"), macro_use)] -extern crate nix; -#[macro_use] -extern crate lazy_static; - -mod common; -mod sys; -#[cfg(not(target_os = "redox"))] -mod test_dir; -mod test_fcntl; -#[cfg(any(target_os = "android", - target_os = "linux"))] -mod test_kmod; -#[cfg(target_os = "freebsd")] -mod test_nmount; -#[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "fushsia", - target_os = "linux", - target_os = "netbsd"))] -mod test_mq; -#[cfg(not(target_os = "redox"))] -mod test_net; -mod test_nix_path; -mod test_resource; -mod test_poll; -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -mod test_pty; -#[cfg(any(target_os = "android", - target_os = "linux"))] -mod test_sched; -#[cfg(any(target_os = "android", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos"))] -mod test_sendfile; -mod test_stat; -mod test_time; -mod test_unistd; - -use std::os::unix::io::RawFd; -use std::path::PathBuf; -use std::sync::{Mutex, RwLock, RwLockWriteGuard}; -use nix::unistd::{chdir, getcwd, read}; - - -/// Helper function analogous to `std::io::Read::read_exact`, but for `RawFD`s -fn read_exact(f: RawFd, buf: &mut [u8]) { - let mut len = 0; - while len < buf.len() { - // get_mut would be better than split_at_mut, but it requires nightly - let (_, remaining) = buf.split_at_mut(len); - len += read(f, remaining).unwrap(); - } -} - -lazy_static! { - /// Any test that changes the process's current working directory must grab - /// the RwLock exclusively. Any process that cares about the current - /// working directory must grab it shared. - pub static ref CWD_LOCK: RwLock<()> = RwLock::new(()); - /// Any test that creates child processes must grab this mutex, regardless - /// of what it does with those children. - pub static ref FORK_MTX: Mutex<()> = Mutex::new(()); - /// Any test that changes the process's supplementary groups must grab this - /// mutex - pub static ref GROUPS_MTX: Mutex<()> = Mutex::new(()); - /// Any tests that loads or unloads kernel modules must grab this mutex - pub static ref KMOD_MTX: Mutex<()> = Mutex::new(()); - /// Any test that calls ptsname(3) must grab this mutex. - pub static ref PTSNAME_MTX: Mutex<()> = Mutex::new(()); - /// Any test that alters signal handling must grab this mutex. - pub static ref SIGNAL_MTX: Mutex<()> = Mutex::new(()); -} - -/// RAII object that restores a test's original directory on drop -struct DirRestore<'a> { - d: PathBuf, - _g: RwLockWriteGuard<'a, ()> -} - -impl<'a> DirRestore<'a> { - fn new() -> Self { - let guard = crate::CWD_LOCK.write() - .expect("Lock got poisoned by another test"); - DirRestore{ - _g: guard, - d: getcwd().unwrap(), - } - } -} - -impl<'a> Drop for DirRestore<'a> { - fn drop(&mut self) { - let r = chdir(&self.d); - if std::thread::panicking() { - r.unwrap(); - } - } -} diff --git a/vendor/nix-v0.23.1-patched/test/test_clearenv.rs b/vendor/nix-v0.23.1-patched/test/test_clearenv.rs deleted file mode 100644 index 28a776804..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_clearenv.rs +++ /dev/null @@ -1,9 +0,0 @@ -use std::env; - -#[test] -fn clearenv() { - env::set_var("FOO", "BAR"); - unsafe { nix::env::clearenv() }.unwrap(); - assert_eq!(env::var("FOO").unwrap_err(), env::VarError::NotPresent); - assert_eq!(env::vars().count(), 0); -} diff --git a/vendor/nix-v0.23.1-patched/test/test_dir.rs b/vendor/nix-v0.23.1-patched/test/test_dir.rs deleted file mode 100644 index 2940b6eaf..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_dir.rs +++ /dev/null @@ -1,56 +0,0 @@ -use nix::dir::{Dir, Type}; -use nix::fcntl::OFlag; -use nix::sys::stat::Mode; -use std::fs::File; -use tempfile::tempdir; - - -#[cfg(test)] -fn flags() -> OFlag { - #[cfg(target_os = "illumos")] - let f = OFlag::O_RDONLY | OFlag::O_CLOEXEC; - - #[cfg(not(target_os = "illumos"))] - let f = OFlag::O_RDONLY | OFlag::O_CLOEXEC | OFlag::O_DIRECTORY; - - f -} - -#[test] -#[allow(clippy::unnecessary_sort_by)] // False positive -fn read() { - let tmp = tempdir().unwrap(); - File::create(&tmp.path().join("foo")).unwrap(); - ::std::os::unix::fs::symlink("foo", tmp.path().join("bar")).unwrap(); - let mut dir = Dir::open(tmp.path(), flags(), Mode::empty()).unwrap(); - let mut entries: Vec<_> = dir.iter().map(|e| e.unwrap()).collect(); - entries.sort_by(|a, b| a.file_name().cmp(b.file_name())); - let entry_names: Vec<_> = entries - .iter() - .map(|e| e.file_name().to_str().unwrap().to_owned()) - .collect(); - assert_eq!(&entry_names[..], &[".", "..", "bar", "foo"]); - - // Check file types. The system is allowed to return DT_UNKNOWN (aka None here) but if it does - // return a type, ensure it's correct. - assert!(&[Some(Type::Directory), None].contains(&entries[0].file_type())); // .: dir - assert!(&[Some(Type::Directory), None].contains(&entries[1].file_type())); // ..: dir - assert!(&[Some(Type::Symlink), None].contains(&entries[2].file_type())); // bar: symlink - assert!(&[Some(Type::File), None].contains(&entries[3].file_type())); // foo: regular file -} - -#[test] -fn rewind() { - let tmp = tempdir().unwrap(); - let mut dir = Dir::open(tmp.path(), flags(), Mode::empty()).unwrap(); - let entries1: Vec<_> = dir.iter().map(|e| e.unwrap().file_name().to_owned()).collect(); - let entries2: Vec<_> = dir.iter().map(|e| e.unwrap().file_name().to_owned()).collect(); - let entries3: Vec<_> = dir.into_iter().map(|e| e.unwrap().file_name().to_owned()).collect(); - assert_eq!(entries1, entries2); - assert_eq!(entries2, entries3); -} - -#[test] -fn ebadf() { - assert_eq!(Dir::from_fd(-1).unwrap_err(), nix::Error::EBADF); -} diff --git a/vendor/nix-v0.23.1-patched/test/test_fcntl.rs b/vendor/nix-v0.23.1-patched/test/test_fcntl.rs deleted file mode 100644 index db2acfbf5..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_fcntl.rs +++ /dev/null @@ -1,540 +0,0 @@ -#[cfg(not(target_os = "redox"))] -use nix::errno::*; -#[cfg(not(target_os = "redox"))] -use nix::fcntl::{open, OFlag, readlink}; -#[cfg(not(target_os = "redox"))] -use nix::fcntl::{openat, readlinkat, renameat}; -#[cfg(all( - target_os = "linux", - target_env = "gnu", - any( - target_arch = "x86_64", - target_arch = "x32", - target_arch = "powerpc", - target_arch = "s390x" - ) -))] -use nix::fcntl::{RenameFlags, renameat2}; -#[cfg(not(target_os = "redox"))] -use nix::sys::stat::Mode; -#[cfg(not(target_os = "redox"))] -use nix::unistd::{close, read}; -#[cfg(not(target_os = "redox"))] -use tempfile::{self, NamedTempFile}; -#[cfg(not(target_os = "redox"))] -use std::fs::File; -#[cfg(not(target_os = "redox"))] -use std::io::prelude::*; -#[cfg(not(target_os = "redox"))] -use std::os::unix::fs; - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_openat() { - const CONTENTS: &[u8] = b"abcd"; - let mut tmp = NamedTempFile::new().unwrap(); - tmp.write_all(CONTENTS).unwrap(); - - let dirfd = open(tmp.path().parent().unwrap(), - OFlag::empty(), - Mode::empty()).unwrap(); - let fd = openat(dirfd, - tmp.path().file_name().unwrap(), - OFlag::O_RDONLY, - Mode::empty()).unwrap(); - - let mut buf = [0u8; 1024]; - assert_eq!(4, read(fd, &mut buf).unwrap()); - assert_eq!(CONTENTS, &buf[0..4]); - - close(fd).unwrap(); - close(dirfd).unwrap(); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_renameat() { - let old_dir = tempfile::tempdir().unwrap(); - let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); - let old_path = old_dir.path().join("old"); - File::create(&old_path).unwrap(); - let new_dir = tempfile::tempdir().unwrap(); - let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); - renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap(); - assert_eq!(renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap_err(), - Errno::ENOENT); - close(old_dirfd).unwrap(); - close(new_dirfd).unwrap(); - assert!(new_dir.path().join("new").exists()); -} - -#[test] -#[cfg(all( - target_os = "linux", - target_env = "gnu", - any( - target_arch = "x86_64", - target_arch = "x32", - target_arch = "powerpc", - target_arch = "s390x" - ) -))] -fn test_renameat2_behaves_like_renameat_with_no_flags() { - let old_dir = tempfile::tempdir().unwrap(); - let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); - let old_path = old_dir.path().join("old"); - File::create(&old_path).unwrap(); - let new_dir = tempfile::tempdir().unwrap(); - let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); - renameat2( - Some(old_dirfd), - "old", - Some(new_dirfd), - "new", - RenameFlags::empty(), - ) - .unwrap(); - assert_eq!( - renameat2( - Some(old_dirfd), - "old", - Some(new_dirfd), - "new", - RenameFlags::empty() - ) - .unwrap_err(), - Errno::ENOENT - ); - close(old_dirfd).unwrap(); - close(new_dirfd).unwrap(); - assert!(new_dir.path().join("new").exists()); -} - -#[test] -#[cfg(all( - target_os = "linux", - target_env = "gnu", - any( - target_arch = "x86_64", - target_arch = "x32", - target_arch = "powerpc", - target_arch = "s390x" - ) -))] -fn test_renameat2_exchange() { - let old_dir = tempfile::tempdir().unwrap(); - let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); - let old_path = old_dir.path().join("old"); - { - let mut old_f = File::create(&old_path).unwrap(); - old_f.write_all(b"old").unwrap(); - } - let new_dir = tempfile::tempdir().unwrap(); - let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); - let new_path = new_dir.path().join("new"); - { - let mut new_f = File::create(&new_path).unwrap(); - new_f.write_all(b"new").unwrap(); - } - renameat2( - Some(old_dirfd), - "old", - Some(new_dirfd), - "new", - RenameFlags::RENAME_EXCHANGE, - ) - .unwrap(); - let mut buf = String::new(); - let mut new_f = File::open(&new_path).unwrap(); - new_f.read_to_string(&mut buf).unwrap(); - assert_eq!(buf, "old"); - buf = "".to_string(); - let mut old_f = File::open(&old_path).unwrap(); - old_f.read_to_string(&mut buf).unwrap(); - assert_eq!(buf, "new"); - close(old_dirfd).unwrap(); - close(new_dirfd).unwrap(); -} - -#[test] -#[cfg(all( - target_os = "linux", - target_env = "gnu", - any( - target_arch = "x86_64", - target_arch = "x32", - target_arch = "powerpc", - target_arch = "s390x" - ) -))] -fn test_renameat2_noreplace() { - let old_dir = tempfile::tempdir().unwrap(); - let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); - let old_path = old_dir.path().join("old"); - File::create(&old_path).unwrap(); - let new_dir = tempfile::tempdir().unwrap(); - let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); - let new_path = new_dir.path().join("new"); - File::create(&new_path).unwrap(); - assert_eq!( - renameat2( - Some(old_dirfd), - "old", - Some(new_dirfd), - "new", - RenameFlags::RENAME_NOREPLACE - ) - .unwrap_err(), - Errno::EEXIST - ); - close(old_dirfd).unwrap(); - close(new_dirfd).unwrap(); - assert!(new_dir.path().join("new").exists()); - assert!(old_dir.path().join("old").exists()); -} - - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_readlink() { - let tempdir = tempfile::tempdir().unwrap(); - let src = tempdir.path().join("a"); - let dst = tempdir.path().join("b"); - println!("a: {:?}, b: {:?}", &src, &dst); - fs::symlink(&src.as_path(), &dst.as_path()).unwrap(); - let dirfd = open(tempdir.path(), - OFlag::empty(), - Mode::empty()).unwrap(); - let expected_dir = src.to_str().unwrap(); - - assert_eq!(readlink(&dst).unwrap().to_str().unwrap(), expected_dir); - assert_eq!(readlinkat(dirfd, "b").unwrap().to_str().unwrap(), expected_dir); - -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -mod linux_android { - use std::io::prelude::*; - use std::io::SeekFrom; - use std::os::unix::prelude::*; - use libc::loff_t; - - use nix::fcntl::*; - use nix::sys::uio::IoVec; - use nix::unistd::{close, pipe, read, write}; - - use tempfile::tempfile; - #[cfg(any(target_os = "linux"))] - use tempfile::NamedTempFile; - - use crate::*; - - /// This test creates a temporary file containing the contents - /// 'foobarbaz' and uses the `copy_file_range` call to transfer - /// 3 bytes at offset 3 (`bar`) to another empty file at offset 0. The - /// resulting file is read and should contain the contents `bar`. - /// The from_offset should be updated by the call to reflect - /// the 3 bytes read (6). - #[test] - // QEMU does not support copy_file_range. Skip under qemu - #[cfg_attr(qemu, ignore)] - fn test_copy_file_range() { - const CONTENTS: &[u8] = b"foobarbaz"; - - let mut tmp1 = tempfile().unwrap(); - let mut tmp2 = tempfile().unwrap(); - - tmp1.write_all(CONTENTS).unwrap(); - tmp1.flush().unwrap(); - - let mut from_offset: i64 = 3; - copy_file_range( - tmp1.as_raw_fd(), - Some(&mut from_offset), - tmp2.as_raw_fd(), - None, - 3, - ) - .unwrap(); - - let mut res: String = String::new(); - tmp2.seek(SeekFrom::Start(0)).unwrap(); - tmp2.read_to_string(&mut res).unwrap(); - - assert_eq!(res, String::from("bar")); - assert_eq!(from_offset, 6); - } - - #[test] - fn test_splice() { - const CONTENTS: &[u8] = b"abcdef123456"; - let mut tmp = tempfile().unwrap(); - tmp.write_all(CONTENTS).unwrap(); - - let (rd, wr) = pipe().unwrap(); - let mut offset: loff_t = 5; - let res = splice(tmp.as_raw_fd(), Some(&mut offset), - wr, None, 2, SpliceFFlags::empty()).unwrap(); - - assert_eq!(2, res); - - let mut buf = [0u8; 1024]; - assert_eq!(2, read(rd, &mut buf).unwrap()); - assert_eq!(b"f1", &buf[0..2]); - assert_eq!(7, offset); - - close(rd).unwrap(); - close(wr).unwrap(); - } - - #[test] - fn test_tee() { - let (rd1, wr1) = pipe().unwrap(); - let (rd2, wr2) = pipe().unwrap(); - - write(wr1, b"abc").unwrap(); - let res = tee(rd1, wr2, 2, SpliceFFlags::empty()).unwrap(); - - assert_eq!(2, res); - - let mut buf = [0u8; 1024]; - - // Check the tee'd bytes are at rd2. - assert_eq!(2, read(rd2, &mut buf).unwrap()); - assert_eq!(b"ab", &buf[0..2]); - - // Check all the bytes are still at rd1. - assert_eq!(3, read(rd1, &mut buf).unwrap()); - assert_eq!(b"abc", &buf[0..3]); - - close(rd1).unwrap(); - close(wr1).unwrap(); - close(rd2).unwrap(); - close(wr2).unwrap(); - } - - #[test] - fn test_vmsplice() { - let (rd, wr) = pipe().unwrap(); - - let buf1 = b"abcdef"; - let buf2 = b"defghi"; - let iovecs = vec![ - IoVec::from_slice(&buf1[0..3]), - IoVec::from_slice(&buf2[0..3]) - ]; - - let res = vmsplice(wr, &iovecs[..], SpliceFFlags::empty()).unwrap(); - - assert_eq!(6, res); - - // Check the bytes can be read at rd. - let mut buf = [0u8; 32]; - assert_eq!(6, read(rd, &mut buf).unwrap()); - assert_eq!(b"abcdef", &buf[0..6]); - - close(rd).unwrap(); - close(wr).unwrap(); - } - - #[cfg(any(target_os = "linux"))] - #[test] - fn test_fallocate() { - let tmp = NamedTempFile::new().unwrap(); - - let fd = tmp.as_raw_fd(); - fallocate(fd, FallocateFlags::empty(), 0, 100).unwrap(); - - // Check if we read exactly 100 bytes - let mut buf = [0u8; 200]; - assert_eq!(100, read(fd, &mut buf).unwrap()); - } - - // The tests below are disabled for the listed targets - // due to OFD locks not being available in the kernel/libc - // versions used in the CI environment, probably because - // they run under QEMU. - - #[test] - #[cfg(all(target_os = "linux", not(target_env = "musl")))] - fn test_ofd_write_lock() { - use nix::sys::stat::fstat; - use std::mem; - - let tmp = NamedTempFile::new().unwrap(); - - let fd = tmp.as_raw_fd(); - let statfs = nix::sys::statfs::fstatfs(&tmp).unwrap(); - if statfs.filesystem_type() == nix::sys::statfs::OVERLAYFS_SUPER_MAGIC { - // OverlayFS is a union file system. It returns one inode value in - // stat(2), but a different one shows up in /proc/locks. So we must - // skip the test. - skip!("/proc/locks does not work on overlayfs"); - } - let inode = fstat(fd).expect("fstat failed").st_ino as usize; - - let mut flock: libc::flock = unsafe { - mem::zeroed() // required for Linux/mips - }; - flock.l_type = libc::F_WRLCK as libc::c_short; - flock.l_whence = libc::SEEK_SET as libc::c_short; - flock.l_start = 0; - flock.l_len = 0; - flock.l_pid = 0; - fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write lock failed"); - assert_eq!( - Some(("OFDLCK".to_string(), "WRITE".to_string())), - lock_info(inode) - ); - - flock.l_type = libc::F_UNLCK as libc::c_short; - fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write unlock failed"); - assert_eq!(None, lock_info(inode)); - } - - #[test] - #[cfg(all(target_os = "linux", not(target_env = "musl")))] - fn test_ofd_read_lock() { - use nix::sys::stat::fstat; - use std::mem; - - let tmp = NamedTempFile::new().unwrap(); - - let fd = tmp.as_raw_fd(); - let statfs = nix::sys::statfs::fstatfs(&tmp).unwrap(); - if statfs.filesystem_type() == nix::sys::statfs::OVERLAYFS_SUPER_MAGIC { - // OverlayFS is a union file system. It returns one inode value in - // stat(2), but a different one shows up in /proc/locks. So we must - // skip the test. - skip!("/proc/locks does not work on overlayfs"); - } - let inode = fstat(fd).expect("fstat failed").st_ino as usize; - - let mut flock: libc::flock = unsafe { - mem::zeroed() // required for Linux/mips - }; - flock.l_type = libc::F_RDLCK as libc::c_short; - flock.l_whence = libc::SEEK_SET as libc::c_short; - flock.l_start = 0; - flock.l_len = 0; - flock.l_pid = 0; - fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read lock failed"); - assert_eq!( - Some(("OFDLCK".to_string(), "READ".to_string())), - lock_info(inode) - ); - - flock.l_type = libc::F_UNLCK as libc::c_short; - fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read unlock failed"); - assert_eq!(None, lock_info(inode)); - } - - #[cfg(all(target_os = "linux", not(target_env = "musl")))] - fn lock_info(inode: usize) -> Option<(String, String)> { - use std::{ - fs::File, - io::BufReader - }; - - let file = File::open("/proc/locks").expect("open /proc/locks failed"); - let buf = BufReader::new(file); - - for line in buf.lines() { - let line = line.unwrap(); - let parts: Vec<_> = line.split_whitespace().collect(); - let lock_type = parts[1]; - let lock_access = parts[3]; - let ino_parts: Vec<_> = parts[5].split(':').collect(); - let ino: usize = ino_parts[2].parse().unwrap(); - if ino == inode { - return Some((lock_type.to_string(), lock_access.to_string())); - } - } - None - } -} - -#[cfg(any(target_os = "linux", - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia", - any(target_os = "wasi", target_env = "wasi"), - target_env = "uclibc", - target_os = "freebsd"))] -mod test_posix_fadvise { - - use tempfile::NamedTempFile; - use std::os::unix::io::{RawFd, AsRawFd}; - use nix::errno::Errno; - use nix::fcntl::*; - use nix::unistd::pipe; - - #[test] - fn test_success() { - let tmp = NamedTempFile::new().unwrap(); - let fd = tmp.as_raw_fd(); - let res = posix_fadvise(fd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED); - - assert!(res.is_ok()); - } - - #[test] - fn test_errno() { - let (rd, _wr) = pipe().unwrap(); - let res = posix_fadvise(rd as RawFd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED); - assert_eq!(res, Err(Errno::ESPIPE)); - } -} - -#[cfg(any(target_os = "linux", - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia", - any(target_os = "wasi", target_env = "wasi"), - target_os = "freebsd"))] -mod test_posix_fallocate { - - use tempfile::NamedTempFile; - use std::{io::Read, os::unix::io::{RawFd, AsRawFd}}; - use nix::errno::Errno; - use nix::fcntl::*; - use nix::unistd::pipe; - - #[test] - fn success() { - const LEN: usize = 100; - let mut tmp = NamedTempFile::new().unwrap(); - let fd = tmp.as_raw_fd(); - let res = posix_fallocate(fd, 0, LEN as libc::off_t); - match res { - Ok(_) => { - let mut data = [1u8; LEN]; - assert_eq!(tmp.read(&mut data).expect("read failure"), LEN); - assert_eq!(&data[..], &[0u8; LEN][..]); - } - Err(Errno::EINVAL) => { - // POSIX requires posix_fallocate to return EINVAL both for - // invalid arguments (i.e. len < 0) and if the operation is not - // supported by the file system. - // There's no way to tell for sure whether the file system - // supports posix_fallocate, so we must pass the test if it - // returns EINVAL. - } - _ => res.unwrap(), - } - } - - #[test] - fn errno() { - let (rd, _wr) = pipe().unwrap(); - let err = posix_fallocate(rd as RawFd, 0, 100).unwrap_err(); - match err { - Errno::EINVAL | Errno::ENODEV | Errno::ESPIPE | Errno::EBADF => (), - errno => - panic!( - "unexpected errno {}", - errno, - ), - } - } -} diff --git a/vendor/nix-v0.23.1-patched/test/test_kmod/hello_mod/Makefile b/vendor/nix-v0.23.1-patched/test/test_kmod/hello_mod/Makefile deleted file mode 100644 index 74c99b77e..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_kmod/hello_mod/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -obj-m += hello.o - -all: - make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules - -clean: - make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean diff --git a/vendor/nix-v0.23.1-patched/test/test_kmod/hello_mod/hello.c b/vendor/nix-v0.23.1-patched/test/test_kmod/hello_mod/hello.c deleted file mode 100644 index 1c34987d2..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_kmod/hello_mod/hello.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0+ or MIT - */ -#include -#include - -static int number= 1; -static char *who = "World"; - -module_param(number, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); -MODULE_PARM_DESC(myint, "Just some number"); -module_param(who, charp, 0000); -MODULE_PARM_DESC(who, "Whot to greet"); - -int init_module(void) -{ - printk(KERN_INFO "Hello %s (%d)!\n", who, number); - return 0; -} - -void cleanup_module(void) -{ - printk(KERN_INFO "Goodbye %s (%d)!\n", who, number); -} - -MODULE_LICENSE("Dual MIT/GPL"); diff --git a/vendor/nix-v0.23.1-patched/test/test_kmod/mod.rs b/vendor/nix-v0.23.1-patched/test/test_kmod/mod.rs deleted file mode 100644 index 0f7fc48e2..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_kmod/mod.rs +++ /dev/null @@ -1,166 +0,0 @@ -use std::fs::copy; -use std::path::PathBuf; -use std::process::Command; -use tempfile::{tempdir, TempDir}; -use crate::*; - -fn compile_kernel_module() -> (PathBuf, String, TempDir) { - let _m = crate::FORK_MTX - .lock() - .expect("Mutex got poisoned by another test"); - - let tmp_dir = tempdir().expect("unable to create temporary build directory"); - - copy( - "test/test_kmod/hello_mod/hello.c", - &tmp_dir.path().join("hello.c"), - ).expect("unable to copy hello.c to temporary build directory"); - copy( - "test/test_kmod/hello_mod/Makefile", - &tmp_dir.path().join("Makefile"), - ).expect("unable to copy Makefile to temporary build directory"); - - let status = Command::new("make") - .current_dir(tmp_dir.path()) - .status() - .expect("failed to run make"); - - assert!(status.success()); - - // Return the relative path of the build kernel module - (tmp_dir.path().join("hello.ko"), "hello".to_owned(), tmp_dir) -} - -use nix::errno::Errno; -use nix::kmod::{delete_module, DeleteModuleFlags}; -use nix::kmod::{finit_module, init_module, ModuleInitFlags}; -use std::ffi::CString; -use std::fs::File; -use std::io::Read; - -#[test] -fn test_finit_and_delete_module() { - require_capability!("test_finit_and_delete_module", CAP_SYS_MODULE); - let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test"); - let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test"); - - let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module(); - - let f = File::open(kmod_path).expect("unable to open kernel module"); - finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()) - .expect("unable to load kernel module"); - - delete_module( - &CString::new(kmod_name).unwrap(), - DeleteModuleFlags::empty(), - ).expect("unable to unload kernel module"); -} - -#[test] -fn test_finit_and_delete_module_with_params() { - require_capability!("test_finit_and_delete_module_with_params", CAP_SYS_MODULE); - let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test"); - let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test"); - - let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module(); - - let f = File::open(kmod_path).expect("unable to open kernel module"); - finit_module( - &f, - &CString::new("who=Rust number=2018").unwrap(), - ModuleInitFlags::empty(), - ).expect("unable to load kernel module"); - - delete_module( - &CString::new(kmod_name).unwrap(), - DeleteModuleFlags::empty(), - ).expect("unable to unload kernel module"); -} - -#[test] -fn test_init_and_delete_module() { - require_capability!("test_init_and_delete_module", CAP_SYS_MODULE); - let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test"); - let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test"); - - let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module(); - - let mut f = File::open(kmod_path).expect("unable to open kernel module"); - let mut contents: Vec = Vec::new(); - f.read_to_end(&mut contents) - .expect("unable to read kernel module content to buffer"); - init_module(&contents, &CString::new("").unwrap()).expect("unable to load kernel module"); - - delete_module( - &CString::new(kmod_name).unwrap(), - DeleteModuleFlags::empty(), - ).expect("unable to unload kernel module"); -} - -#[test] -fn test_init_and_delete_module_with_params() { - require_capability!("test_init_and_delete_module_with_params", CAP_SYS_MODULE); - let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test"); - let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test"); - - let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module(); - - let mut f = File::open(kmod_path).expect("unable to open kernel module"); - let mut contents: Vec = Vec::new(); - f.read_to_end(&mut contents) - .expect("unable to read kernel module content to buffer"); - init_module(&contents, &CString::new("who=Nix number=2015").unwrap()) - .expect("unable to load kernel module"); - - delete_module( - &CString::new(kmod_name).unwrap(), - DeleteModuleFlags::empty(), - ).expect("unable to unload kernel module"); -} - -#[test] -fn test_finit_module_invalid() { - require_capability!("test_finit_module_invalid", CAP_SYS_MODULE); - let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test"); - let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test"); - - let kmod_path = "/dev/zero"; - - let f = File::open(kmod_path).expect("unable to open kernel module"); - let result = finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()); - - assert_eq!(result.unwrap_err(), Errno::EINVAL); -} - -#[test] -fn test_finit_module_twice_and_delete_module() { - require_capability!("test_finit_module_twice_and_delete_module", CAP_SYS_MODULE); - let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test"); - let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test"); - - let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module(); - - let f = File::open(kmod_path).expect("unable to open kernel module"); - finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()) - .expect("unable to load kernel module"); - - let result = finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()); - - assert_eq!(result.unwrap_err(), Errno::EEXIST); - - delete_module( - &CString::new(kmod_name).unwrap(), - DeleteModuleFlags::empty(), - ).expect("unable to unload kernel module"); -} - -#[test] -fn test_delete_module_not_loaded() { - require_capability!("test_delete_module_not_loaded", CAP_SYS_MODULE); - let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test"); - let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test"); - - let result = delete_module(&CString::new("hello").unwrap(), DeleteModuleFlags::empty()); - - assert_eq!(result.unwrap_err(), Errno::ENOENT); -} diff --git a/vendor/nix-v0.23.1-patched/test/test_mount.rs b/vendor/nix-v0.23.1-patched/test/test_mount.rs deleted file mode 100644 index 44287f975..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_mount.rs +++ /dev/null @@ -1,236 +0,0 @@ -mod common; - -// Impelmentation note: to allow unprivileged users to run it, this test makes -// use of user and mount namespaces. On systems that allow unprivileged user -// namespaces (Linux >= 3.8 compiled with CONFIG_USER_NS), the test should run -// without root. - -#[cfg(target_os = "linux")] -mod test_mount { - use std::fs::{self, File}; - use std::io::{self, Read, Write}; - use std::os::unix::fs::OpenOptionsExt; - use std::os::unix::fs::PermissionsExt; - use std::process::{self, Command}; - - use libc::{EACCES, EROFS}; - - use nix::errno::Errno; - use nix::mount::{mount, umount, MsFlags}; - use nix::sched::{unshare, CloneFlags}; - use nix::sys::stat::{self, Mode}; - use nix::unistd::getuid; - - static SCRIPT_CONTENTS: &[u8] = b"#!/bin/sh -exit 23"; - - const EXPECTED_STATUS: i32 = 23; - - const NONE: Option<&'static [u8]> = None; - #[allow(clippy::bind_instead_of_map)] // False positive - pub fn test_mount_tmpfs_without_flags_allows_rwx() { - let tempdir = tempfile::tempdir().unwrap(); - - mount(NONE, - tempdir.path(), - Some(b"tmpfs".as_ref()), - MsFlags::empty(), - NONE) - .unwrap_or_else(|e| panic!("mount failed: {}", e)); - - let test_path = tempdir.path().join("test"); - - // Verify write. - fs::OpenOptions::new() - .create(true) - .write(true) - .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits()) - .open(&test_path) - .or_else(|e| - if Errno::from_i32(e.raw_os_error().unwrap()) == Errno::EOVERFLOW { - // Skip tests on certain Linux kernels which have a bug - // regarding tmpfs in namespaces. - // Ubuntu 14.04 and 16.04 are known to be affected; 16.10 is - // not. There is no legitimate reason for open(2) to return - // EOVERFLOW here. - // https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1659087 - let stderr = io::stderr(); - let mut handle = stderr.lock(); - writeln!(handle, "Buggy Linux kernel detected. Skipping test.") - .unwrap(); - process::exit(0); - } else { - panic!("open failed: {}", e); - } - ) - .and_then(|mut f| f.write(SCRIPT_CONTENTS)) - .unwrap_or_else(|e| panic!("write failed: {}", e)); - - // Verify read. - let mut buf = Vec::new(); - File::open(&test_path) - .and_then(|mut f| f.read_to_end(&mut buf)) - .unwrap_or_else(|e| panic!("read failed: {}", e)); - assert_eq!(buf, SCRIPT_CONTENTS); - - // Verify execute. - assert_eq!(EXPECTED_STATUS, - Command::new(&test_path) - .status() - .unwrap_or_else(|e| panic!("exec failed: {}", e)) - .code() - .unwrap_or_else(|| panic!("child killed by signal"))); - - umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e)); - } - - pub fn test_mount_rdonly_disallows_write() { - let tempdir = tempfile::tempdir().unwrap(); - - mount(NONE, - tempdir.path(), - Some(b"tmpfs".as_ref()), - MsFlags::MS_RDONLY, - NONE) - .unwrap_or_else(|e| panic!("mount failed: {}", e)); - - // EROFS: Read-only file system - assert_eq!(EROFS as i32, - File::create(tempdir.path().join("test")).unwrap_err().raw_os_error().unwrap()); - - umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e)); - } - - pub fn test_mount_noexec_disallows_exec() { - let tempdir = tempfile::tempdir().unwrap(); - - mount(NONE, - tempdir.path(), - Some(b"tmpfs".as_ref()), - MsFlags::MS_NOEXEC, - NONE) - .unwrap_or_else(|e| panic!("mount failed: {}", e)); - - let test_path = tempdir.path().join("test"); - - fs::OpenOptions::new() - .create(true) - .write(true) - .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits()) - .open(&test_path) - .and_then(|mut f| f.write(SCRIPT_CONTENTS)) - .unwrap_or_else(|e| panic!("write failed: {}", e)); - - // Verify that we cannot execute despite a+x permissions being set. - let mode = stat::Mode::from_bits_truncate(fs::metadata(&test_path) - .map(|md| md.permissions().mode()) - .unwrap_or_else(|e| { - panic!("metadata failed: {}", e) - })); - - assert!(mode.contains(Mode::S_IXUSR | Mode::S_IXGRP | Mode::S_IXOTH), - "{:?} did not have execute permissions", - &test_path); - - // EACCES: Permission denied - assert_eq!(EACCES as i32, - Command::new(&test_path).status().unwrap_err().raw_os_error().unwrap()); - - umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e)); - } - - pub fn test_mount_bind() { - let tempdir = tempfile::tempdir().unwrap(); - let file_name = "test"; - - { - let mount_point = tempfile::tempdir().unwrap(); - - mount(Some(tempdir.path()), - mount_point.path(), - NONE, - MsFlags::MS_BIND, - NONE) - .unwrap_or_else(|e| panic!("mount failed: {}", e)); - - fs::OpenOptions::new() - .create(true) - .write(true) - .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits()) - .open(mount_point.path().join(file_name)) - .and_then(|mut f| f.write(SCRIPT_CONTENTS)) - .unwrap_or_else(|e| panic!("write failed: {}", e)); - - umount(mount_point.path()).unwrap_or_else(|e| panic!("umount failed: {}", e)); - } - - // Verify the file written in the mount shows up in source directory, even - // after unmounting. - - let mut buf = Vec::new(); - File::open(tempdir.path().join(file_name)) - .and_then(|mut f| f.read_to_end(&mut buf)) - .unwrap_or_else(|e| panic!("read failed: {}", e)); - assert_eq!(buf, SCRIPT_CONTENTS); - } - - pub fn setup_namespaces() { - // Hold on to the uid in the parent namespace. - let uid = getuid(); - - unshare(CloneFlags::CLONE_NEWNS | CloneFlags::CLONE_NEWUSER).unwrap_or_else(|e| { - let stderr = io::stderr(); - let mut handle = stderr.lock(); - writeln!(handle, - "unshare failed: {}. Are unprivileged user namespaces available?", - e).unwrap(); - writeln!(handle, "mount is not being tested").unwrap(); - // Exit with success because not all systems support unprivileged user namespaces, and - // that's not what we're testing for. - process::exit(0); - }); - - // Map user as uid 1000. - fs::OpenOptions::new() - .write(true) - .open("/proc/self/uid_map") - .and_then(|mut f| f.write(format!("1000 {} 1\n", uid).as_bytes())) - .unwrap_or_else(|e| panic!("could not write uid map: {}", e)); - } -} - - -// Test runner - -/// Mimic normal test output (hackishly). -#[cfg(target_os = "linux")] -macro_rules! run_tests { - ( $($test_fn:ident),* ) => {{ - println!(); - - $( - print!("test test_mount::{} ... ", stringify!($test_fn)); - $test_fn(); - println!("ok"); - )* - - println!(); - }} -} - -#[cfg(target_os = "linux")] -fn main() { - use test_mount::{setup_namespaces, test_mount_tmpfs_without_flags_allows_rwx, - test_mount_rdonly_disallows_write, test_mount_noexec_disallows_exec, - test_mount_bind}; - skip_if_cirrus!("Fails for an unknown reason Cirrus CI. Bug #1351"); - setup_namespaces(); - - run_tests!(test_mount_tmpfs_without_flags_allows_rwx, - test_mount_rdonly_disallows_write, - test_mount_noexec_disallows_exec, - test_mount_bind); -} - -#[cfg(not(target_os = "linux"))] -fn main() {} diff --git a/vendor/nix-v0.23.1-patched/test/test_mq.rs b/vendor/nix-v0.23.1-patched/test/test_mq.rs deleted file mode 100644 index 430df5ddc..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_mq.rs +++ /dev/null @@ -1,157 +0,0 @@ -use std::ffi::CString; -use std::str; - -use nix::errno::Errno; -use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive, mq_attr_member_t}; -use nix::mqueue::{MqAttr, MQ_OFlag}; -use nix::sys::stat::Mode; - -#[test] -fn test_mq_send_and_receive() { - const MSG_SIZE: mq_attr_member_t = 32; - let attr = MqAttr::new(0, 10, MSG_SIZE, 0); - let mq_name= &CString::new(b"/a_nix_test_queue".as_ref()).unwrap(); - - let oflag0 = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY; - let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH; - let r0 = mq_open(mq_name, oflag0, mode, Some(&attr)); - if let Err(Errno::ENOSYS) = r0 { - println!("message queues not supported or module not loaded?"); - return; - }; - let mqd0 = r0.unwrap(); - let msg_to_send = "msg_1"; - mq_send(mqd0, msg_to_send.as_bytes(), 1).unwrap(); - - let oflag1 = MQ_OFlag::O_CREAT | MQ_OFlag::O_RDONLY; - let mqd1 = mq_open(mq_name, oflag1, mode, Some(&attr)).unwrap(); - let mut buf = [0u8; 32]; - let mut prio = 0u32; - let len = mq_receive(mqd1, &mut buf, &mut prio).unwrap(); - assert_eq!(prio, 1); - - mq_close(mqd1).unwrap(); - mq_close(mqd0).unwrap(); - assert_eq!(msg_to_send, str::from_utf8(&buf[0..len]).unwrap()); -} - - -#[test] -#[cfg(not(any(target_os = "netbsd")))] -fn test_mq_getattr() { - use nix::mqueue::mq_getattr; - const MSG_SIZE: mq_attr_member_t = 32; - let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); - let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap(); - let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY; - let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH; - let r = mq_open(mq_name, oflag, mode, Some(&initial_attr)); - if let Err(Errno::ENOSYS) = r { - println!("message queues not supported or module not loaded?"); - return; - }; - let mqd = r.unwrap(); - - let read_attr = mq_getattr(mqd).unwrap(); - assert_eq!(read_attr, initial_attr); - mq_close(mqd).unwrap(); -} - -// FIXME: Fix failures for mips in QEMU -#[test] -#[cfg(not(any(target_os = "netbsd")))] -#[cfg_attr(all( - qemu, - any(target_arch = "mips", target_arch = "mips64") - ), ignore -)] -fn test_mq_setattr() { - use nix::mqueue::{mq_getattr, mq_setattr}; - const MSG_SIZE: mq_attr_member_t = 32; - let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); - let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap(); - let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY; - let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH; - let r = mq_open(mq_name, oflag, mode, Some(&initial_attr)); - if let Err(Errno::ENOSYS) = r { - println!("message queues not supported or module not loaded?"); - return; - }; - let mqd = r.unwrap(); - - let new_attr = MqAttr::new(0, 20, MSG_SIZE * 2, 100); - let old_attr = mq_setattr(mqd, &new_attr).unwrap(); - assert_eq!(old_attr, initial_attr); - - let new_attr_get = mq_getattr(mqd).unwrap(); - // The following tests make sense. No changes here because according to the Linux man page only - // O_NONBLOCK can be set (see tests below) - assert_ne!(new_attr_get, new_attr); - - let new_attr_non_blocking = MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as mq_attr_member_t, 10, MSG_SIZE, 0); - mq_setattr(mqd, &new_attr_non_blocking).unwrap(); - let new_attr_get = mq_getattr(mqd).unwrap(); - - // now the O_NONBLOCK flag has been set - assert_ne!(new_attr_get, initial_attr); - assert_eq!(new_attr_get, new_attr_non_blocking); - mq_close(mqd).unwrap(); -} - -// FIXME: Fix failures for mips in QEMU -#[test] -#[cfg(not(any(target_os = "netbsd")))] -#[cfg_attr(all( - qemu, - any(target_arch = "mips", target_arch = "mips64") - ), ignore -)] -fn test_mq_set_nonblocking() { - use nix::mqueue::{mq_getattr, mq_set_nonblock, mq_remove_nonblock}; - const MSG_SIZE: mq_attr_member_t = 32; - let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); - let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap(); - let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY; - let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH; - let r = mq_open(mq_name, oflag, mode, Some(&initial_attr)); - if let Err(Errno::ENOSYS) = r { - println!("message queues not supported or module not loaded?"); - return; - }; - let mqd = r.unwrap(); - mq_set_nonblock(mqd).unwrap(); - let new_attr = mq_getattr(mqd); - assert_eq!(new_attr.unwrap().flags(), MQ_OFlag::O_NONBLOCK.bits() as mq_attr_member_t); - mq_remove_nonblock(mqd).unwrap(); - let new_attr = mq_getattr(mqd); - assert_eq!(new_attr.unwrap().flags(), 0); - mq_close(mqd).unwrap(); -} - -#[test] -#[cfg(not(any(target_os = "netbsd")))] -fn test_mq_unlink() { - use nix::mqueue::mq_unlink; - const MSG_SIZE: mq_attr_member_t = 32; - let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); - let mq_name_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap(); - let mq_name_not_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap(); - let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY; - let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH; - let r = mq_open(mq_name_opened, oflag, mode, Some(&initial_attr)); - if let Err(Errno::ENOSYS) = r { - println!("message queues not supported or module not loaded?"); - return; - }; - let mqd = r.unwrap(); - - let res_unlink = mq_unlink(mq_name_opened); - assert_eq!(res_unlink, Ok(()) ); - - let res_unlink_not_opened = mq_unlink(mq_name_not_opened); - assert_eq!(res_unlink_not_opened, Err(Errno::ENOENT) ); - - mq_close(mqd).unwrap(); - let res_unlink_after_close = mq_unlink(mq_name_opened); - assert_eq!(res_unlink_after_close, Err(Errno::ENOENT) ); -} diff --git a/vendor/nix-v0.23.1-patched/test/test_net.rs b/vendor/nix-v0.23.1-patched/test/test_net.rs deleted file mode 100644 index 40ecd6bb7..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_net.rs +++ /dev/null @@ -1,12 +0,0 @@ -use nix::net::if_::*; - -#[cfg(any(target_os = "android", target_os = "linux"))] -const LOOPBACK: &[u8] = b"lo"; - -#[cfg(not(any(target_os = "android", target_os = "linux")))] -const LOOPBACK: &[u8] = b"lo0"; - -#[test] -fn test_if_nametoindex() { - assert!(if_nametoindex(LOOPBACK).is_ok()); -} diff --git a/vendor/nix-v0.23.1-patched/test/test_nix_path.rs b/vendor/nix-v0.23.1-patched/test/test_nix_path.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/nix-v0.23.1-patched/test/test_nmount.rs b/vendor/nix-v0.23.1-patched/test/test_nmount.rs deleted file mode 100644 index 4c74ecf62..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_nmount.rs +++ /dev/null @@ -1,51 +0,0 @@ -use crate::*; -use nix::{ - errno::Errno, - mount::{MntFlags, Nmount, unmount} -}; -use std::{ - ffi::CString, - fs::File, - path::Path -}; -use tempfile::tempdir; - -#[test] -fn ok() { - require_mount!("nullfs"); - - let mountpoint = tempdir().unwrap(); - let target = tempdir().unwrap(); - let _sentry = File::create(target.path().join("sentry")).unwrap(); - - let fstype = CString::new("fstype").unwrap(); - let nullfs = CString::new("nullfs").unwrap(); - Nmount::new() - .str_opt(&fstype, &nullfs) - .str_opt_owned("fspath", mountpoint.path().to_str().unwrap()) - .str_opt_owned("target", target.path().to_str().unwrap()) - .nmount(MntFlags::empty()).unwrap(); - - // Now check that the sentry is visible through the mountpoint - let exists = Path::exists(&mountpoint.path().join("sentry")); - - // Cleanup the mountpoint before asserting - unmount(mountpoint.path(), MntFlags::empty()).unwrap(); - - assert!(exists); -} - -#[test] -fn bad_fstype() { - let mountpoint = tempdir().unwrap(); - let target = tempdir().unwrap(); - let _sentry = File::create(target.path().join("sentry")).unwrap(); - - let e = Nmount::new() - .str_opt_owned("fspath", mountpoint.path().to_str().unwrap()) - .str_opt_owned("target", target.path().to_str().unwrap()) - .nmount(MntFlags::empty()).unwrap_err(); - - assert_eq!(e.error(), Errno::EINVAL); - assert_eq!(e.errmsg(), Some("Invalid fstype")); -} diff --git a/vendor/nix-v0.23.1-patched/test/test_poll.rs b/vendor/nix-v0.23.1-patched/test/test_poll.rs deleted file mode 100644 index e4b369f3f..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_poll.rs +++ /dev/null @@ -1,82 +0,0 @@ -use nix::{ - errno::Errno, - poll::{PollFlags, poll, PollFd}, - unistd::{write, pipe} -}; - -macro_rules! loop_while_eintr { - ($poll_expr: expr) => { - loop { - match $poll_expr { - Ok(nfds) => break nfds, - Err(Errno::EINTR) => (), - Err(e) => panic!("{}", e) - } - } - } -} - -#[test] -fn test_poll() { - let (r, w) = pipe().unwrap(); - let mut fds = [PollFd::new(r, PollFlags::POLLIN)]; - - // Poll an idle pipe. Should timeout - let nfds = loop_while_eintr!(poll(&mut fds, 100)); - assert_eq!(nfds, 0); - assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN)); - - write(w, b".").unwrap(); - - // Poll a readable pipe. Should return an event. - let nfds = poll(&mut fds, 100).unwrap(); - assert_eq!(nfds, 1); - assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN)); -} - -// ppoll(2) is the same as poll except for how it handles timeouts and signals. -// Repeating the test for poll(2) should be sufficient to check that our -// bindings are correct. -#[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux"))] -#[test] -fn test_ppoll() { - use nix::poll::ppoll; - use nix::sys::signal::SigSet; - use nix::sys::time::{TimeSpec, TimeValLike}; - - let timeout = TimeSpec::milliseconds(1); - let (r, w) = pipe().unwrap(); - let mut fds = [PollFd::new(r, PollFlags::POLLIN)]; - - // Poll an idle pipe. Should timeout - let sigset = SigSet::empty(); - let nfds = loop_while_eintr!(ppoll(&mut fds, Some(timeout), sigset)); - assert_eq!(nfds, 0); - assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN)); - - write(w, b".").unwrap(); - - // Poll a readable pipe. Should return an event. - let nfds = ppoll(&mut fds, Some(timeout), SigSet::empty()).unwrap(); - assert_eq!(nfds, 1); - assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN)); -} - -#[test] -fn test_pollfd_fd() { - use std::os::unix::io::AsRawFd; - - let pfd = PollFd::new(0x1234, PollFlags::empty()); - assert_eq!(pfd.as_raw_fd(), 0x1234); -} - -#[test] -fn test_pollfd_events() { - let mut pfd = PollFd::new(-1, PollFlags::POLLIN); - assert_eq!(pfd.events(), PollFlags::POLLIN); - pfd.set_events(PollFlags::POLLOUT); - assert_eq!(pfd.events(), PollFlags::POLLOUT); -} diff --git a/vendor/nix-v0.23.1-patched/test/test_pty.rs b/vendor/nix-v0.23.1-patched/test/test_pty.rs deleted file mode 100644 index 57874de3d..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_pty.rs +++ /dev/null @@ -1,301 +0,0 @@ -use std::fs::File; -use std::io::{Read, Write}; -use std::path::Path; -use std::os::unix::prelude::*; -use tempfile::tempfile; - -use libc::{_exit, STDOUT_FILENO}; -use nix::fcntl::{OFlag, open}; -use nix::pty::*; -use nix::sys::stat; -use nix::sys::termios::*; -use nix::unistd::{write, close, pause}; - -/// Regression test for Issue #659 -/// This is the correct way to explicitly close a `PtyMaster` -#[test] -fn test_explicit_close() { - let mut f = { - let m = posix_openpt(OFlag::O_RDWR).unwrap(); - close(m.into_raw_fd()).unwrap(); - tempfile().unwrap() - }; - // This should work. But if there's been a double close, then it will - // return EBADF - f.write_all(b"whatever").unwrap(); -} - -/// Test equivalence of `ptsname` and `ptsname_r` -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptsname_equivalence() { - let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test"); - - // Open a new PTTY master - let master_fd = posix_openpt(OFlag::O_RDWR).unwrap(); - assert!(master_fd.as_raw_fd() > 0); - - // Get the name of the slave - let slave_name = unsafe { ptsname(&master_fd) }.unwrap() ; - let slave_name_r = ptsname_r(&master_fd).unwrap(); - assert_eq!(slave_name, slave_name_r); -} - -/// Test data copying of `ptsname` -// TODO need to run in a subprocess, since ptsname is non-reentrant -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptsname_copy() { - let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test"); - - // Open a new PTTY master - let master_fd = posix_openpt(OFlag::O_RDWR).unwrap(); - assert!(master_fd.as_raw_fd() > 0); - - // Get the name of the slave - let slave_name1 = unsafe { ptsname(&master_fd) }.unwrap(); - let slave_name2 = unsafe { ptsname(&master_fd) }.unwrap(); - assert_eq!(slave_name1, slave_name2); - // Also make sure that the string was actually copied and they point to different parts of - // memory. - assert!(slave_name1.as_ptr() != slave_name2.as_ptr()); -} - -/// Test data copying of `ptsname_r` -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptsname_r_copy() { - // Open a new PTTY master - let master_fd = posix_openpt(OFlag::O_RDWR).unwrap(); - assert!(master_fd.as_raw_fd() > 0); - - // Get the name of the slave - let slave_name1 = ptsname_r(&master_fd).unwrap(); - let slave_name2 = ptsname_r(&master_fd).unwrap(); - assert_eq!(slave_name1, slave_name2); - assert!(slave_name1.as_ptr() != slave_name2.as_ptr()); -} - -/// Test that `ptsname` returns different names for different devices -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptsname_unique() { - let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test"); - - // Open a new PTTY master - let master1_fd = posix_openpt(OFlag::O_RDWR).unwrap(); - assert!(master1_fd.as_raw_fd() > 0); - - // Open a second PTTY master - let master2_fd = posix_openpt(OFlag::O_RDWR).unwrap(); - assert!(master2_fd.as_raw_fd() > 0); - - // Get the name of the slave - let slave_name1 = unsafe { ptsname(&master1_fd) }.unwrap(); - let slave_name2 = unsafe { ptsname(&master2_fd) }.unwrap(); - assert!(slave_name1 != slave_name2); -} - -/// Common setup for testing PTTY pairs -fn open_ptty_pair() -> (PtyMaster, File) { - let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test"); - - // Open a new PTTY master - let master = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed"); - - // Allow a slave to be generated for it - grantpt(&master).expect("grantpt failed"); - unlockpt(&master).expect("unlockpt failed"); - - // Get the name of the slave - let slave_name = unsafe { ptsname(&master) }.expect("ptsname failed"); - - // Open the slave device - let slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, stat::Mode::empty()).unwrap(); - - #[cfg(target_os = "illumos")] - // TODO: rewrite using ioctl! - #[allow(clippy::comparison_chain)] - { - use libc::{ioctl, I_FIND, I_PUSH}; - - // On illumos systems, as per pts(7D), one must push STREAMS modules - // after opening a device path returned from ptsname(). - let ptem = b"ptem\0"; - let ldterm = b"ldterm\0"; - let r = unsafe { ioctl(slave_fd, I_FIND, ldterm.as_ptr()) }; - if r < 0 { - panic!("I_FIND failure"); - } else if r == 0 { - if unsafe { ioctl(slave_fd, I_PUSH, ptem.as_ptr()) } < 0 { - panic!("I_PUSH ptem failure"); - } - if unsafe { ioctl(slave_fd, I_PUSH, ldterm.as_ptr()) } < 0 { - panic!("I_PUSH ldterm failure"); - } - } - } - - let slave = unsafe { File::from_raw_fd(slave_fd) }; - - (master, slave) -} - -/// Test opening a master/slave PTTY pair -/// -/// This uses a common `open_ptty_pair` because much of these functions aren't useful by -/// themselves. So for this test we perform the basic act of getting a file handle for a -/// master/slave PTTY pair, then just sanity-check the raw values. -#[test] -fn test_open_ptty_pair() { - let (master, slave) = open_ptty_pair(); - assert!(master.as_raw_fd() > 0); - assert!(slave.as_raw_fd() > 0); -} - -/// Put the terminal in raw mode. -fn make_raw(fd: RawFd) { - let mut termios = tcgetattr(fd).unwrap(); - cfmakeraw(&mut termios); - tcsetattr(fd, SetArg::TCSANOW, &termios).unwrap(); -} - -/// Test `io::Read` on the PTTY master -#[test] -fn test_read_ptty_pair() { - let (mut master, mut slave) = open_ptty_pair(); - make_raw(slave.as_raw_fd()); - - let mut buf = [0u8; 5]; - slave.write_all(b"hello").unwrap(); - master.read_exact(&mut buf).unwrap(); - assert_eq!(&buf, b"hello"); -} - -/// Test `io::Write` on the PTTY master -#[test] -fn test_write_ptty_pair() { - let (mut master, mut slave) = open_ptty_pair(); - make_raw(slave.as_raw_fd()); - - let mut buf = [0u8; 5]; - master.write_all(b"adios").unwrap(); - slave.read_exact(&mut buf).unwrap(); - assert_eq!(&buf, b"adios"); -} - -#[test] -fn test_openpty() { - // openpty uses ptname(3) internally - let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test"); - - let pty = openpty(None, None).unwrap(); - assert!(pty.master > 0); - assert!(pty.slave > 0); - - // Writing to one should be readable on the other one - let string = "foofoofoo\n"; - let mut buf = [0u8; 10]; - write(pty.master, string.as_bytes()).unwrap(); - crate::read_exact(pty.slave, &mut buf); - - assert_eq!(&buf, string.as_bytes()); - - // Read the echo as well - let echoed_string = "foofoofoo\r\n"; - let mut buf = [0u8; 11]; - crate::read_exact(pty.master, &mut buf); - assert_eq!(&buf, echoed_string.as_bytes()); - - let string2 = "barbarbarbar\n"; - let echoed_string2 = "barbarbarbar\r\n"; - let mut buf = [0u8; 14]; - write(pty.slave, string2.as_bytes()).unwrap(); - crate::read_exact(pty.master, &mut buf); - - assert_eq!(&buf, echoed_string2.as_bytes()); - - close(pty.master).unwrap(); - close(pty.slave).unwrap(); -} - -#[test] -fn test_openpty_with_termios() { - // openpty uses ptname(3) internally - let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test"); - - // Open one pty to get attributes for the second one - let mut termios = { - let pty = openpty(None, None).unwrap(); - assert!(pty.master > 0); - assert!(pty.slave > 0); - let termios = tcgetattr(pty.slave).unwrap(); - close(pty.master).unwrap(); - close(pty.slave).unwrap(); - termios - }; - // Make sure newlines are not transformed so the data is preserved when sent. - termios.output_flags.remove(OutputFlags::ONLCR); - - let pty = openpty(None, &termios).unwrap(); - // Must be valid file descriptors - assert!(pty.master > 0); - assert!(pty.slave > 0); - - // Writing to one should be readable on the other one - let string = "foofoofoo\n"; - let mut buf = [0u8; 10]; - write(pty.master, string.as_bytes()).unwrap(); - crate::read_exact(pty.slave, &mut buf); - - assert_eq!(&buf, string.as_bytes()); - - // read the echo as well - let echoed_string = "foofoofoo\n"; - crate::read_exact(pty.master, &mut buf); - assert_eq!(&buf, echoed_string.as_bytes()); - - let string2 = "barbarbarbar\n"; - let echoed_string2 = "barbarbarbar\n"; - let mut buf = [0u8; 13]; - write(pty.slave, string2.as_bytes()).unwrap(); - crate::read_exact(pty.master, &mut buf); - - assert_eq!(&buf, echoed_string2.as_bytes()); - - close(pty.master).unwrap(); - close(pty.slave).unwrap(); -} - -#[test] -fn test_forkpty() { - use nix::unistd::ForkResult::*; - use nix::sys::signal::*; - use nix::sys::wait::wait; - // forkpty calls openpty which uses ptname(3) internally. - let _m0 = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test"); - // forkpty spawns a child process - let _m1 = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test"); - - let string = "naninani\n"; - let echoed_string = "naninani\r\n"; - let pty = unsafe { - forkpty(None, None).unwrap() - }; - match pty.fork_result { - Child => { - write(STDOUT_FILENO, string.as_bytes()).unwrap(); - pause(); // we need the child to stay alive until the parent calls read - unsafe { _exit(0); } - }, - Parent { child } => { - let mut buf = [0u8; 10]; - assert!(child.as_raw() > 0); - crate::read_exact(pty.master, &mut buf); - kill(child, SIGTERM).unwrap(); - wait().unwrap(); // keep other tests using generic wait from getting our child - assert_eq!(&buf, echoed_string.as_bytes()); - close(pty.master).unwrap(); - }, - } -} diff --git a/vendor/nix-v0.23.1-patched/test/test_ptymaster_drop.rs b/vendor/nix-v0.23.1-patched/test/test_ptymaster_drop.rs deleted file mode 100644 index a68f81ee1..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_ptymaster_drop.rs +++ /dev/null @@ -1,20 +0,0 @@ -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -mod t { - use nix::fcntl::OFlag; - use nix::pty::*; - use nix::unistd::close; - use std::os::unix::io::AsRawFd; - - /// Regression test for Issue #659 - /// - /// `PtyMaster` should panic rather than double close the file descriptor - /// This must run in its own test process because it deliberately creates a - /// race condition. - #[test] - #[should_panic(expected = "Closing an invalid file descriptor!")] - fn test_double_close() { - let m = posix_openpt(OFlag::O_RDWR).unwrap(); - close(m.as_raw_fd()).unwrap(); - drop(m); // should panic here - } -} diff --git a/vendor/nix-v0.23.1-patched/test/test_resource.rs b/vendor/nix-v0.23.1-patched/test/test_resource.rs deleted file mode 100644 index 596975009..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_resource.rs +++ /dev/null @@ -1,23 +0,0 @@ -#[cfg(not(any(target_os = "redox", target_os = "fuchsia", target_os = "illumos")))] -use nix::sys::resource::{getrlimit, setrlimit, Resource}; - -/// Tests the RLIMIT_NOFILE functionality of getrlimit(), where the resource RLIMIT_NOFILE refers -/// to the maximum file descriptor number that can be opened by the process (aka the maximum number -/// of file descriptors that the process can open, since Linux 4.5). -/// -/// We first fetch the existing file descriptor maximum values using getrlimit(), then edit the -/// soft limit to make sure it has a new and distinct value to the hard limit. We then setrlimit() -/// to put the new soft limit in effect, and then getrlimit() once more to ensure the limits have -/// been updated. -#[test] -#[cfg(not(any(target_os = "redox", target_os = "fuchsia", target_os = "illumos")))] -pub fn test_resource_limits_nofile() { - let (soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); - - let soft_limit = Some(soft_limit.map_or(1024, |v| v - 1)); - assert_ne!(soft_limit, hard_limit); - setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap(); - - let (new_soft_limit, _) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); - assert_eq!(new_soft_limit, soft_limit); -} diff --git a/vendor/nix-v0.23.1-patched/test/test_sched.rs b/vendor/nix-v0.23.1-patched/test/test_sched.rs deleted file mode 100644 index 922196a3d..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_sched.rs +++ /dev/null @@ -1,32 +0,0 @@ -use nix::sched::{sched_getaffinity, sched_setaffinity, CpuSet}; -use nix::unistd::Pid; - -#[test] -fn test_sched_affinity() { - // If pid is zero, then the mask of the calling process is returned. - let initial_affinity = sched_getaffinity(Pid::from_raw(0)).unwrap(); - let mut at_least_one_cpu = false; - let mut last_valid_cpu = 0; - for field in 0..CpuSet::count() { - if initial_affinity.is_set(field).unwrap() { - at_least_one_cpu = true; - last_valid_cpu = field; - } - } - assert!(at_least_one_cpu); - - // Now restrict the running CPU - let mut new_affinity = CpuSet::new(); - new_affinity.set(last_valid_cpu).unwrap(); - sched_setaffinity(Pid::from_raw(0), &new_affinity).unwrap(); - - // And now re-check the affinity which should be only the one we set. - let updated_affinity = sched_getaffinity(Pid::from_raw(0)).unwrap(); - for field in 0..CpuSet::count() { - // Should be set only for the CPU we set previously - assert_eq!(updated_affinity.is_set(field).unwrap(), field==last_valid_cpu) - } - - // Finally, reset the initial CPU set - sched_setaffinity(Pid::from_raw(0), &initial_affinity).unwrap(); -} diff --git a/vendor/nix-v0.23.1-patched/test/test_sendfile.rs b/vendor/nix-v0.23.1-patched/test/test_sendfile.rs deleted file mode 100644 index b6559d329..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_sendfile.rs +++ /dev/null @@ -1,151 +0,0 @@ -use std::io::prelude::*; -use std::os::unix::prelude::*; - -use libc::off_t; -use nix::sys::sendfile::*; -use tempfile::tempfile; - -cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { - use nix::unistd::{close, pipe, read}; - } else if #[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))] { - use std::net::Shutdown; - use std::os::unix::net::UnixStream; - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[test] -fn test_sendfile_linux() { - const CONTENTS: &[u8] = b"abcdef123456"; - let mut tmp = tempfile().unwrap(); - tmp.write_all(CONTENTS).unwrap(); - - let (rd, wr) = pipe().unwrap(); - let mut offset: off_t = 5; - let res = sendfile(wr, tmp.as_raw_fd(), Some(&mut offset), 2).unwrap(); - - assert_eq!(2, res); - - let mut buf = [0u8; 1024]; - assert_eq!(2, read(rd, &mut buf).unwrap()); - assert_eq!(b"f1", &buf[0..2]); - assert_eq!(7, offset); - - close(rd).unwrap(); - close(wr).unwrap(); -} - -#[cfg(target_os = "linux")] -#[test] -fn test_sendfile64_linux() { - const CONTENTS: &[u8] = b"abcdef123456"; - let mut tmp = tempfile().unwrap(); - tmp.write_all(CONTENTS).unwrap(); - - let (rd, wr) = pipe().unwrap(); - let mut offset: libc::off64_t = 5; - let res = sendfile64(wr, tmp.as_raw_fd(), Some(&mut offset), 2).unwrap(); - - assert_eq!(2, res); - - let mut buf = [0u8; 1024]; - assert_eq!(2, read(rd, &mut buf).unwrap()); - assert_eq!(b"f1", &buf[0..2]); - assert_eq!(7, offset); - - close(rd).unwrap(); - close(wr).unwrap(); -} - -#[cfg(target_os = "freebsd")] -#[test] -fn test_sendfile_freebsd() { - // Declare the content - let header_strings = vec!["HTTP/1.1 200 OK\n", "Content-Type: text/plain\n", "\n"]; - let body = "Xabcdef123456"; - let body_offset = 1; - let trailer_strings = vec!["\n", "Served by Make Believe\n"]; - - // Write the body to a file - let mut tmp = tempfile().unwrap(); - tmp.write_all(body.as_bytes()).unwrap(); - - // Prepare headers and trailers for sendfile - let headers: Vec<&[u8]> = header_strings.iter().map(|s| s.as_bytes()).collect(); - let trailers: Vec<&[u8]> = trailer_strings.iter().map(|s| s.as_bytes()).collect(); - - // Prepare socket pair - let (mut rd, wr) = UnixStream::pair().unwrap(); - - // Call the test method - let (res, bytes_written) = sendfile( - tmp.as_raw_fd(), - wr.as_raw_fd(), - body_offset as off_t, - None, - Some(headers.as_slice()), - Some(trailers.as_slice()), - SfFlags::empty(), - 0, - ); - assert!(res.is_ok()); - wr.shutdown(Shutdown::Both).unwrap(); - - // Prepare the expected result - let expected_string = - header_strings.concat() + &body[body_offset..] + &trailer_strings.concat(); - - // Verify the message that was sent - assert_eq!(bytes_written as usize, expected_string.as_bytes().len()); - - let mut read_string = String::new(); - let bytes_read = rd.read_to_string(&mut read_string).unwrap(); - assert_eq!(bytes_written as usize, bytes_read); - assert_eq!(expected_string, read_string); -} - -#[cfg(any(target_os = "ios", target_os = "macos"))] -#[test] -fn test_sendfile_darwin() { - // Declare the content - let header_strings = vec!["HTTP/1.1 200 OK\n", "Content-Type: text/plain\n", "\n"]; - let body = "Xabcdef123456"; - let body_offset = 1; - let trailer_strings = vec!["\n", "Served by Make Believe\n"]; - - // Write the body to a file - let mut tmp = tempfile().unwrap(); - tmp.write_all(body.as_bytes()).unwrap(); - - // Prepare headers and trailers for sendfile - let headers: Vec<&[u8]> = header_strings.iter().map(|s| s.as_bytes()).collect(); - let trailers: Vec<&[u8]> = trailer_strings.iter().map(|s| s.as_bytes()).collect(); - - // Prepare socket pair - let (mut rd, wr) = UnixStream::pair().unwrap(); - - // Call the test method - let (res, bytes_written) = sendfile( - tmp.as_raw_fd(), - wr.as_raw_fd(), - body_offset as off_t, - None, - Some(headers.as_slice()), - Some(trailers.as_slice()), - ); - assert!(res.is_ok()); - wr.shutdown(Shutdown::Both).unwrap(); - - // Prepare the expected result - let expected_string = - header_strings.concat() + &body[body_offset..] + &trailer_strings.concat(); - - // Verify the message that was sent - assert_eq!(bytes_written as usize, expected_string.as_bytes().len()); - - let mut read_string = String::new(); - let bytes_read = rd.read_to_string(&mut read_string).unwrap(); - assert_eq!(bytes_written as usize, bytes_read); - assert_eq!(expected_string, read_string); -} diff --git a/vendor/nix-v0.23.1-patched/test/test_stat.rs b/vendor/nix-v0.23.1-patched/test/test_stat.rs deleted file mode 100644 index 33cf748da..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_stat.rs +++ /dev/null @@ -1,358 +0,0 @@ -#[cfg(not(target_os = "redox"))] -use std::fs; -use std::fs::File; -#[cfg(not(target_os = "redox"))] -use std::os::unix::fs::{symlink, PermissionsExt}; -use std::os::unix::prelude::AsRawFd; -#[cfg(not(target_os = "redox"))] -use std::time::{Duration, UNIX_EPOCH}; -#[cfg(not(target_os = "redox"))] -use std::path::Path; - -#[cfg(not(any(target_os = "netbsd", target_os = "redox")))] -use libc::{S_IFMT, S_IFLNK}; -use libc::mode_t; - -#[cfg(not(target_os = "redox"))] -use nix::fcntl; -#[cfg(not(target_os = "redox"))] -use nix::errno::Errno; -#[cfg(not(target_os = "redox"))] -use nix::sys::stat::{self, futimens, utimes}; -use nix::sys::stat::{fchmod, stat}; -#[cfg(not(target_os = "redox"))] -use nix::sys::stat::{fchmodat, utimensat, mkdirat}; -#[cfg(any(target_os = "linux", - target_os = "haiku", - target_os = "ios", - target_os = "macos", - target_os = "freebsd", - target_os = "netbsd"))] -use nix::sys::stat::lutimes; -#[cfg(not(target_os = "redox"))] -use nix::sys::stat::{FchmodatFlags, UtimensatFlags}; -use nix::sys::stat::Mode; - -#[cfg(not(any(target_os = "netbsd", target_os = "redox")))] -use nix::sys::stat::FileStat; - -#[cfg(not(target_os = "redox"))] -use nix::sys::time::{TimeSpec, TimeVal, TimeValLike}; -#[cfg(not(target_os = "redox"))] -use nix::unistd::chdir; - -#[cfg(not(any(target_os = "netbsd", target_os = "redox")))] -use nix::Result; - -#[cfg(not(any(target_os = "netbsd", target_os = "redox")))] -fn assert_stat_results(stat_result: Result) { - let stats = stat_result.expect("stat call failed"); - assert!(stats.st_dev > 0); // must be positive integer, exact number machine dependent - assert!(stats.st_ino > 0); // inode is positive integer, exact number machine dependent - assert!(stats.st_mode > 0); // must be positive integer - assert_eq!(stats.st_nlink, 1); // there links created, must be 1 - assert_eq!(stats.st_size, 0); // size is 0 because we did not write anything to the file - assert!(stats.st_blksize > 0); // must be positive integer, exact number machine dependent - assert!(stats.st_blocks <= 16); // Up to 16 blocks can be allocated for a blank file -} - -#[cfg(not(any(target_os = "netbsd", target_os = "redox")))] -// (Android's st_blocks is ulonglong which is always non-negative.) -#[cfg_attr(target_os = "android", allow(unused_comparisons))] -#[allow(clippy::absurd_extreme_comparisons)] // Not absurd on all OSes -fn assert_lstat_results(stat_result: Result) { - let stats = stat_result.expect("stat call failed"); - assert!(stats.st_dev > 0); // must be positive integer, exact number machine dependent - assert!(stats.st_ino > 0); // inode is positive integer, exact number machine dependent - assert!(stats.st_mode > 0); // must be positive integer - - // st_mode is c_uint (u32 on Android) while S_IFMT is mode_t - // (u16 on Android), and that will be a compile error. - // On other platforms they are the same (either both are u16 or u32). - assert_eq!((stats.st_mode as usize) & (S_IFMT as usize), S_IFLNK as usize); // should be a link - assert_eq!(stats.st_nlink, 1); // there links created, must be 1 - assert!(stats.st_size > 0); // size is > 0 because it points to another file - assert!(stats.st_blksize > 0); // must be positive integer, exact number machine dependent - - // st_blocks depends on whether the machine's file system uses fast - // or slow symlinks, so just make sure it's not negative - assert!(stats.st_blocks >= 0); -} - -#[test] -#[cfg(not(any(target_os = "netbsd", target_os = "redox")))] -fn test_stat_and_fstat() { - use nix::sys::stat::fstat; - - let tempdir = tempfile::tempdir().unwrap(); - let filename = tempdir.path().join("foo.txt"); - let file = File::create(&filename).unwrap(); - - let stat_result = stat(&filename); - assert_stat_results(stat_result); - - let fstat_result = fstat(file.as_raw_fd()); - assert_stat_results(fstat_result); -} - -#[test] -#[cfg(not(any(target_os = "netbsd", target_os = "redox")))] -fn test_fstatat() { - let tempdir = tempfile::tempdir().unwrap(); - let filename = tempdir.path().join("foo.txt"); - File::create(&filename).unwrap(); - let dirfd = fcntl::open(tempdir.path(), - fcntl::OFlag::empty(), - stat::Mode::empty()); - - let result = stat::fstatat(dirfd.unwrap(), - &filename, - fcntl::AtFlags::empty()); - assert_stat_results(result); -} - -#[test] -#[cfg(not(any(target_os = "netbsd", target_os = "redox")))] -fn test_stat_fstat_lstat() { - use nix::sys::stat::{fstat, lstat}; - - let tempdir = tempfile::tempdir().unwrap(); - let filename = tempdir.path().join("bar.txt"); - let linkname = tempdir.path().join("barlink"); - - File::create(&filename).unwrap(); - symlink("bar.txt", &linkname).unwrap(); - let link = File::open(&linkname).unwrap(); - - // should be the same result as calling stat, - // since it's a regular file - let stat_result = stat(&filename); - assert_stat_results(stat_result); - - let lstat_result = lstat(&linkname); - assert_lstat_results(lstat_result); - - let fstat_result = fstat(link.as_raw_fd()); - assert_stat_results(fstat_result); -} - -#[test] -fn test_fchmod() { - let tempdir = tempfile::tempdir().unwrap(); - let filename = tempdir.path().join("foo.txt"); - let file = File::create(&filename).unwrap(); - - let mut mode1 = Mode::empty(); - mode1.insert(Mode::S_IRUSR); - mode1.insert(Mode::S_IWUSR); - fchmod(file.as_raw_fd(), mode1).unwrap(); - - let file_stat1 = stat(&filename).unwrap(); - assert_eq!(file_stat1.st_mode as mode_t & 0o7777, mode1.bits()); - - let mut mode2 = Mode::empty(); - mode2.insert(Mode::S_IROTH); - fchmod(file.as_raw_fd(), mode2).unwrap(); - - let file_stat2 = stat(&filename).unwrap(); - assert_eq!(file_stat2.st_mode as mode_t & 0o7777, mode2.bits()); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_fchmodat() { - let _dr = crate::DirRestore::new(); - let tempdir = tempfile::tempdir().unwrap(); - let filename = "foo.txt"; - let fullpath = tempdir.path().join(filename); - File::create(&fullpath).unwrap(); - - let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); - - let mut mode1 = Mode::empty(); - mode1.insert(Mode::S_IRUSR); - mode1.insert(Mode::S_IWUSR); - fchmodat(Some(dirfd), filename, mode1, FchmodatFlags::FollowSymlink).unwrap(); - - let file_stat1 = stat(&fullpath).unwrap(); - assert_eq!(file_stat1.st_mode as mode_t & 0o7777, mode1.bits()); - - chdir(tempdir.path()).unwrap(); - - let mut mode2 = Mode::empty(); - mode2.insert(Mode::S_IROTH); - fchmodat(None, filename, mode2, FchmodatFlags::FollowSymlink).unwrap(); - - let file_stat2 = stat(&fullpath).unwrap(); - assert_eq!(file_stat2.st_mode as mode_t & 0o7777, mode2.bits()); -} - -/// Asserts that the atime and mtime in a file's metadata match expected values. -/// -/// The atime and mtime are expressed with a resolution of seconds because some file systems -/// (like macOS's HFS+) do not have higher granularity. -#[cfg(not(target_os = "redox"))] -fn assert_times_eq(exp_atime_sec: u64, exp_mtime_sec: u64, attr: &fs::Metadata) { - assert_eq!( - Duration::new(exp_atime_sec, 0), - attr.accessed().unwrap().duration_since(UNIX_EPOCH).unwrap()); - assert_eq!( - Duration::new(exp_mtime_sec, 0), - attr.modified().unwrap().duration_since(UNIX_EPOCH).unwrap()); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_utimes() { - let tempdir = tempfile::tempdir().unwrap(); - let fullpath = tempdir.path().join("file"); - drop(File::create(&fullpath).unwrap()); - - utimes(&fullpath, &TimeVal::seconds(9990), &TimeVal::seconds(5550)).unwrap(); - assert_times_eq(9990, 5550, &fs::metadata(&fullpath).unwrap()); -} - -#[test] -#[cfg(any(target_os = "linux", - target_os = "haiku", - target_os = "ios", - target_os = "macos", - target_os = "freebsd", - target_os = "netbsd"))] -fn test_lutimes() { - let tempdir = tempfile::tempdir().unwrap(); - let target = tempdir.path().join("target"); - let fullpath = tempdir.path().join("symlink"); - drop(File::create(&target).unwrap()); - symlink(&target, &fullpath).unwrap(); - - let exp_target_metadata = fs::symlink_metadata(&target).unwrap(); - lutimes(&fullpath, &TimeVal::seconds(4560), &TimeVal::seconds(1230)).unwrap(); - assert_times_eq(4560, 1230, &fs::symlink_metadata(&fullpath).unwrap()); - - let target_metadata = fs::symlink_metadata(&target).unwrap(); - assert_eq!(exp_target_metadata.accessed().unwrap(), target_metadata.accessed().unwrap(), - "atime of symlink target was unexpectedly modified"); - assert_eq!(exp_target_metadata.modified().unwrap(), target_metadata.modified().unwrap(), - "mtime of symlink target was unexpectedly modified"); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_futimens() { - let tempdir = tempfile::tempdir().unwrap(); - let fullpath = tempdir.path().join("file"); - drop(File::create(&fullpath).unwrap()); - - let fd = fcntl::open(&fullpath, fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); - - futimens(fd, &TimeSpec::seconds(10), &TimeSpec::seconds(20)).unwrap(); - assert_times_eq(10, 20, &fs::metadata(&fullpath).unwrap()); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_utimensat() { - let _dr = crate::DirRestore::new(); - let tempdir = tempfile::tempdir().unwrap(); - let filename = "foo.txt"; - let fullpath = tempdir.path().join(filename); - drop(File::create(&fullpath).unwrap()); - - let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); - - utimensat(Some(dirfd), filename, &TimeSpec::seconds(12345), &TimeSpec::seconds(678), - UtimensatFlags::FollowSymlink).unwrap(); - assert_times_eq(12345, 678, &fs::metadata(&fullpath).unwrap()); - - chdir(tempdir.path()).unwrap(); - - utimensat(None, filename, &TimeSpec::seconds(500), &TimeSpec::seconds(800), - UtimensatFlags::FollowSymlink).unwrap(); - assert_times_eq(500, 800, &fs::metadata(&fullpath).unwrap()); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_mkdirat_success_path() { - let tempdir = tempfile::tempdir().unwrap(); - let filename = "example_subdir"; - let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); - assert!((mkdirat(dirfd, filename, Mode::S_IRWXU)).is_ok()); - assert!(Path::exists(&tempdir.path().join(filename))); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_mkdirat_success_mode() { - let expected_bits = stat::SFlag::S_IFDIR.bits() | stat::Mode::S_IRWXU.bits(); - let tempdir = tempfile::tempdir().unwrap(); - let filename = "example_subdir"; - let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); - assert!((mkdirat(dirfd, filename, Mode::S_IRWXU)).is_ok()); - let permissions = fs::metadata(tempdir.path().join(filename)).unwrap().permissions(); - let mode = permissions.mode(); - assert_eq!(mode as mode_t, expected_bits) -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_mkdirat_fail() { - let tempdir = tempfile::tempdir().unwrap(); - let not_dir_filename= "example_not_dir"; - let filename = "example_subdir_dir"; - let dirfd = fcntl::open(&tempdir.path().join(not_dir_filename), fcntl::OFlag::O_CREAT, - stat::Mode::empty()).unwrap(); - let result = mkdirat(dirfd, filename, Mode::S_IRWXU).unwrap_err(); - assert_eq!(result, Errno::ENOTDIR); -} - -#[test] -#[cfg(not(any(target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "redox")))] -fn test_mknod() { - use stat::{lstat, mknod, SFlag}; - - let file_name = "test_file"; - let tempdir = tempfile::tempdir().unwrap(); - let target = tempdir.path().join(file_name); - mknod(&target, SFlag::S_IFREG, Mode::S_IRWXU, 0).unwrap(); - let mode = lstat(&target).unwrap().st_mode as mode_t; - assert!(mode & libc::S_IFREG == libc::S_IFREG); - assert!(mode & libc::S_IRWXU == libc::S_IRWXU); -} - -#[test] -#[cfg(not(any(target_os = "freebsd", - target_os = "illumos", - target_os = "ios", - target_os = "macos", - target_os = "redox")))] -fn test_mknodat() { - use fcntl::{AtFlags, OFlag}; - use nix::dir::Dir; - use stat::{fstatat, mknodat, SFlag}; - - let file_name = "test_file"; - let tempdir = tempfile::tempdir().unwrap(); - let target_dir = Dir::open(tempdir.path(), OFlag::O_DIRECTORY, Mode::S_IRWXU).unwrap(); - mknodat( - target_dir.as_raw_fd(), - file_name, - SFlag::S_IFREG, - Mode::S_IRWXU, - 0, - ) - .unwrap(); - let mode = fstatat( - target_dir.as_raw_fd(), - file_name, - AtFlags::AT_SYMLINK_NOFOLLOW, - ) - .unwrap() - .st_mode as mode_t; - assert!(mode & libc::S_IFREG == libc::S_IFREG); - assert!(mode & libc::S_IRWXU == libc::S_IRWXU); -} diff --git a/vendor/nix-v0.23.1-patched/test/test_time.rs b/vendor/nix-v0.23.1-patched/test/test_time.rs deleted file mode 100644 index dc307e57b..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_time.rs +++ /dev/null @@ -1,58 +0,0 @@ -#[cfg(any( - target_os = "freebsd", - target_os = "dragonfly", - target_os = "linux", - target_os = "android", - target_os = "emscripten", -))] -use nix::time::clock_getcpuclockid; -use nix::time::{clock_gettime, ClockId}; - -#[cfg(not(target_os = "redox"))] -#[test] -pub fn test_clock_getres() { - assert!(nix::time::clock_getres(ClockId::CLOCK_REALTIME).is_ok()); -} - -#[test] -pub fn test_clock_gettime() { - assert!(clock_gettime(ClockId::CLOCK_REALTIME).is_ok()); -} - -#[cfg(any( - target_os = "freebsd", - target_os = "dragonfly", - target_os = "linux", - target_os = "android", - target_os = "emscripten", -))] -#[test] -pub fn test_clock_getcpuclockid() { - let clock_id = clock_getcpuclockid(nix::unistd::Pid::this()).unwrap(); - assert!(clock_gettime(clock_id).is_ok()); -} - -#[cfg(not(target_os = "redox"))] -#[test] -pub fn test_clock_id_res() { - assert!(ClockId::CLOCK_REALTIME.res().is_ok()); -} - -#[test] -pub fn test_clock_id_now() { - assert!(ClockId::CLOCK_REALTIME.now().is_ok()); -} - -#[cfg(any( - target_os = "freebsd", - target_os = "dragonfly", - target_os = "linux", - target_os = "android", - target_os = "emscripten", -))] -#[test] -pub fn test_clock_id_pid_cpu_clock_id() { - assert!(ClockId::pid_cpu_clock_id(nix::unistd::Pid::this()) - .map(ClockId::now) - .is_ok()); -} diff --git a/vendor/nix-v0.23.1-patched/test/test_unistd.rs b/vendor/nix-v0.23.1-patched/test/test_unistd.rs deleted file mode 100644 index 3a3d49ddf..000000000 --- a/vendor/nix-v0.23.1-patched/test/test_unistd.rs +++ /dev/null @@ -1,1150 +0,0 @@ -#[cfg(not(target_os = "redox"))] -use nix::fcntl::{self, open, readlink}; -use nix::fcntl::OFlag; -use nix::unistd::*; -use nix::unistd::ForkResult::*; -#[cfg(not(target_os = "redox"))] -use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet, Signal, sigaction}; -use nix::sys::wait::*; -use nix::sys::stat::{self, Mode, SFlag}; -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -use nix::pty::{posix_openpt, grantpt, unlockpt, ptsname}; -use nix::errno::Errno; -use std::env; -#[cfg(not(any(target_os = "fuchsia", target_os = "redox")))] -use std::ffi::CString; -#[cfg(not(target_os = "redox"))] -use std::fs::DirBuilder; -use std::fs::{self, File}; -use std::io::Write; -use std::os::unix::prelude::*; -#[cfg(not(any(target_os = "fuchsia", target_os = "redox")))] -use std::path::Path; -use tempfile::{tempdir, tempfile}; -use libc::{_exit, mode_t, off_t}; - -use crate::*; - -#[test] -#[cfg(not(any(target_os = "netbsd")))] -fn test_fork_and_waitpid() { - let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test"); - - // Safe: Child only calls `_exit`, which is signal-safe - match unsafe{fork()}.expect("Error: Fork Failed") { - Child => unsafe { _exit(0) }, - Parent { child } => { - // assert that child was created and pid > 0 - let child_raw: ::libc::pid_t = child.into(); - assert!(child_raw > 0); - let wait_status = waitpid(child, None); - match wait_status { - // assert that waitpid returned correct status and the pid is the one of the child - Ok(WaitStatus::Exited(pid_t, _)) => assert_eq!(pid_t, child), - - // panic, must never happen - s @ Ok(_) => panic!("Child exited {:?}, should never happen", s), - - // panic, waitpid should never fail - Err(s) => panic!("Error: waitpid returned Err({:?}", s) - } - - }, - } -} - -#[test] -fn test_wait() { - // Grab FORK_MTX so wait doesn't reap a different test's child process - let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test"); - - // Safe: Child only calls `_exit`, which is signal-safe - match unsafe{fork()}.expect("Error: Fork Failed") { - Child => unsafe { _exit(0) }, - Parent { child } => { - let wait_status = wait(); - - // just assert that (any) one child returns with WaitStatus::Exited - assert_eq!(wait_status, Ok(WaitStatus::Exited(child, 0))); - }, - } -} - -#[test] -fn test_mkstemp() { - let mut path = env::temp_dir(); - path.push("nix_tempfile.XXXXXX"); - - let result = mkstemp(&path); - match result { - Ok((fd, path)) => { - close(fd).unwrap(); - unlink(path.as_path()).unwrap(); - }, - Err(e) => panic!("mkstemp failed: {}", e) - } -} - -#[test] -fn test_mkstemp_directory() { - // mkstemp should fail if a directory is given - assert!(mkstemp(&env::temp_dir()).is_err()); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_mkfifo() { - let tempdir = tempdir().unwrap(); - let mkfifo_fifo = tempdir.path().join("mkfifo_fifo"); - - mkfifo(&mkfifo_fifo, Mode::S_IRUSR).unwrap(); - - let stats = stat::stat(&mkfifo_fifo).unwrap(); - let typ = stat::SFlag::from_bits_truncate(stats.st_mode as mode_t); - assert!(typ == SFlag::S_IFIFO); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_mkfifo_directory() { - // mkfifo should fail if a directory is given - assert!(mkfifo(&env::temp_dir(), Mode::S_IRUSR).is_err()); -} - -#[test] -#[cfg(not(any( - target_os = "macos", target_os = "ios", - target_os = "android", target_os = "redox")))] -fn test_mkfifoat_none() { - let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test"); - - let tempdir = tempdir().unwrap(); - let mkfifoat_fifo = tempdir.path().join("mkfifoat_fifo"); - - mkfifoat(None, &mkfifoat_fifo, Mode::S_IRUSR).unwrap(); - - let stats = stat::stat(&mkfifoat_fifo).unwrap(); - let typ = stat::SFlag::from_bits_truncate(stats.st_mode); - assert_eq!(typ, SFlag::S_IFIFO); -} - -#[test] -#[cfg(not(any( - target_os = "macos", target_os = "ios", - target_os = "android", target_os = "redox")))] -fn test_mkfifoat() { - use nix::fcntl; - - let tempdir = tempdir().unwrap(); - let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); - let mkfifoat_name = "mkfifoat_name"; - - mkfifoat(Some(dirfd), mkfifoat_name, Mode::S_IRUSR).unwrap(); - - let stats = stat::fstatat(dirfd, mkfifoat_name, fcntl::AtFlags::empty()).unwrap(); - let typ = stat::SFlag::from_bits_truncate(stats.st_mode); - assert_eq!(typ, SFlag::S_IFIFO); -} - -#[test] -#[cfg(not(any( - target_os = "macos", target_os = "ios", - target_os = "android", target_os = "redox")))] -fn test_mkfifoat_directory_none() { - let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test"); - - // mkfifoat should fail if a directory is given - assert!(!mkfifoat(None, &env::temp_dir(), Mode::S_IRUSR).is_ok()); -} - -#[test] -#[cfg(not(any( - target_os = "macos", target_os = "ios", - target_os = "android", target_os = "redox")))] -fn test_mkfifoat_directory() { - // mkfifoat should fail if a directory is given - let tempdir = tempdir().unwrap(); - let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); - let mkfifoat_dir = "mkfifoat_dir"; - stat::mkdirat(dirfd, mkfifoat_dir, Mode::S_IRUSR).unwrap(); - - assert!(!mkfifoat(Some(dirfd), mkfifoat_dir, Mode::S_IRUSR).is_ok()); -} - -#[test] -fn test_getpid() { - let pid: ::libc::pid_t = getpid().into(); - let ppid: ::libc::pid_t = getppid().into(); - assert!(pid > 0); - assert!(ppid > 0); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_getsid() { - let none_sid: ::libc::pid_t = getsid(None).unwrap().into(); - let pid_sid: ::libc::pid_t = getsid(Some(getpid())).unwrap().into(); - assert!(none_sid > 0); - assert_eq!(none_sid, pid_sid); -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -mod linux_android { - use nix::unistd::gettid; - - #[test] - fn test_gettid() { - let tid: ::libc::pid_t = gettid().into(); - assert!(tid > 0); - } -} - -#[test] -// `getgroups()` and `setgroups()` do not behave as expected on Apple platforms -#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox", target_os = "fuchsia")))] -fn test_setgroups() { - // Skip this test when not run as root as `setgroups()` requires root. - skip_if_not_root!("test_setgroups"); - - let _m = crate::GROUPS_MTX.lock().expect("Mutex got poisoned by another test"); - - // Save the existing groups - let old_groups = getgroups().unwrap(); - - // Set some new made up groups - let groups = [Gid::from_raw(123), Gid::from_raw(456)]; - setgroups(&groups).unwrap(); - - let new_groups = getgroups().unwrap(); - assert_eq!(new_groups, groups); - - // Revert back to the old groups - setgroups(&old_groups).unwrap(); -} - -#[test] -// `getgroups()` and `setgroups()` do not behave as expected on Apple platforms -#[cfg(not(any(target_os = "ios", - target_os = "macos", - target_os = "redox", - target_os = "fuchsia", - target_os = "illumos")))] -fn test_initgroups() { - // Skip this test when not run as root as `initgroups()` and `setgroups()` - // require root. - skip_if_not_root!("test_initgroups"); - - let _m = crate::GROUPS_MTX.lock().expect("Mutex got poisoned by another test"); - - // Save the existing groups - let old_groups = getgroups().unwrap(); - - // It doesn't matter if the root user is not called "root" or if a user - // called "root" doesn't exist. We are just checking that the extra, - // made-up group, `123`, is set. - // FIXME: Test the other half of initgroups' functionality: whether the - // groups that the user belongs to are also set. - let user = CString::new("root").unwrap(); - let group = Gid::from_raw(123); - let group_list = getgrouplist(&user, group).unwrap(); - assert!(group_list.contains(&group)); - - initgroups(&user, group).unwrap(); - - let new_groups = getgroups().unwrap(); - assert_eq!(new_groups, group_list); - - // Revert back to the old groups - setgroups(&old_groups).unwrap(); -} - -#[cfg(not(any(target_os = "fuchsia", target_os = "redox")))] -macro_rules! execve_test_factory( - ($test_name:ident, $syscall:ident, $exe: expr $(, $pathname:expr, $flags:expr)*) => ( - - #[cfg(test)] - mod $test_name { - use std::ffi::CStr; - use super::*; - - const EMPTY: &'static [u8] = b"\0"; - const DASH_C: &'static [u8] = b"-c\0"; - const BIGARG: &'static [u8] = b"echo nix!!! && echo foo=$foo && echo baz=$baz\0"; - const FOO: &'static [u8] = b"foo=bar\0"; - const BAZ: &'static [u8] = b"baz=quux\0"; - - fn syscall_cstr_ref() -> Result { - $syscall( - $exe, - $(CString::new($pathname).unwrap().as_c_str(), )* - &[CStr::from_bytes_with_nul(EMPTY).unwrap(), - CStr::from_bytes_with_nul(DASH_C).unwrap(), - CStr::from_bytes_with_nul(BIGARG).unwrap()], - &[CStr::from_bytes_with_nul(FOO).unwrap(), - CStr::from_bytes_with_nul(BAZ).unwrap()] - $(, $flags)*) - } - - fn syscall_cstring() -> Result { - $syscall( - $exe, - $(CString::new($pathname).unwrap().as_c_str(), )* - &[CString::from(CStr::from_bytes_with_nul(EMPTY).unwrap()), - CString::from(CStr::from_bytes_with_nul(DASH_C).unwrap()), - CString::from(CStr::from_bytes_with_nul(BIGARG).unwrap())], - &[CString::from(CStr::from_bytes_with_nul(FOO).unwrap()), - CString::from(CStr::from_bytes_with_nul(BAZ).unwrap())] - $(, $flags)*) - } - - fn common_test(syscall: fn() -> Result) { - if "execveat" == stringify!($syscall) { - // Though undocumented, Docker's default seccomp profile seems to - // block this syscall. https://github.com/nix-rust/nix/issues/1122 - skip_if_seccomp!($test_name); - } - - let m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test"); - // The `exec`d process will write to `writer`, and we'll read that - // data from `reader`. - let (reader, writer) = pipe().unwrap(); - - // Safe: Child calls `exit`, `dup`, `close` and the provided `exec*` family function. - // NOTE: Technically, this makes the macro unsafe to use because you could pass anything. - // The tests make sure not to do that, though. - match unsafe{fork()}.unwrap() { - Child => { - // Make `writer` be the stdout of the new process. - dup2(writer, 1).unwrap(); - let r = syscall(); - let _ = std::io::stderr() - .write_all(format!("{:?}", r).as_bytes()); - // Should only get here in event of error - unsafe{ _exit(1) }; - }, - Parent { child } => { - // Wait for the child to exit. - let ws = waitpid(child, None); - drop(m); - assert_eq!(ws, Ok(WaitStatus::Exited(child, 0))); - // Read 1024 bytes. - let mut buf = [0u8; 1024]; - read(reader, &mut buf).unwrap(); - // It should contain the things we printed using `/bin/sh`. - let string = String::from_utf8_lossy(&buf); - assert!(string.contains("nix!!!")); - assert!(string.contains("foo=bar")); - assert!(string.contains("baz=quux")); - } - } - } - - // These tests frequently fail on musl, probably due to - // https://github.com/nix-rust/nix/issues/555 - #[cfg_attr(target_env = "musl", ignore)] - #[test] - fn test_cstr_ref() { - common_test(syscall_cstr_ref); - } - - // These tests frequently fail on musl, probably due to - // https://github.com/nix-rust/nix/issues/555 - #[cfg_attr(target_env = "musl", ignore)] - #[test] - fn test_cstring() { - common_test(syscall_cstring); - } - } - - ) -); - -cfg_if!{ - if #[cfg(target_os = "android")] { - execve_test_factory!(test_execve, execve, CString::new("/system/bin/sh").unwrap().as_c_str()); - execve_test_factory!(test_fexecve, fexecve, File::open("/system/bin/sh").unwrap().into_raw_fd()); - } else if #[cfg(any(target_os = "freebsd", - target_os = "linux"))] { - // These tests frequently fail on musl, probably due to - // https://github.com/nix-rust/nix/issues/555 - execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str()); - execve_test_factory!(test_fexecve, fexecve, File::open("/bin/sh").unwrap().into_raw_fd()); - } else if #[cfg(any(target_os = "dragonfly", - target_os = "illumos", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris"))] { - execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str()); - // No fexecve() on DragonFly, ios, macos, NetBSD, OpenBSD. - // - // Note for NetBSD and OpenBSD: although rust-lang/libc includes it - // (under unix/bsd/netbsdlike/) fexecve is not currently implemented on - // NetBSD nor on OpenBSD. - } -} - -#[cfg(any(target_os = "haiku", target_os = "linux", target_os = "openbsd"))] -execve_test_factory!(test_execvpe, execvpe, &CString::new("sh").unwrap()); - -cfg_if!{ - if #[cfg(target_os = "android")] { - use nix::fcntl::AtFlags; - execve_test_factory!(test_execveat_empty, execveat, - File::open("/system/bin/sh").unwrap().into_raw_fd(), - "", AtFlags::AT_EMPTY_PATH); - execve_test_factory!(test_execveat_relative, execveat, - File::open("/system/bin/").unwrap().into_raw_fd(), - "./sh", AtFlags::empty()); - execve_test_factory!(test_execveat_absolute, execveat, - File::open("/").unwrap().into_raw_fd(), - "/system/bin/sh", AtFlags::empty()); - } else if #[cfg(all(target_os = "linux", any(target_arch ="x86_64", target_arch ="x86")))] { - use nix::fcntl::AtFlags; - execve_test_factory!(test_execveat_empty, execveat, File::open("/bin/sh").unwrap().into_raw_fd(), - "", AtFlags::AT_EMPTY_PATH); - execve_test_factory!(test_execveat_relative, execveat, File::open("/bin/").unwrap().into_raw_fd(), - "./sh", AtFlags::empty()); - execve_test_factory!(test_execveat_absolute, execveat, File::open("/").unwrap().into_raw_fd(), - "/bin/sh", AtFlags::empty()); - } -} - -#[test] -#[cfg(not(target_os = "fuchsia"))] -fn test_fchdir() { - // fchdir changes the process's cwd - let _dr = crate::DirRestore::new(); - - let tmpdir = tempdir().unwrap(); - let tmpdir_path = tmpdir.path().canonicalize().unwrap(); - let tmpdir_fd = File::open(&tmpdir_path).unwrap().into_raw_fd(); - - assert!(fchdir(tmpdir_fd).is_ok()); - assert_eq!(getcwd().unwrap(), tmpdir_path); - - assert!(close(tmpdir_fd).is_ok()); -} - -#[test] -fn test_getcwd() { - // chdir changes the process's cwd - let _dr = crate::DirRestore::new(); - - let tmpdir = tempdir().unwrap(); - let tmpdir_path = tmpdir.path().canonicalize().unwrap(); - assert!(chdir(&tmpdir_path).is_ok()); - assert_eq!(getcwd().unwrap(), tmpdir_path); - - // make path 500 chars longer so that buffer doubling in getcwd - // kicks in. Note: One path cannot be longer than 255 bytes - // (NAME_MAX) whole path cannot be longer than PATH_MAX (usually - // 4096 on linux, 1024 on macos) - let mut inner_tmp_dir = tmpdir_path; - for _ in 0..5 { - let newdir = "a".repeat(100); - inner_tmp_dir.push(newdir); - assert!(mkdir(inner_tmp_dir.as_path(), Mode::S_IRWXU).is_ok()); - } - assert!(chdir(inner_tmp_dir.as_path()).is_ok()); - assert_eq!(getcwd().unwrap(), inner_tmp_dir.as_path()); -} - -#[test] -fn test_chown() { - // Testing for anything other than our own UID/GID is hard. - let uid = Some(getuid()); - let gid = Some(getgid()); - - let tempdir = tempdir().unwrap(); - let path = tempdir.path().join("file"); - { - File::create(&path).unwrap(); - } - - chown(&path, uid, gid).unwrap(); - chown(&path, uid, None).unwrap(); - chown(&path, None, gid).unwrap(); - - fs::remove_file(&path).unwrap(); - chown(&path, uid, gid).unwrap_err(); -} - -#[test] -fn test_fchown() { - // Testing for anything other than our own UID/GID is hard. - let uid = Some(getuid()); - let gid = Some(getgid()); - - let path = tempfile().unwrap(); - let fd = path.as_raw_fd(); - - fchown(fd, uid, gid).unwrap(); - fchown(fd, uid, None).unwrap(); - fchown(fd, None, gid).unwrap(); - fchown(999999999, uid, gid).unwrap_err(); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_fchownat() { - let _dr = crate::DirRestore::new(); - // Testing for anything other than our own UID/GID is hard. - let uid = Some(getuid()); - let gid = Some(getgid()); - - let tempdir = tempdir().unwrap(); - let path = tempdir.path().join("file"); - { - File::create(&path).unwrap(); - } - - let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); - - fchownat(Some(dirfd), "file", uid, gid, FchownatFlags::FollowSymlink).unwrap(); - - chdir(tempdir.path()).unwrap(); - fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap(); - - fs::remove_file(&path).unwrap(); - fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap_err(); -} - -#[test] -fn test_lseek() { - const CONTENTS: &[u8] = b"abcdef123456"; - let mut tmp = tempfile().unwrap(); - tmp.write_all(CONTENTS).unwrap(); - let tmpfd = tmp.into_raw_fd(); - - let offset: off_t = 5; - lseek(tmpfd, offset, Whence::SeekSet).unwrap(); - - let mut buf = [0u8; 7]; - crate::read_exact(tmpfd, &mut buf); - assert_eq!(b"f123456", &buf); - - close(tmpfd).unwrap(); -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -#[test] -fn test_lseek64() { - const CONTENTS: &[u8] = b"abcdef123456"; - let mut tmp = tempfile().unwrap(); - tmp.write_all(CONTENTS).unwrap(); - let tmpfd = tmp.into_raw_fd(); - - lseek64(tmpfd, 5, Whence::SeekSet).unwrap(); - - let mut buf = [0u8; 7]; - crate::read_exact(tmpfd, &mut buf); - assert_eq!(b"f123456", &buf); - - close(tmpfd).unwrap(); -} - -cfg_if!{ - if #[cfg(any(target_os = "android", target_os = "linux"))] { - macro_rules! require_acct{ - () => { - require_capability!("test_acct", CAP_SYS_PACCT); - } - } - } else if #[cfg(target_os = "freebsd")] { - macro_rules! require_acct{ - () => { - skip_if_not_root!("test_acct"); - skip_if_jailed!("test_acct"); - } - } - } else if #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] { - macro_rules! require_acct{ - () => { - skip_if_not_root!("test_acct"); - } - } - } -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -fn test_acct() { - use tempfile::NamedTempFile; - use std::process::Command; - use std::{thread, time}; - - let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test"); - require_acct!(); - - let file = NamedTempFile::new().unwrap(); - let path = file.path().to_str().unwrap(); - - acct::enable(path).unwrap(); - - loop { - Command::new("echo").arg("Hello world"); - let len = fs::metadata(path).unwrap().len(); - if len > 0 { break; } - thread::sleep(time::Duration::from_millis(10)); - } - acct::disable().unwrap(); -} - -#[test] -fn test_fpathconf_limited() { - let f = tempfile().unwrap(); - // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test - let path_max = fpathconf(f.as_raw_fd(), PathconfVar::PATH_MAX); - assert!(path_max.expect("fpathconf failed").expect("PATH_MAX is unlimited") > 0); -} - -#[test] -fn test_pathconf_limited() { - // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test - let path_max = pathconf("/", PathconfVar::PATH_MAX); - assert!(path_max.expect("pathconf failed").expect("PATH_MAX is unlimited") > 0); -} - -#[test] -fn test_sysconf_limited() { - // AFAIK, OPEN_MAX is limited on all platforms, so it makes a good test - let open_max = sysconf(SysconfVar::OPEN_MAX); - assert!(open_max.expect("sysconf failed").expect("OPEN_MAX is unlimited") > 0); -} - -#[cfg(target_os = "freebsd")] -#[test] -fn test_sysconf_unsupported() { - // I know of no sysconf variables that are unsupported everywhere, but - // _XOPEN_CRYPT is unsupported on FreeBSD 11.0, which is one of the platforms - // we test. - let open_max = sysconf(SysconfVar::_XOPEN_CRYPT); - assert!(open_max.expect("sysconf failed").is_none()) -} - - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[test] -fn test_getresuid() { - let resuids = getresuid().unwrap(); - assert!(resuids.real.as_raw() != libc::uid_t::max_value()); - assert!(resuids.effective.as_raw() != libc::uid_t::max_value()); - assert!(resuids.saved.as_raw() != libc::uid_t::max_value()); -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[test] -fn test_getresgid() { - let resgids = getresgid().unwrap(); - assert!(resgids.real.as_raw() != libc::gid_t::max_value()); - assert!(resgids.effective.as_raw() != libc::gid_t::max_value()); - assert!(resgids.saved.as_raw() != libc::gid_t::max_value()); -} - -// Test that we can create a pair of pipes. No need to verify that they pass -// data; that's the domain of the OS, not nix. -#[test] -fn test_pipe() { - let (fd0, fd1) = pipe().unwrap(); - let m0 = stat::SFlag::from_bits_truncate(stat::fstat(fd0).unwrap().st_mode as mode_t); - // S_IFIFO means it's a pipe - assert_eq!(m0, SFlag::S_IFIFO); - let m1 = stat::SFlag::from_bits_truncate(stat::fstat(fd1).unwrap().st_mode as mode_t); - assert_eq!(m1, SFlag::S_IFIFO); -} - -// pipe2(2) is the same as pipe(2), except it allows setting some flags. Check -// that we can set a flag. -#[cfg(any(target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "illumos", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", - target_os = "redox", - target_os = "solaris"))] -#[test] -fn test_pipe2() { - use nix::fcntl::{fcntl, FcntlArg, FdFlag}; - - let (fd0, fd1) = pipe2(OFlag::O_CLOEXEC).unwrap(); - let f0 = FdFlag::from_bits_truncate(fcntl(fd0, FcntlArg::F_GETFD).unwrap()); - assert!(f0.contains(FdFlag::FD_CLOEXEC)); - let f1 = FdFlag::from_bits_truncate(fcntl(fd1, FcntlArg::F_GETFD).unwrap()); - assert!(f1.contains(FdFlag::FD_CLOEXEC)); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -fn test_truncate() { - let tempdir = tempdir().unwrap(); - let path = tempdir.path().join("file"); - - { - let mut tmp = File::create(&path).unwrap(); - const CONTENTS: &[u8] = b"12345678"; - tmp.write_all(CONTENTS).unwrap(); - } - - truncate(&path, 4).unwrap(); - - let metadata = fs::metadata(&path).unwrap(); - assert_eq!(4, metadata.len()); -} - -#[test] -fn test_ftruncate() { - let tempdir = tempdir().unwrap(); - let path = tempdir.path().join("file"); - - let tmpfd = { - let mut tmp = File::create(&path).unwrap(); - const CONTENTS: &[u8] = b"12345678"; - tmp.write_all(CONTENTS).unwrap(); - tmp.into_raw_fd() - }; - - ftruncate(tmpfd, 2).unwrap(); - close(tmpfd).unwrap(); - - let metadata = fs::metadata(&path).unwrap(); - assert_eq!(2, metadata.len()); -} - -// Used in `test_alarm`. -#[cfg(not(target_os = "redox"))] -static mut ALARM_CALLED: bool = false; - -// Used in `test_alarm`. -#[cfg(not(target_os = "redox"))] -pub extern fn alarm_signal_handler(raw_signal: libc::c_int) { - assert_eq!(raw_signal, libc::SIGALRM, "unexpected signal: {}", raw_signal); - unsafe { ALARM_CALLED = true }; -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_alarm() { - use std::{ - time::{Duration, Instant,}, - thread - }; - - // Maybe other tests that fork interfere with this one? - let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test"); - - let handler = SigHandler::Handler(alarm_signal_handler); - let signal_action = SigAction::new(handler, SaFlags::SA_RESTART, SigSet::empty()); - let old_handler = unsafe { - sigaction(Signal::SIGALRM, &signal_action) - .expect("unable to set signal handler for alarm") - }; - - // Set an alarm. - assert_eq!(alarm::set(60), None); - - // Overwriting an alarm should return the old alarm. - assert_eq!(alarm::set(1), Some(60)); - - // We should be woken up after 1 second by the alarm, so we'll sleep for 3 - // seconds to be sure. - let starttime = Instant::now(); - loop { - thread::sleep(Duration::from_millis(100)); - if unsafe { ALARM_CALLED} { - break; - } - if starttime.elapsed() > Duration::from_secs(3) { - panic!("Timeout waiting for SIGALRM"); - } - } - - // Reset the signal. - unsafe { - sigaction(Signal::SIGALRM, &old_handler) - .expect("unable to set signal handler for alarm"); - } -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_canceling_alarm() { - let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test"); - - assert_eq!(alarm::cancel(), None); - - assert_eq!(alarm::set(60), None); - assert_eq!(alarm::cancel(), Some(60)); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_symlinkat() { - let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test"); - - let tempdir = tempdir().unwrap(); - - let target = tempdir.path().join("a"); - let linkpath = tempdir.path().join("b"); - symlinkat(&target, None, &linkpath).unwrap(); - assert_eq!( - readlink(&linkpath).unwrap().to_str().unwrap(), - target.to_str().unwrap() - ); - - let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); - let target = "c"; - let linkpath = "d"; - symlinkat(target, Some(dirfd), linkpath).unwrap(); - assert_eq!( - readlink(&tempdir.path().join(linkpath)) - .unwrap() - .to_str() - .unwrap(), - target - ); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_linkat_file() { - let tempdir = tempdir().unwrap(); - let oldfilename = "foo.txt"; - let oldfilepath = tempdir.path().join(oldfilename); - - let newfilename = "bar.txt"; - let newfilepath = tempdir.path().join(newfilename); - - // Create file - File::create(&oldfilepath).unwrap(); - - // Get file descriptor for base directory - let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); - - // Attempt hard link file at relative path - linkat(Some(dirfd), oldfilename, Some(dirfd), newfilename, LinkatFlags::SymlinkFollow).unwrap(); - assert!(newfilepath.exists()); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_linkat_olddirfd_none() { - let _dr = crate::DirRestore::new(); - - let tempdir_oldfile = tempdir().unwrap(); - let oldfilename = "foo.txt"; - let oldfilepath = tempdir_oldfile.path().join(oldfilename); - - let tempdir_newfile = tempdir().unwrap(); - let newfilename = "bar.txt"; - let newfilepath = tempdir_newfile.path().join(newfilename); - - // Create file - File::create(&oldfilepath).unwrap(); - - // Get file descriptor for base directory of new file - let dirfd = fcntl::open(tempdir_newfile.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); - - // Attempt hard link file using curent working directory as relative path for old file path - chdir(tempdir_oldfile.path()).unwrap(); - linkat(None, oldfilename, Some(dirfd), newfilename, LinkatFlags::SymlinkFollow).unwrap(); - assert!(newfilepath.exists()); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_linkat_newdirfd_none() { - let _dr = crate::DirRestore::new(); - - let tempdir_oldfile = tempdir().unwrap(); - let oldfilename = "foo.txt"; - let oldfilepath = tempdir_oldfile.path().join(oldfilename); - - let tempdir_newfile = tempdir().unwrap(); - let newfilename = "bar.txt"; - let newfilepath = tempdir_newfile.path().join(newfilename); - - // Create file - File::create(&oldfilepath).unwrap(); - - // Get file descriptor for base directory of old file - let dirfd = fcntl::open(tempdir_oldfile.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); - - // Attempt hard link file using current working directory as relative path for new file path - chdir(tempdir_newfile.path()).unwrap(); - linkat(Some(dirfd), oldfilename, None, newfilename, LinkatFlags::SymlinkFollow).unwrap(); - assert!(newfilepath.exists()); -} - -#[test] -#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))] -fn test_linkat_no_follow_symlink() { - let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test"); - - let tempdir = tempdir().unwrap(); - let oldfilename = "foo.txt"; - let oldfilepath = tempdir.path().join(oldfilename); - - let symoldfilename = "symfoo.txt"; - let symoldfilepath = tempdir.path().join(symoldfilename); - - let newfilename = "nofollowsymbar.txt"; - let newfilepath = tempdir.path().join(newfilename); - - // Create file - File::create(&oldfilepath).unwrap(); - - // Create symlink to file - symlinkat(&oldfilepath, None, &symoldfilepath).unwrap(); - - // Get file descriptor for base directory - let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); - - // Attempt link symlink of file at relative path - linkat(Some(dirfd), symoldfilename, Some(dirfd), newfilename, LinkatFlags::NoSymlinkFollow).unwrap(); - - // Assert newfile is actually a symlink to oldfile. - assert_eq!( - readlink(&newfilepath) - .unwrap() - .to_str() - .unwrap(), - oldfilepath.to_str().unwrap() - ); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_linkat_follow_symlink() { - let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test"); - - let tempdir = tempdir().unwrap(); - let oldfilename = "foo.txt"; - let oldfilepath = tempdir.path().join(oldfilename); - - let symoldfilename = "symfoo.txt"; - let symoldfilepath = tempdir.path().join(symoldfilename); - - let newfilename = "nofollowsymbar.txt"; - let newfilepath = tempdir.path().join(newfilename); - - // Create file - File::create(&oldfilepath).unwrap(); - - // Create symlink to file - symlinkat(&oldfilepath, None, &symoldfilepath).unwrap(); - - // Get file descriptor for base directory - let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); - - // Attempt link target of symlink of file at relative path - linkat(Some(dirfd), symoldfilename, Some(dirfd), newfilename, LinkatFlags::SymlinkFollow).unwrap(); - - let newfilestat = stat::stat(&newfilepath).unwrap(); - - // Check the file type of the new link - assert_eq!((stat::SFlag::from_bits_truncate(newfilestat.st_mode as mode_t) & SFlag::S_IFMT), - SFlag::S_IFREG - ); - - // Check the number of hard links to the original file - assert_eq!(newfilestat.st_nlink, 2); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_unlinkat_dir_noremovedir() { - let tempdir = tempdir().unwrap(); - let dirname = "foo_dir"; - let dirpath = tempdir.path().join(dirname); - - // Create dir - DirBuilder::new().recursive(true).create(&dirpath).unwrap(); - - // Get file descriptor for base directory - let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); - - // Attempt unlink dir at relative path without proper flag - let err_result = unlinkat(Some(dirfd), dirname, UnlinkatFlags::NoRemoveDir).unwrap_err(); - assert!(err_result == Errno::EISDIR || err_result == Errno::EPERM); - } - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_unlinkat_dir_removedir() { - let tempdir = tempdir().unwrap(); - let dirname = "foo_dir"; - let dirpath = tempdir.path().join(dirname); - - // Create dir - DirBuilder::new().recursive(true).create(&dirpath).unwrap(); - - // Get file descriptor for base directory - let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); - - // Attempt unlink dir at relative path with proper flag - unlinkat(Some(dirfd), dirname, UnlinkatFlags::RemoveDir).unwrap(); - assert!(!dirpath.exists()); - } - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_unlinkat_file() { - let tempdir = tempdir().unwrap(); - let filename = "foo.txt"; - let filepath = tempdir.path().join(filename); - - // Create file - File::create(&filepath).unwrap(); - - // Get file descriptor for base directory - let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); - - // Attempt unlink file at relative path - unlinkat(Some(dirfd), filename, UnlinkatFlags::NoRemoveDir).unwrap(); - assert!(!filepath.exists()); - } - -#[test] -fn test_access_not_existing() { - let tempdir = tempdir().unwrap(); - let dir = tempdir.path().join("does_not_exist.txt"); - assert_eq!(access(&dir, AccessFlags::F_OK).err().unwrap(), - Errno::ENOENT); -} - -#[test] -fn test_access_file_exists() { - let tempdir = tempdir().unwrap(); - let path = tempdir.path().join("does_exist.txt"); - let _file = File::create(path.clone()).unwrap(); - assert!(access(&path, AccessFlags::R_OK | AccessFlags::W_OK).is_ok()); -} - -#[cfg(not(target_os = "redox"))] -#[test] -fn test_user_into_passwd() { - // get the UID of the "nobody" user - let nobody = User::from_name("nobody").unwrap().unwrap(); - let pwd: libc::passwd = nobody.into(); - let _: User = (&pwd).into(); -} - -/// Tests setting the filesystem UID with `setfsuid`. -#[cfg(any(target_os = "linux", target_os = "android"))] -#[test] -fn test_setfsuid() { - use std::os::unix::fs::PermissionsExt; - use std::{fs, io, thread}; - require_capability!("test_setfsuid", CAP_SETUID); - - // get the UID of the "nobody" user - let nobody = User::from_name("nobody").unwrap().unwrap(); - - // create a temporary file with permissions '-rw-r-----' - let file = tempfile::NamedTempFile::new_in("/var/tmp").unwrap(); - let temp_path = file.into_temp_path(); - dbg!(&temp_path); - let temp_path_2 = (&temp_path).to_path_buf(); - let mut permissions = fs::metadata(&temp_path).unwrap().permissions(); - permissions.set_mode(0o640); - - // spawn a new thread where to test setfsuid - thread::spawn(move || { - // set filesystem UID - let fuid = setfsuid(nobody.uid); - // trying to open the temporary file should fail with EACCES - let res = fs::File::open(&temp_path); - assert!(res.is_err()); - assert_eq!(res.err().unwrap().kind(), io::ErrorKind::PermissionDenied); - - // assert fuid actually changes - let prev_fuid = setfsuid(Uid::from_raw(-1i32 as u32)); - assert_ne!(prev_fuid, fuid); - }) - .join() - .unwrap(); - - // open the temporary file with the current thread filesystem UID - fs::File::open(temp_path_2).unwrap(); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -fn test_ttyname() { - let fd = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed"); - assert!(fd.as_raw_fd() > 0); - - // on linux, we can just call ttyname on the pty master directly, but - // apparently osx requires that ttyname is called on a slave pty (can't - // find this documented anywhere, but it seems to empirically be the case) - grantpt(&fd).expect("grantpt failed"); - unlockpt(&fd).expect("unlockpt failed"); - let sname = unsafe { ptsname(&fd) }.expect("ptsname failed"); - let fds = open( - Path::new(&sname), - OFlag::O_RDWR, - stat::Mode::empty(), - ).expect("open failed"); - assert!(fds > 0); - - let name = ttyname(fds).expect("ttyname failed"); - assert!(name.starts_with("/dev")); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -fn test_ttyname_not_pty() { - let fd = File::open("/dev/zero").unwrap(); - assert!(fd.as_raw_fd() > 0); - assert_eq!(ttyname(fd.as_raw_fd()), Err(Errno::ENOTTY)); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -fn test_ttyname_invalid_fd() { - assert_eq!(ttyname(-1), Err(Errno::EBADF)); -} - -#[test] -#[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "openbsd", - target_os = "netbsd", - target_os = "dragonfly", -))] -fn test_getpeereid() { - use std::os::unix::net::UnixStream; - let (sock_a, sock_b) = UnixStream::pair().unwrap(); - - let (uid_a, gid_a) = getpeereid(sock_a.as_raw_fd()).unwrap(); - let (uid_b, gid_b) = getpeereid(sock_b.as_raw_fd()).unwrap(); - - let uid = geteuid(); - let gid = getegid(); - - assert_eq!(uid, uid_a); - assert_eq!(gid, gid_a); - assert_eq!(uid_a, uid_b); - assert_eq!(gid_a, gid_b); -} - -#[test] -#[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "openbsd", - target_os = "netbsd", - target_os = "dragonfly", -))] -fn test_getpeereid_invalid_fd() { - // getpeereid is not POSIX, so error codes are inconsistent between different Unices. - assert!(getpeereid(-1).is_err()); -}