Skip to content

Curious makedev function signature mismatch on macOS #4360

Open
@nohajc

Description

@nohajc

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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: bugE-help-wantedCall for participation: Help is requested to fix this issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions