uutils / coreutils

Cross-platform Rust rewrite of the GNU coreutils
https://uutils.github.io/
MIT License
17.85k stars 1.28k forks source link

ls: show device details #2140

Closed cbjadwani closed 1 year ago

cbjadwani commented 3 years ago

Add support to show device major and minor numbers and type (block/char).

Example:

$ ls -l /dev/input/event* | head -5
crw-rw---- 1 root input 13, 64 Apr 26 14:27 /dev/input/event0
crw-rw---- 1 root input 13, 65 Apr 26 14:27 /dev/input/event1
crw-rw---- 1 root input 13, 74 Apr 26 14:27 /dev/input/event10
crw-rw---- 1 root input 13, 75 Apr 26 14:27 /dev/input/event11
crw-rw---- 1 root input 13, 76 Apr 26 14:27 /dev/input/event12

The 'c' in crw-rw---- is for the type of device and 13, 76 are major and minor numbers of the device.

tertsdiepraam commented 3 years ago

@sylvestre GitHub closed this automatically, but it hasn't been implemented yet

jlc-christie commented 3 years ago

Is the only issue with this the major device number? Type and minor seem to be working fine. I will create a quick PR for that fix now.

tertsdiepraam commented 3 years ago

Actually, I'm not sure. I think I might have put the reopen request on the wrong issue😄 Your fix is interesting though, because shifting by 8 works for me, so is it dependent on platform?

jlc-christie commented 3 years ago

Ah that is interesting. It must be, tried to find some info but couldn't find anything concrete. I'm on aarch64 macOS, the stat command is also giving me some strange results for device files.

tertsdiepraam commented 3 years ago

I think I found the solution based on:

We need the major function in libc: https://docs.rs/libc/0.2.94/libc/fn.major.html. This works on my machine:

let major = unsafe { uucore::libc::major(dev) } as u8;
let minor = unsafe { uucore::libc::minor(dev) } as u8;

Could you try that on mac as well?

jlc-christie commented 3 years ago

Ah good find. For some reason I can't use the major and minor funcs from libc? Maybe being feature-gated out for some reason? Although looking at the source:

pub fn major(dev: ::dev_t) -> ::c_uint {
    let mut major = 0;
    major |= (dev & 0x00000000000fff00) >> 8;
    major |= (dev & 0xfffff00000000000) >> 32;
    major as ::c_uint
}

pub fn minor(dev: ::dev_t) -> ::c_uint {
    let mut minor = 0;
    minor |= (dev & 0x00000000000000ff) >> 0;
    minor |= (dev & 0x00000ffffff00000) >> 12;
    minor as ::c_uint
}

I don't see any reason why we couldn't use this logic without calling the unsafe libc func? Unless I'm missing something?

tertsdiepraam commented 3 years ago

For some reason I can't use the major and minor funcs from libc?

Interesting, it looks like those functions aren't defined for Mac. That's too bad.

I don't see any reason why we couldn't use this logic without calling the unsafe libc func? Unless I'm missing something?

I'm guessing that the logic should be different on different systems so this might not solve it, but it's worth a shot!

I did some more digging and this is what exa does (they just ignore the issue):

// In C-land, getting the major and minor device IDs is done with
// preprocessor macros called `major` and `minor` that depend on
// the size of `dev_t`, but we just take the second-to-last and
// last bytes.
f::Size::DeviceIDs(f::DeviceIDs {
    major: device_ids[6],
    minor: device_ids[7],
})

Also here's a StackOverflow answer that we might be able to translate: https://stackoverflow.com/questions/35392291/how-to-convert-between-a-dev-t-and-major-minor-device-numbers. Honestly, I think it's okay to just implement a version that works for Linux and Mac and add fixes for other systems later.

Edit: That SO answer mentions that everything is the same for all systems (except the dev_t size, I guess) apart from Windows, so maybe your solution does work.

SteveLauC commented 2 years ago

Ah good find. For some reason I can't use the major and minor funcs from libc? Maybe being feature-gated out for some reason?

These two functions for Darwin have been added in libc

tertsdiepraam commented 2 years ago

@SteveLauC Thanks for contributing that to libc!

So to summarize, we now have this for:

And the way we can enable this for more platforms is by contributing to libc?

SteveLauC commented 2 years ago

That's exactly what I am doing right now, see rust-lang/libc#2999 😃

SteveLauC commented 2 years ago

It seems that redox does not support this. I searched their libc impl and didn't find those functions

tertsdiepraam commented 2 years ago

Awesome!