diff options
author | Alan Somers <asomers@gmail.com> | 2022-08-26 14:15:53 -0600 |
---|---|---|
committer | Alan Somers <asomers@gmail.com> | 2022-09-07 06:50:04 -0600 |
commit | 5e6d9c4a92fd563f7e2e58a1e2889ccc4a87ff44 (patch) | |
tree | 299539f0a439c19986d7a57607d16e0948478671 /libc-test | |
parent | 75dd59edacd4251a7c9e8e5cc748192adcf708aa (diff) | |
download | rust-libc-5e6d9c4a92fd563f7e2e58a1e2889ccc4a87ff44.tar.gz |
Add makedev for the BSDs
Also, make makedev function safe and const on all platforms.
On Android, change the arguments from signed to unsigned integers to
match the other platforms. The C makedev is a macro, so the
signededness is undefined.
Add an integration test for makedev, too, since it's a macro that we
must reimplement.
Diffstat (limited to 'libc-test')
-rw-r--r-- | libc-test/Cargo.toml | 5 | ||||
-rw-r--r-- | libc-test/build.rs | 9 | ||||
-rw-r--r-- | libc-test/src/makedev.c | 13 | ||||
-rw-r--r-- | libc-test/test/makedev.rs | 103 |
4 files changed, 130 insertions, 0 deletions
diff --git a/libc-test/Cargo.toml b/libc-test/Cargo.toml index 0a2778d1dc..bbd724e27f 100644 --- a/libc-test/Cargo.toml +++ b/libc-test/Cargo.toml @@ -67,6 +67,11 @@ path = "test/cmsg.rs" harness = true [[test]] +name = "makedev" +path = "test/makedev.rs" +harness = true + +[[test]] name = "errqueue" path = "test/errqueue.rs" harness = true diff --git a/libc-test/build.rs b/libc-test/build.rs index ba428fc730..9afbf4bed5 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -22,6 +22,15 @@ fn do_cc() { } cmsg.compile("cmsg"); } + + if target.contains("linux") + || target.contains("android") + || target.contains("emscripten") + || target.contains("fuchsia") + || target.contains("bsd") + { + cc::Build::new().file("src/makedev.c").compile("makedev"); + } } if target.contains("android") || target.contains("linux") { cc::Build::new().file("src/errqueue.c").compile("errqueue"); diff --git a/libc-test/src/makedev.c b/libc-test/src/makedev.c new file mode 100644 index 0000000000..7f99d60728 --- /dev/null +++ b/libc-test/src/makedev.c @@ -0,0 +1,13 @@ +#include <sys/types.h> +#if defined(__linux__) || defined(__EMSCRIPTEN__) +#include <sys/sysmacros.h> +#endif + +// Since makedev is a macro instead of a function, it isn't available to FFI. +// libc must reimplement it, which is error-prone. This file provides FFI +// access to the actual macro so it can be tested against the Rust +// reimplementation. + +dev_t makedev_ffi(unsigned major, unsigned minor) { + return makedev(major, minor); +} diff --git a/libc-test/test/makedev.rs b/libc-test/test/makedev.rs new file mode 100644 index 0000000000..c9a92aa83e --- /dev/null +++ b/libc-test/test/makedev.rs @@ -0,0 +1,103 @@ +//! Compare libc's makdev function against the actual C macros, for various +//! inputs. + +extern crate libc; + +#[cfg(any( + target_os = "android", + target_os = "dragonfly", + target_os = "emscripten", + target_os = "freebsd", + target_os = "fuchsia", + target_os = "linux", + target_os = "netbsd", + target_os = "openbsd", +))] +mod t { + use libc::{self, c_uint, dev_t}; + + extern "C" { + pub fn makedev_ffi(major: c_uint, minor: c_uint) -> dev_t; + } + + fn compare(major: c_uint, minor: c_uint) { + let expected = unsafe { makedev_ffi(major, minor) }; + assert_eq!(libc::makedev(major, minor), expected); + } + + // Every OS should be able to handle 8 bit major and minor numbers + #[test] + fn test_8bits() { + for major in 0..256 { + for minor in 0..256 { + compare(major, minor); + } + } + } + + // Android allows 12 bits for major and 20 for minor + #[test] + #[cfg(target_os = "android")] + fn test_android_like() { + for major in [0, 1, 255, 256, 4095] { + for minor_exp in [1, 8, 16] { + for minor in [(1 << minor_exp) - 1, (1 << minor_exp)] { + compare(major, minor); + } + } + compare(major, (1 << 20) - 1); + } + } + + // These OSes allow 32 bits for minor, but only 8 for major + #[test] + #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd",))] + fn test_fbsd11_like() { + for major in [0, 1, 255] { + for minor_exp in [1, 8, 16, 24, 31] { + for minor in [(1 << minor_exp) - 1, (1 << minor_exp)] { + compare(major, minor); + } + } + compare(major, c_uint::MAX); + } + } + + // OpenBSD allows 8 bits for major and 24 for minor + #[test] + #[cfg(target_os = "openbsd")] + fn test_openbsd_like() { + for major in [0, 1, 255] { + for minor_exp in [1, 8, 16] { + for minor in [(1 << minor_exp) - 1, (1 << minor_exp)] { + compare(major, minor); + } + } + compare(major, (1 << 24) - 1); + } + } + + // These OSes allow 32 bits for both minor and major + #[cfg(any( + target_os = "empscripten", + target_os = "freebsd", + target_os = "fuchsia", + target_os = "linux", + ))] + #[test] + fn test_fbsd12_like() { + if std::mem::size_of::<dev_t>() >= 8 { + for major_exp in [0, 16, 24, 31] { + for major in [(1 << major_exp) - 1, (1 << major_exp)] { + for minor_exp in [1, 8, 16, 24, 31] { + for minor in [(1 << minor_exp) - 1, (1 << minor_exp)] { + compare(major, minor); + } + } + compare(major, c_uint::MAX); + } + compare(c_uint::MAX, c_uint::MAX); + } + } + } +} |