Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

GNU/Linux systemd/sd-device problems creating and filtering an sd_device_enumerator

Preface:

I am not a good developer and am just getting started, the code below is part of a larger program I am building and has only been temporarily placed in the main cpp file. I am aware that the structure still needs improvement only I want to get it running first.

Problem:

I have the last days desperately trying to find documentation, but since I could find nothing but this [https://www.freedesktop.org/software/systemd/man/sd-device.html] and I have tried to work through the source code on github.

I had previously used the libudev library to read BLOCK devices and get values from them which worked, however after further exposure to this topic I read that it is no longer recommended to use libudev and switch to systemd/sd-device.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

The code below doesn’t output an error but it also doesn’t run through the loop because "sd_device_enumerator_get_device_next(enumerator)" always returns a NULL pointer. Even after a very long search I can’t find any documentation for systemd/sd-device and even reading through the src data I can’t figure it out.

This is my attempt, this should basically run through all BLOCK devices and read out certain values, for testing I have entered "ID_PART_TABLE_TYPE".

main.h

#ifndef main_h
#define main_h

#include <string>
#include <bitset>
#include <iostream>
#include <fstream>
#include <sstream>
#include <regex>
#include <vector>
#include <cstring>

#include <stdio.h>
#include <dirent.h>

#include <systemd/sd-device.h>

using std::cout;
using std::endl;
using std::string;
using std::to_string;
using std::cin;
using std::fstream;
using std::ifstream;
using std::ofstream;
using std::vector;

// File: classes/drives-info.cpp
/*
class drivesInfo{
public:

    vector<string> blockDevs;
    vector< vector<string> > blockDevsParts;
        
    int get_blockDevs();


};
*/



#endif

main.cpp

#include "main.h"


int test0() {
    int r;
    sd_device_enumerator *enumerator = NULL;
    sd_device *dev = NULL;

    // Initialize the Device-Enumerator
    r = sd_device_enumerator_new(&enumerator);
    if (r < 0) {
        printf("Error | Initialize the Device-Enumerator: %s\n", strerror(-r));
    }

    // Set Filter to BLOCK
    r = sd_device_enumerator_add_match_subsystem(enumerator, "block", 0);
    if (r < 0) {
        printf("Error | Set Filter to BLOCK: %s\n", strerror(-r));
    }
    
    // Loop to run through all BLOCK devices
    if (r >= 0) {
        while ((dev = sd_device_enumerator_get_device_next(enumerator)) != NULL) {
            const char *pt_type = NULL;
            r = sd_device_get_property_value(dev, "ID_PART_TABLE_TYPE", &pt_type);
            if (r >= 0) {
                printf("Device: %s\n");
                printf("ID_PART_TABLE_TYPE: %s\n", pt_type);
            }

            sd_device_unref(dev);
            dev = NULL;
            cout << "loop" << endl;
        }
    }

    if (r < 0) {
        printf("Error | at Loop to run through all BLOCK devices: %s\n", strerror(-r));
    }

    if (enumerator) {
        sd_device_enumerator_unref(enumerator);
    }
    if (dev) {
        sd_device_unref(dev);
    }

    return r < 0 ? 1 : 0;
}

int main() {

//     drivesInfo drives;
//     
//     drives.get_blockDevs();
// 
//     for (const string &entry : drives.blockDevs){
//         cout << entry << endl;
//     }

    
    test0();

    return 0;
}

>Solution :

You have to first call sd_device_enumerator_get_device_first.

int test0() {
    sd_device_enumerator *enumerator = NULL;
    int r = sd_device_enumerator_new(&enumerator);
    if (r < 0) {
        printf("Error | Initialize the Device-Enumerator: %s\n", strerror(-r));
        return -1;
    }
    r = sd_device_enumerator_add_match_subsystem(enumerator, "block", 0);
    if (r < 0) {
        printf("Error | Set Filter to BLOCK: %s\n", strerror(-r));
        return -1;
    }
    sd_device *dev = NULL;
    for (dev = sd_device_enumerator_get_device_first(enumerator); dev != NULL;
         dev = sd_device_enumerator_get_device_next(enumerator)) {
        const char *pt_type = NULL;
        r = sd_device_get_property_value(dev, "ID_MODEL", &pt_type);
        if (r >= 0) {
            printf("%s\n", pt_type);
        }
        sd_device_unref(dev);
    }
    sd_device_enumerator_unref(enumerator);
    return r < 0 ? 1 : 0;
}

outputs on my pc:

$ g++ -fsanitize=address,undefined -lsystemd 1.cpp && ./a.out 
xHCI_Host_Controller
GK630_Gaming_Keyboard
GK630_Gaming_Keyboard
GK630_Gaming_Keyboard
GK630_Gaming_Keyboard
GK630_Gaming_Keyboard
GK630_Gaming_Keyboard
GK630_Gaming_Keyboard
GK630_Gaming_Keyboard
GK630_Gaming_Keyboard
GK630_Gaming_Keyboard
xHCI_Host_Controller
EHCI_Host_Controller
0024
CSR8510_A10
EHCI_Host_Controller
0024
UDisk
USB_Optical_Mouse
USB_Optical_Mouse
USB_Optical_Mouse
USB_Optical_Mouse
D3162-B1

You might be interested in https://github.com/systemd/systemd/blob/91010bd6ccd363be9e09f22c60d45f5e27c1d2a8/src/libsystemd/sd-device/device-util.h#L52

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading