Skip to content

Commit fe38ca1

Browse files
committed
Auto merge of #2891 - asomers:makedev, r=<try>
Add makedev for the BSDs Also, make Linux's makedev function safe and const.
2 parents 6b36b18 + f26839a commit fe38ca1

File tree

15 files changed

+242
-29
lines changed

15 files changed

+242
-29
lines changed

libc-test/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ name = "cmsg"
6666
path = "test/cmsg.rs"
6767
harness = true
6868

69+
[[test]]
70+
name = "makedev"
71+
path = "test/makedev.rs"
72+
harness = true
73+
6974
[[test]]
7075
name = "errqueue"
7176
path = "test/errqueue.rs"

libc-test/build.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@ fn do_cc() {
2222
}
2323
cmsg.compile("cmsg");
2424
}
25+
26+
if target.contains("linux")
27+
|| target.contains("android")
28+
|| target.contains("emscripten")
29+
|| target.contains("fuchsia")
30+
|| target.contains("bsd")
31+
{
32+
cc::Build::new().file("src/makedev.c").compile("makedev");
33+
}
2534
}
2635
if target.contains("android") || target.contains("linux") {
2736
cc::Build::new().file("src/errqueue.c").compile("errqueue");

libc-test/src/makedev.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <sys/types.h>
2+
#if defined(__linux__) || defined(__EMSCRIPTEN__)
3+
#include <sys/sysmacros.h>
4+
#endif
5+
6+
// Since makedev is a macro instead of a function, it isn't available to FFI.
7+
// libc must reimplement it, which is error-prone. This file provides FFI
8+
// access to the actual macro so it can be tested against the Rust
9+
// reimplementation.
10+
11+
dev_t makedev_ffi(unsigned major, unsigned minor) {
12+
return makedev(major, minor);
13+
}

libc-test/test/makedev.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//! Compare libc's makdev function against the actual C macros, for various
2+
//! inputs.
3+
4+
extern crate libc;
5+
6+
#[cfg(any(
7+
target_os = "android",
8+
target_os = "dragonfly",
9+
target_os = "emscripten",
10+
target_os = "freebsd",
11+
target_os = "fuchsia",
12+
target_os = "linux",
13+
target_os = "netbsd",
14+
target_os = "openbsd",
15+
))]
16+
mod t {
17+
use libc::{self, c_uint, dev_t};
18+
19+
extern "C" {
20+
pub fn makedev_ffi(major: c_uint, minor: c_uint) -> dev_t;
21+
}
22+
23+
fn compare(major: c_uint, minor: c_uint) {
24+
let expected = unsafe { makedev_ffi(major, minor) };
25+
assert_eq!(libc::makedev(major, minor), expected);
26+
}
27+
28+
// Every OS should be able to handle 8 bit major and minor numbers
29+
#[test]
30+
fn test_8bits() {
31+
for major in 0..256 {
32+
for minor in 0..256 {
33+
compare(major, minor);
34+
}
35+
}
36+
}
37+
38+
// Android allows 12 bits for major and 20 for minor
39+
#[test]
40+
#[cfg(target_os = "android")]
41+
fn test_android_like() {
42+
for major in [0, 1, 255, 256, 4095] {
43+
for minor_exp in [1, 8, 16] {
44+
for minor in [(1 << minor_exp) - 1, (1 << minor_exp)] {
45+
compare(major, minor);
46+
}
47+
}
48+
compare(major, (1 << 20) - 1);
49+
}
50+
}
51+
52+
// These OSes allow 32 bits for minor, but only 8 for major
53+
#[test]
54+
#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd",))]
55+
fn test_fbsd11_like() {
56+
for major in [0, 1, 255] {
57+
for minor_exp in [1, 8, 16, 24, 31] {
58+
for minor in [(1 << minor_exp) - 1, (1 << minor_exp)] {
59+
compare(major, minor);
60+
}
61+
}
62+
compare(major, c_uint::MAX);
63+
}
64+
}
65+
66+
// OpenBSD allows 8 bits for major and 24 for minor
67+
#[test]
68+
#[cfg(target_os = "openbsd")]
69+
fn test_openbsd_like() {
70+
for major in [0, 1, 255] {
71+
for minor_exp in [1, 8, 16] {
72+
for minor in [(1 << minor_exp) - 1, (1 << minor_exp)] {
73+
compare(major, minor);
74+
}
75+
}
76+
compare(major, (1 << 24) - 1);
77+
}
78+
}
79+
80+
// These OSes allow 32 bits for both minor and major
81+
#[cfg(any(
82+
target_os = "empscripten",
83+
target_os = "freebsd",
84+
target_os = "fuchsia",
85+
target_os = "linux",
86+
))]
87+
#[test]
88+
fn test_fbsd12_like() {
89+
if std::mem::size_of::<dev_t>() >= 8 {
90+
for major_exp in [0, 16, 24, 31] {
91+
for major in [(1 << major_exp) - 1, (1 << major_exp)] {
92+
for minor_exp in [1, 8, 16, 24, 31] {
93+
for minor in [(1 << minor_exp) - 1, (1 << minor_exp)] {
94+
compare(major, minor);
95+
}
96+
}
97+
compare(major, c_uint::MAX);
98+
}
99+
compare(c_uint::MAX, c_uint::MAX);
100+
}
101+
}
102+
}
103+
}

src/fuchsia/mod.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3235,17 +3235,6 @@ f! {
32353235
minor as ::c_uint
32363236
}
32373237

3238-
pub fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
3239-
let major = major as ::dev_t;
3240-
let minor = minor as ::dev_t;
3241-
let mut dev = 0;
3242-
dev |= (major & 0x00000fff) << 8;
3243-
dev |= (major & 0xfffff000) << 32;
3244-
dev |= (minor & 0x000000ff) << 0;
3245-
dev |= (minor & 0xffffff00) << 12;
3246-
dev
3247-
}
3248-
32493238
pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar {
32503239
cmsg.offset(1) as *mut c_uchar
32513240
}
@@ -3322,6 +3311,17 @@ safe_f! {
33223311
pub {const} fn QCMD(cmd: ::c_int, type_: ::c_int) -> ::c_int {
33233312
(cmd << 8) | (type_ & 0x00ff)
33243313
}
3314+
3315+
pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
3316+
let major = major as ::dev_t;
3317+
let minor = minor as ::dev_t;
3318+
let mut dev = 0;
3319+
dev |= (major & 0x00000fff) << 8;
3320+
dev |= (major & 0xfffff000) << 32;
3321+
dev |= (minor & 0x000000ff) << 0;
3322+
dev |= (minor & 0xffffff00) << 12;
3323+
dev
3324+
}
33253325
}
33263326

33273327
fn __CMSG_LEN(cmsg: *const cmsghdr) -> ::ssize_t {

src/unix/bsd/freebsdlike/dragonfly/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,6 +1571,15 @@ safe_f! {
15711571
pub {const} fn WIFSIGNALED(status: ::c_int) -> bool {
15721572
(status & 0o177) != 0o177 && (status & 0o177) != 0
15731573
}
1574+
1575+
pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
1576+
let major = major as ::dev_t;
1577+
let minor = minor as ::dev_t;
1578+
let mut dev = 0;
1579+
dev |= major << 8;
1580+
dev |= minor;
1581+
dev
1582+
}
15741583
}
15751584

15761585
extern "C" {

src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,14 @@ pub const MINCORE_SUPER: ::c_int = 0x20;
434434
/// max length of devicename
435435
pub const SPECNAMELEN: ::c_int = 63;
436436

437+
safe_f! {
438+
pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
439+
let major = major as ::dev_t;
440+
let minor = minor as ::dev_t;
441+
(major << 8) | minor
442+
}
443+
}
444+
437445
extern "C" {
438446
// Return type ::c_int was removed in FreeBSD 12
439447
pub fn setgrent() -> ::c_int;

src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,19 @@ pub const KI_NSPARE_PTR: usize = 6;
449449

450450
pub const MINCORE_SUPER: ::c_int = 0x20;
451451

452+
safe_f! {
453+
pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
454+
let major = major as ::dev_t;
455+
let minor = minor as ::dev_t;
456+
let mut dev = 0;
457+
dev |= ((major & 0xffffff00) as dev_t) << 32;
458+
dev |= ((major & 0x000000ff) as dev_t) << 8;
459+
dev |= ((minor & 0x0000ff00) as dev_t) << 24;
460+
dev |= ((minor & 0xffff00ff) as dev_t) << 0;
461+
dev
462+
}
463+
}
464+
452465
extern "C" {
453466
pub fn setgrent();
454467
pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int;

src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,19 @@ pub const DOMAINSET_POLICY_INTERLEAVE: ::c_int = 4;
468468

469469
pub const MINCORE_SUPER: ::c_int = 0x20;
470470

471+
safe_f! {
472+
pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
473+
let major = major as ::dev_t;
474+
let minor = minor as ::dev_t;
475+
let mut dev = 0;
476+
dev |= ((major & 0xffffff00) as dev_t) << 32;
477+
dev |= ((major & 0x000000ff) as dev_t) << 8;
478+
dev |= ((minor & 0x0000ff00) as dev_t) << 24;
479+
dev |= ((minor & 0xffff00ff) as dev_t) << 0;
480+
dev
481+
}
482+
}
483+
471484
extern "C" {
472485
pub fn setgrent();
473486
pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int;

src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,19 @@ pub const DOMAINSET_POLICY_INTERLEAVE: ::c_int = 4;
468468

469469
pub const MINCORE_SUPER: ::c_int = 0x60;
470470

471+
safe_f! {
472+
pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
473+
let major = major as ::dev_t;
474+
let minor = minor as ::dev_t;
475+
let mut dev = 0;
476+
dev |= ((major & 0xffffff00) as dev_t) << 32;
477+
dev |= ((major & 0x000000ff) as dev_t) << 8;
478+
dev |= ((minor & 0x0000ff00) as dev_t) << 24;
479+
dev |= ((minor & 0xffff00ff) as dev_t) << 0;
480+
dev
481+
}
482+
}
483+
471484
extern "C" {
472485
pub fn setgrent();
473486
pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int;

src/unix/bsd/netbsdlike/netbsd/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2351,6 +2351,16 @@ safe_f! {
23512351
pub {const} fn WIFCONTINUED(status: ::c_int) -> bool {
23522352
status == 0xffff
23532353
}
2354+
2355+
pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
2356+
let major = major as ::dev_t;
2357+
let minor = minor as ::dev_t;
2358+
let mut dev = 0;
2359+
dev |= (major << 8) & 0x000ff00;
2360+
dev |= (minor << 12) & 0xfff00000;
2361+
dev |= minor & 0xff;
2362+
dev
2363+
}
23542364
}
23552365

