summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Somers <asomers@gmail.com>2022-08-26 14:15:53 -0600
committerAlan Somers <asomers@gmail.com>2022-09-07 06:50:04 -0600
commit5e6d9c4a92fd563f7e2e58a1e2889ccc4a87ff44 (patch)
tree299539f0a439c19986d7a57607d16e0948478671
parent75dd59edacd4251a7c9e8e5cc748192adcf708aa (diff)
downloadrust-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.
-rw-r--r--libc-test/Cargo.toml5
-rw-r--r--libc-test/build.rs9
-rw-r--r--libc-test/src/makedev.c13
-rw-r--r--libc-test/test/makedev.rs103
-rw-r--r--src/fuchsia/mod.rs22
-rw-r--r--src/unix/bsd/freebsdlike/dragonfly/mod.rs9
-rw-r--r--src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs8
-rw-r--r--src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs13
-rw-r--r--src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs13
-rw-r--r--src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs13
-rw-r--r--src/unix/bsd/netbsdlike/netbsd/mod.rs10
-rw-r--r--src/unix/bsd/netbsdlike/openbsd/mod.rs10
-rw-r--r--src/unix/linux_like/android/mod.rs15
-rw-r--r--src/unix/linux_like/emscripten/mod.rs4
-rw-r--r--src/unix/linux_like/linux/mod.rs24
15 files changed, 242 insertions, 29 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);
+ }
+ }
+ }
+}
diff --git a/src/fuchsia/mod.rs b/src/fuchsia/mod.rs
index 4a18a8daab..c08d48c339 100644
--- a/src/fuchsia/mod.rs
+++ b/src/fuchsia/mod.rs
@@ -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
}
@@ -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 {
diff --git a/src/unix/bsd/freebsdlike/dragonfly/mod.rs b/src/unix/bsd/freebsdlike/dragonfly/mod.rs
index df7719b4b9..2935534f0d 100644
--- a/src/unix/bsd/freebsdlike/dragonfly/mod.rs
+++ b/src/unix/bsd/freebsdlike/dragonfly/mod.rs
@@ -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" {
diff --git a/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs b/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs
index 1af555fa36..aaa0435847 100644
--- a/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs
+++ b/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs
@@ -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;
diff --git a/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs b/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs
index 848db33993..e7f8ad7802 100644
--- a/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs
+++ b/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs
@@ -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;
diff --git a/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs b/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs
index a929f9d290..bcd09006b5 100644
--- a/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs
+++ b/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs
@@ -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;
diff --git a/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs b/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs
index c655d555d9..9da6696048 100644
--- a/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs
+++ b/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs
@@ -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;
diff --git a/src/unix/bsd/netbsdlike/netbsd/mod.rs b/src/unix/bsd/netbsdlike/netbsd/mod.rs
index d12fd07301..82784bbbfc 100644
--- a/src/unix/bsd/netbsdlike/netbsd/mod.rs
+++ b/src/unix/bsd/netbsdlike/netbsd/mod.rs
@@ -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" {
diff --git a/src/unix/bsd/netbsdlike/openbsd/mod.rs b/src/unix/bsd/netbsdlike/openbsd/mod.rs
index 1910f24a46..ba26f92431 100644
--- a/src/unix/bsd/netbsdlike/openbsd/mod.rs
+++ b/src/unix/bsd/netbsdlike/openbsd/mod.rs
@@ -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" {
diff --git a/src/unix/linux_like/android/mod.rs b/src/unix/linux_like/android/mod.rs
index cfd229a474..8a21147def 100644
--- a/src/unix/linux_like/android/mod.rs
+++ b/src/unix/linux_like/android/mod.rs
@@ -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)
}
@@ -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;
diff --git a/src/unix/linux_like/emscripten/mod.rs b/src/unix/linux_like/emscripten/mod.rs
index 31d0ebf25b..11fbb31c38 100644
--- a/src/unix/linux_like/emscripten/mod.rs
+++ b/src/unix/linux_like/emscripten/mod.rs
@@ -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;
diff --git a/src/unix/linux_like/linux/mod.rs b/src/unix/linux_like/linux/mod.rs
index 6d078aac32..026c5307c2 100644
--- a/src/unix/linux_like/linux/mod.rs
+++ b/src/unix/linux_like/linux/mod.rs
@@ -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
}
@@ -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" {