Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 62 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,37 +1,85 @@
on:
workflow_dispatch:
pull_request:
push:
tags: ["v*.*.*"]
branches-ignore:
- '**.tmp'

name: ci
name: Continuous Integration

jobs:
test:
runs-on: ubuntu-latest
test-sys:
name: Build and test the sys crate / ${{matrix.target}}
runs-on: ${{matrix.host_os}}
strategy:
fail-fast: false
matrix:
rust:
- stable
- beta
- nightly
- 1.47.0
include:
- target: x86_64-unknown-linux-gnu
host_os: ubuntu-latest
- target: x86_64-apple-darwin
host_os: macos-latest
- target: x86_64-unknown-freebsd
host_os: ubuntu-latest
vm_action: vmactions/freebsd-vm@v1
- target: x86_64-unknown-openbsd
host_os: ubuntu-latest
vm_action: vmactions/openbsd-vm@v1
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
- name: Rust Cache
uses: Swatinem/rust-cache@v2
with:
toolchain: ${{ matrix.rust }}
- uses: Swatinem/rust-cache@v2
- run: cargo test --all
key: ${{matrix.host_os}}-${{matrix.target}}-ioctl-sys
- name: Build for target ${{matrix.target}} with a virtual machine
if: matrix.vm_action != null
uses: vmactions/openbsd-vm@v1
with:
usesh: true
prepare: |
pkg_add rust
run: |
cargo test --package ioctl-sys
- name: Build for target ${{matrix.target}}
if: matrix.vm_action == null
run: cargo test --package ioctl-sys

check:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@beta
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- run: cargo fmt --all -- --check
- run: cargo fmt --all
#- run: cargo clippy --all --all-targets -- -D warnings

test:
name: Build / ${{matrix.target}}
runs-on: ${{matrix.host_os}}
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
host_os: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Rust Cache
uses: Swatinem/rust-cache@v2
with:
key: ${{matrix.host_os}}-${{matrix.target}}-ioctl-sys
- name: Test for target ${{matrix.target}} with a virtual machine
if: matrix.vm_action != null
uses: vmactions/openbsd-vm@v1
with:
usesh: true
prepare: |
pkg_add rust
run: |
cargo test --all
- name: Test for target ${{matrix.target}}
if: matrix.vm_action == null
run: cargo test --all
4 changes: 4 additions & 0 deletions ioctl-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ documentation = "https://docs.rs/ioctl-sys"
include = ["Cargo.toml", "**/*.rs"]

[dependencies]

[dev-dependencies]
# Only for the ioctl test
libc = "0.2"
24 changes: 7 additions & 17 deletions ioctl-sys/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
use std::os::raw::{c_int, c_ulong};

#[cfg(any(
#[cfg(not(any(
target_os = "linux",
target_os = "macos",
target_os = "openbsd",
target_os = "freebsd",
target_os = "netbsd",
target_os = "dragonfly",
target_os = "android"
))]
#[macro_use]
)))]
compile_error!("This platform is not supported!");

mod platform;

#[cfg(any(
target_os = "linux",
target_os = "macos",
target_os = "openbsd",
target_os = "android"
))]
pub use platform::*;

extern "C" {
Expand All @@ -31,14 +29,6 @@ pub fn check_res(res: c_int) -> std::io::Result<()> {
}
}

#[cfg(not(any(
target_os = "linux",
target_os = "macos",
target_os = "openbsd",
target_os = "android"
)))]
use platform_not_supported;

#[cfg(doctest)]
mod test_readme {
macro_rules! external_doc_test {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/// Constants for BSD-derived operating systems. Confirmed to work on macOS, FreeBSD, OpenBSD.
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
mod consts {
#[doc(hidden)]
Expand Down
14 changes: 8 additions & 6 deletions ioctl-sys/src/platform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ pub const TYPEBITS: u32 = 8;
#[path = "linux.rs"]
mod consts;

#[cfg(target_os = "macos")]
#[path = "macos.rs"]
mod consts;

#[cfg(target_os = "openbsd")]
#[path = "openbsd.rs"]
#[cfg(any(
target_os = "macos",
target_os = "openbsd",
target_os = "freebsd",
target_os = "netbsd",
target_os = "dragonfly",
))]
#[path = "bsd.rs"]
mod consts;

#[doc(hidden)]
Expand Down
19 changes: 0 additions & 19 deletions ioctl-sys/src/platform/openbsd.rs

This file was deleted.

101 changes: 101 additions & 0 deletions ioctl-sys/tests/ioctl_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
extern crate ioctl_sys;
extern crate libc;

const TEMP_FILE_PATH: &str = concat!(env!("CARGO_TARGET_TMPDIR"), "/ioctl_test");

// BSD ioctl tests. Shamelessly stolen from the nix crate
#[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "openbsd"))]
mod bsd_ioctls {
use std::fs::File;
use std::{io, mem};
use std::os::fd::IntoRawFd;
use std::os::raw::c_int;

use libc::termios;


// From:
// macOS: /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/ttycom.h
// FreeBSD, OpenBSD:
use ioctl_sys::ioctl;
use TEMP_FILE_PATH;
ioctl!(none tiocnxcl with b't', 14);
ioctl!(read tiocgeta with b't', 19; termios);
ioctl!(write tiocseta with b't', 20; termios);

// Common function
fn test_ioctl(
expected_err_code: Option<(c_int, &str)>,
f: fn(temp_file_fd: c_int, stdout_fd: c_int) -> c_int
) {
let temp_file_fd = File::create(TEMP_FILE_PATH)
.expect("create temp file").into_raw_fd();
let stdout_fd = 1;
let result = f(temp_file_fd, stdout_fd);
match expected_err_code {
Some((code, name)) => {
let fail_err_code = io::Error::last_os_error().raw_os_error()
.expect("ioctl error code");
assert_eq!(result, -1, "expected fail code (-1)");
assert_eq!(fail_err_code, code, "expected error code {} ({})", name, code);
},
None => {
assert_eq!(result, 0, "expected success code (0)");
}
}
}

#[test]
fn test_ioctl_none_fail() {
test_ioctl(Some((25, "ERRNOTTY")), |file_fd, _stdout_fd| {
unsafe { tiocnxcl( file_fd ) }
});
}

#[test]
fn test_ioctl_read_fail() {
test_ioctl(Some((25, "ERRNOTTY")), |file_fd, _stdout_fd| {
let mut termios = unsafe { mem::zeroed() };
unsafe { tiocgeta( file_fd, &mut termios ) }
});
}

#[test]
fn test_ioctl_write_fail() {
test_ioctl(Some((25, "ERRNOTTY")), |file_fd, _stdout_fd| {
let mut termios = unsafe { mem::zeroed() };
unsafe { tiocseta( file_fd, &mut termios ) }
});
}

// Ignored because it need doesn't work on GitHub actions
#[ignore]
#[test]
fn test_ioctl_none_pass() {
test_ioctl(Some((25, "ERRNOTTY")), |_file_fd, stdout_fd| {
unsafe { tiocnxcl( stdout_fd ) }
});
}

// Ignored because it need doesn't work on GitHub actions
#[ignore]
#[test]
fn test_ioctl_read_pass() {
test_ioctl(Some((25, "ERRNOTTY")), |_file_fd, stdout_fd| {
let mut termios = unsafe { mem::zeroed() };
unsafe { tiocgeta( stdout_fd, &mut termios ) }
});
}

// Ignored because it need doesn't work on GitHub actions
// Also ignored because TIOCSETA with zeroed termios will destroy your current terminal session
// If you decide to test it, just restart your terminal after
#[ignore]
#[test]
fn test_ioctl_write_pass() {
test_ioctl(Some((25, "ERRNOTTY")), |_file_fd, stdout_fd| {
let mut termios = unsafe { mem::zeroed() };
unsafe { tiocseta( stdout_fd, &mut termios ) }
});
}
}