23562366
extern "C" {

src/unix/bsd/netbsdlike/openbsd/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,6 +1695,16 @@ safe_f! {
16951695
pub {const} fn WIFCONTINUED(status: ::c_int) -> bool {
16961696
(status & 0o177777) == 0o177777
16971697
}
1698+
1699+
pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
1700+
let major = major as ::dev_t;
1701+
let minor = minor as ::dev_t;
1702+
let mut dev = 0;
1703+
dev |= (major & 0xff) << 8;
1704+
dev |= (minor & 0xff);
1705+
dev |= (minor & 0xffff00) << 8;
1706+
dev
1707+
}
16981708
}
16991709

17001710
extern "C" {

src/unix/linux_like/android/mod.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2781,12 +2781,6 @@ f! {
27812781
pub fn minor(dev: ::dev_t) -> ::c_int {
27822782
((dev & 0xff) | ((dev >> 12) & 0xfff00)) as ::c_int
27832783
}
2784-
pub fn makedev(ma: ::c_int, mi: ::c_int) -> ::dev_t {
2785-
let ma = ma as ::dev_t;
2786-
let mi = mi as ::dev_t;
2787-
((ma & 0xfff) << 8) | (mi & 0xff) | ((mi & 0xfff00) << 12)
2788-
}
2789-
27902784
pub fn NLA_ALIGN(len: ::c_int) -> ::c_int {
27912785
return ((len) + NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1)
27922786
}
@@ -2796,6 +2790,15 @@ f! {
27962790
}
27972791
}
27982792

2793+
safe_f! {
2794+
pub {const} fn makedev(ma: ::c_uint, mi: ::c_uint) -> ::dev_t {
2795+
let ma = ma as ::dev_t;
2796+
let mi = mi as ::dev_t;
2797+
((ma & 0xfff) << 8) | (mi & 0xff) | ((mi & 0xfff00) << 12)
2798+
}
2799+
2800+
}
2801+
27992802
extern "C" {
28002803
pub fn getrlimit64(resource: ::c_int, rlim: *mut rlimit64) -> ::c_int;
28012804
pub fn setrlimit64(resource: ::c_int, rlim: *const rlimit64) -> ::c_int;

src/unix/linux_like/emscripten/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1740,8 +1740,10 @@ f! {
17401740
minor |= (dev & 0xffffff00) >> 12;
17411741
minor as ::c_uint
17421742
}
1743+
}
17431744

1744-
pub fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
1745+
safe_f! {
1746+
pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
17451747
let major = major as ::dev_t;
17461748
let minor = minor as ::dev_t;
17471749
let mut dev = 0;

src/unix/linux_like/linux/mod.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3570,17 +3570,6 @@ f! {
35703570
minor as ::c_uint
35713571
}
35723572

3573-
pub fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
3574-
let major = major as ::dev_t;
3575-
let minor = minor as ::dev_t;
3576-
let mut dev = 0;
3577-
dev |= (major & 0x00000fff) << 8;
3578-
dev |= (major & 0xfffff000) << 32;
3579-
dev |= (minor & 0x000000ff) << 0;
3580-
dev |= (minor & 0xffffff00) << 12;
3581-
dev
3582-
}
3583-
35843573
pub fn IPTOS_TOS(tos: u8) -> u8 {
35853574
tos & IPTOS_TOS_MASK
35863575
}
@@ -3622,6 +3611,19 @@ f! {
36223611
}
36233612
}
36243613

3614+
safe_f! {
3615+
pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
3616+
let major = major as ::dev_t;
3617+
let minor = minor as ::dev_t;
3618+
let mut dev = 0;
3619+
dev |= (major & 0x00000fff) << 8;
3620+
dev |= (major & 0xfffff000) << 32;
3621+
dev |= (minor & 0x000000ff) << 0;
3622+
dev |= (minor & 0xffffff00) << 12;
3623+
dev
3624+
}
3625+
}
3626+
36253627
cfg_if! {
36263628
if #[cfg(not(target_env = "uclibc"))] {
36273629
extern "C" {

0 commit comments

Comments
 (0)