1 //! Compare libc's makedev, major, minor functions against the actual C macros, for various
2 //! inputs.
3
4 #![cfg(any(
5 target_os = "android",
6 target_os = "dragonfly",
7 target_os = "emscripten",
8 target_os = "freebsd",
9 target_os = "fuchsia",
10 target_os = "linux",
11 target_os = "netbsd",
12 target_os = "openbsd",
13 target_os = "cygwin",
14 ))]
15
16 use libc::{self, c_uint, dev_t};
17
18 cfg_if::cfg_if! {
19 if #[cfg(any(target_os = "solaris", target_os = "illumos"))] {
20 pub type MajorRetType = libc::major_t;
21 pub type MinorRetType = libc::minor_t;
22 } else if #[cfg(any(
23 target_os = "linux",
24 target_os = "l4re",
25 target_os = "emscripten",
26 target_os = "fuchsia",
27 target_os = "nto",
28 target_os = "hurd",
29 target_os = "openbsd",
30 target_os = "cygwin",
31 ))] {
32 pub type MajorRetType = c_uint;
33 pub type MinorRetType = c_uint;
34 } else if #[cfg(any(
35 target_os = "android",
36 target_os = "dragonfly",
37 target_os = "netbsd",
38 target_os = "freebsd",
39 ))] {
40 pub type MajorRetType = libc::c_int;
41 pub type MinorRetType = libc::c_int;
42 } else if #[cfg(any(
43 target_os = "macos",
44 target_os = "ios",
45 target_os = "tvos",
46 target_os = "watchos",
47 target_os = "visionos"
48 ))] {
49 pub type MajorRetType = i32;
50 pub type MinorRetType = i32;
51 }
52 }
53
54 extern "C" {
makedev_ffi(major: c_uint, minor: c_uint) -> dev_t55 pub fn makedev_ffi(major: c_uint, minor: c_uint) -> dev_t;
major_ffi(dev: dev_t) -> c_uint56 pub fn major_ffi(dev: dev_t) -> c_uint;
minor_ffi(dev: dev_t) -> c_uint57 pub fn minor_ffi(dev: dev_t) -> c_uint;
58 }
59
compare(major: c_uint, minor: c_uint)60 fn compare(major: c_uint, minor: c_uint) {
61 let dev = unsafe { makedev_ffi(major, minor) };
62 assert_eq!(libc::makedev(major, minor), dev);
63 let major = unsafe { major_ffi(dev) };
64 assert_eq!(libc::major(dev), major as MajorRetType);
65 let minor = unsafe { minor_ffi(dev) };
66 assert_eq!(libc::minor(dev), minor as MinorRetType);
67 }
68
69 // Every OS should be able to handle 8 bit major and minor numbers
70 #[test]
test_8bits()71 fn test_8bits() {
72 for major in 0..256 {
73 for minor in 0..256 {
74 compare(major, minor);
75 }
76 }
77 }
78
79 // Android allows 12 bits for major and 20 for minor
80 #[test]
81 #[cfg(target_os = "android")]
test_android_like()82 fn test_android_like() {
83 for major in [0, 1, 255, 256, 4095] {
84 for minor_exp in [1, 8, 16] {
85 for minor in [(1 << minor_exp) - 1, (1 << minor_exp)] {
86 compare(major, minor);
87 }
88 }
89 compare(major, (1 << 20) - 1);
90 }
91 }
92
93 // These OSes allow 32 bits for minor, but only 8 for major
94 #[test]
95 #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd",))]
test_fbsd11_like()96 fn test_fbsd11_like() {
97 for major in [0, 1, 255] {
98 for minor_exp in [1, 8, 16, 24, 31] {
99 for minor in [(1 << minor_exp) - 1, (1 << minor_exp)] {
100 compare(major, minor);
101 }
102 }
103 compare(major, c_uint::MAX);
104 }
105 }
106
107 // OpenBSD allows 8 bits for major and 24 for minor
108 #[test]
109 #[cfg(target_os = "openbsd")]
test_openbsd_like()110 fn test_openbsd_like() {
111 for major in [0, 1, 255] {
112 for minor_exp in [1, 8, 16] {
113 for minor in [(1 << minor_exp) - 1, (1 << minor_exp)] {
114 compare(major, minor);
115 }
116 }
117 compare(major, (1 << 24) - 1);
118 }
119 }
120
121 // These OSes allow 32 bits for both minor and major
122 #[cfg(any(
123 target_os = "emscripten",
124 target_os = "freebsd",
125 target_os = "fuchsia",
126 target_os = "linux",
127 target_os = "cygwin",
128 ))]
129 #[test]
test_fbsd12_like()130 fn test_fbsd12_like() {
131 if size_of::<dev_t>() >= 8 {
132 for major_exp in [0, 16, 24, 31] {
133 for major in [(1 << major_exp) - 1, (1 << major_exp)] {
134 for minor_exp in [1, 8, 16, 24, 31] {
135 for minor in [(1 << minor_exp) - 1, (1 << minor_exp)] {
136 compare(major, minor);
137 }
138 }
139 compare(major, c_uint::MAX);
140 }
141 compare(c_uint::MAX, c_uint::MAX);
142 }
143 }
144 }
145