c++clinuxserial-numberhard-drive

Get /dev/disk/by-id element from /dev/sd* element


I know that there is /dev/disk/by-id/ folder which contains links to /dev/sd* elements. I'd like to know, is there any way to get by-id element pointing to, for example, /dev/sda.

P.S.: yeah, I know that I can loop through elements in by-id folder and /dev/sd*, so that I can compare serial numbers and match them. But is there any better way?

EDIT: sorry for my mistake. It should be done in C/C++. UUID's were mentioned. That would be great, they are unique and so on, but how can I collect all the UUID's of one hdd? I mean the main, pointing to sda, for example, and partition UUID's, pointing to sda1, sda2 and so on.


Solution

  • I'm sorry for late answer.

    My question was wrong, I did not need /dev/sd* element to get /dev/disk/by-id/ elements.

    I've used libudev and got these elements:

    #include <libudev.h>
    
    ...
    
    struct udev *udev;
    udev = udev_new();
    
    udev_enumerate *enumerate;
    enumerate = udev_enumerate_new(udev);
    
    udev_list_entry *udev_entries;
    udev_list_entry *dev_list_entry;
    udev_device *dev;
    
    udev_enumerate_add_match_subsystem(enumerate, "block");
    udev_enumerate_scan_devices(enumerate);
    udev_entries = udev_enumerate_get_list_entry(enumerate);
    udev_list_entry_foreach(dev_list_entry, udev_entries)
    {
        const char* path = udev_list_entry_get_name(dev_list_entry);
        dev = udev_device_new_from_syspath(udev, path);
        const char* bus = udev_device_get_property_value(dev, "ID_BUS");
        const char* type = udev_device_get_property_value(dev, "ID_TYPE");
    
        if (!bus || !type)
            continue;
    
        // strncmp return 0 if equal
        if (!(strncmp(bus, "ata", 3) &&
                !strncmp(type, "disk", 4))
            continue;
    
        // i wanted to get only partitions, so parent is empty
        udev_device *parent = 
            udev_device_get_parent_with_subsystem_devtype(dev, "block", "disk");
        if (!parent)
            continue;
    
        // get /dev/disk/by-id/...-partX
        struct udev_list_entry* devlinks = udev_device_get_devlinks_list_entry(dev);
        std::string partition(udev_list_entry_get_name(devlinks));
        // now we have /dev/disk/by-id/...-partX in partition and can save it somewhere
    }
    

    P.S.: I've used that in special LFS-based distribution, that does have serial numbers in /dev/disk/by-id/ name.