summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-09-09 13:47:17 +0000
committerbors <bors@rust-lang.org>2022-09-09 13:47:17 +0000
commit6eee580b51455131b10b780087025379a591ceb6 (patch)
tree289638e4531d6ef89f05c20b1a317f486037fa33
parentfb16d18481076c35e3700e0ccd17eefdfb1ba3bf (diff)
parent5e6d9c4a92fd563f7e2e58a1e2889ccc4a87ff44 (diff)
downloadrust-libc-6eee580b51455131b10b780087025379a591ceb6.tar.gz
Auto merge of #2891 - asomers:makedev, r=JohnTitor
Add makedev for the BSDs Also, make Linux's makedev function safe and const.
-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 840de21713..1ef846aed8 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 54ca083279..512d5f0ffb 100644
--- a/src/unix/linux_like/linux/mod.rs
+++ b/src/unix/linux_like/linux/mod.rs
@@ -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
}
@@ -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" {