Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add makedev for the BSDs #2891

Merged
merged 1 commit into from Sep 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions libc-test/Cargo.toml
Expand Up @@ -66,6 +66,11 @@ name = "cmsg"
path = "test/cmsg.rs"
harness = true

[[test]]
name = "makedev"
path = "test/makedev.rs"
harness = true

[[test]]
name = "errqueue"
path = "test/errqueue.rs"
Expand Down
9 changes: 9 additions & 0 deletions libc-test/build.rs
Expand Up @@ -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");
Expand Down
13 changes: 13 additions & 0 deletions 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);
}
103 changes: 103 additions & 0 deletions 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);
}
}
}
}
22 changes: 11 additions & 11 deletions src/fuchsia/mod.rs
Expand Up @@ -3235,17 +3235,6 @@ f! {
minor as ::c_uint
}

pub fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
let major = major as ::dev_t;
let minor = minor as ::dev_t;
let mut dev = 0;
dev |= (major & 0x00000fff) << 8;
dev |= (major & 0xfffff000) << 32;
dev |= (minor & 0x000000ff) << 0;
dev |= (minor & 0xffffff00) << 12;
dev
}

pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar {
cmsg.offset(1) as *mut c_uchar
}
Expand Down Expand Up @@ -3322,6 +3311,17 @@ safe_f! {
pub {const} fn QCMD(cmd: ::c_int, type_: ::c_int) -> ::c_int {
(cmd << 8) | (type_ & 0x00ff)
}

pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
let major = major as ::dev_t;
let minor = minor as ::dev_t;
let mut dev = 0;
dev |= (major & 0x00000fff) << 8;
dev |= (major & 0xfffff000) << 32;
dev |= (minor & 0x000000ff) << 0;
dev |= (minor & 0xffffff00) << 12;
dev
}
}

fn __CMSG_LEN(cmsg: *const cmsghdr) -> ::ssize_t {
Expand Down
9 changes: 9 additions & 0 deletions src/unix/bsd/freebsdlike/dragonfly/mod.rs
Expand Up @@ -1571,6 +1571,15 @@ safe_f! {
pub {const} fn WIFSIGNALED(status: ::c_int) -> bool {
(status & 0o177) != 0o177 && (status & 0o177) != 0
}

pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
let major = major as ::dev_t;
let minor = minor as ::dev_t;
let mut dev = 0;
dev |= major << 8;
dev |= minor;
dev
}
}

extern "C" {
Expand Down
8 changes: 8 additions & 0 deletions src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs
Expand Up @@ -434,6 +434,14 @@ pub const MINCORE_SUPER: ::c_int = 0x20;
/// max length of devicename
pub const SPECNAMELEN: ::c_int = 63;

safe_f! {
pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
let major = major as ::dev_t;
let minor = minor as ::dev_t;
(major << 8) | minor
}
}

extern "C" {
// Return type ::c_int was removed in FreeBSD 12
pub fn setgrent() -> ::c_int;
Expand Down
13 changes: 13 additions & 0 deletions src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs
Expand Up @@ -449,6 +449,19 @@ pub const KI_NSPARE_PTR: usize = 6;

pub const MINCORE_SUPER: ::c_int = 0x20;

safe_f! {
pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
let major = major as ::dev_t;
let minor = minor as ::dev_t;
let mut dev = 0;
dev |= ((major & 0xffffff00) as dev_t) << 32;
dev |= ((major & 0x000000ff) as dev_t) << 8;
dev |= ((minor & 0x0000ff00) as dev_t) << 24;
dev |= ((minor & 0xffff00ff) as dev_t) << 0;
dev
}
}

extern "C" {
pub fn setgrent();
pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int;
Expand Down
13 changes: 13 additions & 0 deletions src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs
Expand Up @@ -468,6 +468,19 @@ pub const DOMAINSET_POLICY_INTERLEAVE: ::c_int = 4;

pub const MINCORE_SUPER: ::c_int = 0x20;

safe_f! {
pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
let major = major as ::dev_t;
let minor = minor as ::dev_t;
let mut dev = 0;
dev |= ((major & 0xffffff00) as dev_t) << 32;
dev |= ((major & 0x000000ff) as dev_t) << 8;
dev |= ((minor & 0x0000ff00) as dev_t) << 24;
dev |= ((minor & 0xffff00ff) as dev_t) << 0;
dev
}
}

extern "C" {
pub fn setgrent();
pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int;
Expand Down
13 changes: 13 additions & 0 deletions src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs
Expand Up @@ -468,6 +468,19 @@ pub const DOMAINSET_POLICY_INTERLEAVE: ::c_int = 4;

pub const MINCORE_SUPER: ::c_int = 0x60;

safe_f! {
pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
let major = major as ::dev_t;
let minor = minor as ::dev_t;
let mut dev = 0;
dev |= ((major & 0xffffff00) as dev_t) << 32;
dev |= ((major & 0x000000ff) as dev_t) << 8;
dev |= ((minor & 0x0000ff00) as dev_t) << 24;
dev |= ((minor & 0xffff00ff) as dev_t) << 0;
dev
}
}

extern "C" {
pub fn setgrent();
pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int;
Expand Down
10 changes: 10 additions & 0 deletions src/unix/bsd/netbsdlike/netbsd/mod.rs
Expand Up @@ -2351,6 +2351,16 @@ safe_f! {
pub {const} fn WIFCONTINUED(status: ::c_int) -> bool {
status == 0xffff
}

pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
let major = major as ::dev_t;
let minor = minor as ::dev_t;
let mut dev = 0;
dev |= (major << 8) & 0x000ff00;
dev |= (minor << 12) & 0xfff00000;
dev |= minor & 0xff;
dev
}
}

extern "C" {
Expand Down
10 changes: 10 additions & 0 deletions src/unix/bsd/netbsdlike/openbsd/mod.rs
Expand Up @@ -1695,6 +1695,16 @@ safe_f! {
pub {const} fn WIFCONTINUED(status: ::c_int) -> bool {
(status & 0o177777) == 0o177777
}

pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
let major = major as ::dev_t;
let minor = minor as ::dev_t;
let mut dev = 0;
dev |= (major & 0xff) << 8;
dev |= minor & 0xff;
dev |= (minor & 0xffff00) << 8;
dev
}
}

extern "C" {
Expand Down
15 changes: 9 additions & 6 deletions src/unix/linux_like/android/mod.rs
Expand Up @@ -2781,12 +2781,6 @@ f! {
pub fn minor(dev: ::dev_t) -> ::c_int {
((dev & 0xff) | ((dev >> 12) & 0xfff00)) as ::c_int
}
pub fn makedev(ma: ::c_int, mi: ::c_int) -> ::dev_t {
let ma = ma as ::dev_t;
let mi = mi as ::dev_t;
((ma & 0xfff) << 8) | (mi & 0xff) | ((mi & 0xfff00) << 12)
}

pub fn NLA_ALIGN(len: ::c_int) -> ::c_int {
return ((len) + NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1)
}
Expand All @@ -2796,6 +2790,15 @@ f! {
}
}

safe_f! {
pub {const} fn makedev(ma: ::c_uint, mi: ::c_uint) -> ::dev_t {
let ma = ma as ::dev_t;
let mi = mi as ::dev_t;
((ma & 0xfff) << 8) | (mi & 0xff) | ((mi & 0xfff00) << 12)
}

}

extern "C" {
pub fn getrlimit64(resource: ::c_int, rlim: *mut rlimit64) -> ::c_int;
pub fn setrlimit64(resource: ::c_int, rlim: *const rlimit64) -> ::c_int;
Expand Down
4 changes: 3 additions & 1 deletion src/unix/linux_like/emscripten/mod.rs
Expand Up @@ -1740,8 +1740,10 @@ f! {
minor |= (dev & 0xffffff00) >> 12;
minor as ::c_uint
}
}

pub fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
safe_f! {
pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
let major = major as ::dev_t;
let minor = minor as ::dev_t;
let mut dev = 0;
Expand Down
24 changes: 13 additions & 11 deletions src/unix/linux_like/linux/mod.rs
Expand Up @@ -3351,17 +3351,6 @@ f! {
minor as ::c_uint
}

pub fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
let major = major as ::dev_t;
let minor = minor as ::dev_t;
let mut dev = 0;
dev |= (major & 0x00000fff) << 8;
dev |= (major & 0xfffff000) << 32;
dev |= (minor & 0x000000ff) << 0;
dev |= (minor & 0xffffff00) << 12;
dev
}

pub fn IPTOS_TOS(tos: u8) -> u8 {
tos & IPTOS_TOS_MASK
}
Expand Down Expand Up @@ -3403,6 +3392,19 @@ f! {
}
}

safe_f! {
pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
let major = major as ::dev_t;
let minor = minor as ::dev_t;
let mut dev = 0;
dev |= (major & 0x00000fff) << 8;
dev |= (major & 0xfffff000) << 32;
dev |= (minor & 0x000000ff) << 0;
dev |= (minor & 0xffffff00) << 12;
dev
}
}

cfg_if! {
if #[cfg(not(target_env = "uclibc"))] {
extern "C" {
Expand Down