Search code examples
c++linuxsystems-programmingparted

How to write out all connected devices using Libparted on Linux Mint?


I have been trying to print out all connected storage devices to my machine using C++ and libparted on Linux Mint 22 x86_64.

I have been tinkering with the ped_device_get_next() function, that should return the next device in the list provided by the ped_device_probe_all() function. I have trouble getting this to work, since the documentation on this library is pretty poor.

The most useful thing I've gotten to work is this simple chunk of code.

#include <cmakeconfig.h>
#include "mainheader.h"

int main()
{
    ped_device_probe_all();

    PedDevice *tempbed;
    int c = 0;
    do {
        tempbed = ped_device_get_next(NULL);
        std::cout<<c<<" "<<tempbed->model<<"\n";
        c++;
    } while(tempbed != NULL && c < 256); 

    return 0;
}

And all it does is print out the model of my SSD 256 times. Without the c variable acting as a safety mechanism, it does it forever (until the resources run out I guess).

It does not print out the model of my HDD anywhere.

I know that my code does exactly what the documentation says, prints out the first device x times, but I just cannot figure out how to make it print out the devices consecutively.

0 <model name>
1 <model name>
2 <model name>
3 <model name>
4 <model name>
etc.

Documentation of ped_device_get_next


Solution

  • You initially call ped_device_get_next(NULL); Then on subsequent calls, you pass the value it returned on the previous call. One way to do this would be something like this:

    int main()
    {
        ped_device_probe_all();
    
        PedDevice *tempbed = nullptr;
        int c = 0;
    
        while((tempbed = ped_device_get_next(tempbed))!= nullptr && c <255) {
            std::cout<<c<<" "<<tempbed->model<<"\n";
            c++;
        } 
    
        return 0;
    }
    

    ...or you could wrap it up onto a class that imitates a container:

    #include <parted/parted.h>
    
    
    class devices {
    public:
        class iterator {
            PedDevice *current = nullptr;
        public:
            iterator &operator++() {
                current = ped_device_get_next(current);
                return *this;
            }
    
            PedDevice &operator*() const { return *current; }
    
            bool operator!=(iterator const &other) const { 
                return current != other.current;
            }
        };
        
        devices() { ped_device_probe_all(); }
        iterator begin() {
            iterator i;
            return ++i;        
        }
        iterator end() { return iterator(); }
    };
    

    ...then iterate over it like almost a other container:

    int main()
    {
        devices dev;
    
        for (auto const &d : dev) {
            std::cout << d.model << "\n";
        }
    }
    

    As an aside, note that on most systems, you'll have to run this as root for it to actually show anything.