Description
I want to ask about the makedev
function signature. In the macOS implementation of libc
crate, major
and minor
arguments are signed. This is consistent with the return type of major
and minor
functions.
pub {const} fn makedev(major: i32, minor: i32) -> dev_t {
(major << 24) | minor
}
pub {const} fn major(dev: dev_t) -> i32 {
(dev >> 24) & 0xff
}
pub {const} fn minor(dev: dev_t) -> i32 {
dev & 0xffffff
}
However, Apple declares major
and minor
arguments as unsigned in their documentation.
https://developer.apple.com/documentation/kernel/1547212-makedev
While the major
/minor
return types are still signed.
https://developer.apple.com/documentation/kernel/1547203-major
https://developer.apple.com/documentation/kernel/1547204-minor
It is technically Objective-C documentation and also the actual definitions in <sys/types.h> are just macros, so strictly speaking the argument types to makedev
are not well defined.
#define major(x) ((int32_t)(((u_int32_t)(x) >> 24) & 0xff))
#define minor(x) ((int32_t)((x) & 0xffffff))
#define makedev(x, y) ((dev_t)(((x) << 24) | (y)))
I suppose it would be logical to assume they're signed since major
and minor
macros use an explicit cast to a signed type, but here we have a contradicting documentation by Apple.
Interestingly, if I compare this to the Android implementation, it also has this exact input/output type mismatch but this time it is also reflected in libc
.
pub {const} fn makedev(ma: c_uint, mi: c_uint) -> crate::dev_t {
let ma = ma as crate::dev_t;
let mi = mi as crate::dev_t;
((ma & 0xfff) << 8) | (mi & 0xff) | ((mi & 0xfff00) << 12)
}
pub {const} fn major(dev: crate::dev_t) -> c_int {
((dev >> 8) & 0xfff) as c_int
}
pub {const} fn minor(dev: crate::dev_t) -> c_int {
((dev & 0xff) | ((dev >> 12) & 0xfff00)) as c_int
}
I guess my question is whether this has been done on purpose or if there's any room for improvement (maybe just mention these ambiguities and inconsistencies in libc
documentation).