Skip to content

Commit

Permalink
Auto merge of #2891 - asomers:makedev, r=JohnTitor
Browse files Browse the repository at this point in the history
Add makedev for the BSDs

Also, make Linux's makedev function safe and const.
  • Loading branch information
bors committed Sep 9, 2022
2 parents fb16d18 + 5e6d9c4 commit 6eee580
Show file tree
Hide file tree
Showing 15 changed files with 242 additions and 29 deletions.
5 changes: 5 additions & 0 deletions libc-test/Cargo.toml
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -3570,17 +3570,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 @@ -3622,6 +3611,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

0 comments on commit 6eee580

Please sign in to comment.