0

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.

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;
}

  • `if (r < 0) { while` ? You code does not `return` on `r < 0`, just continues. – KamilCuk Apr 28 '23 at 12:13
  • oops, i added the mistake later, but it is still the case that sd_device_enumerator_get_device_next always returns a NULL pointer –  Apr 28 '23 at 12:19

1 Answers1

0

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

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • Thank you very much that was my problem, do you know any documentation for the systemd/sd-device by any chance or do you take the information from the src files ? –  Apr 28 '23 at 12:38
  • `do you know any documentation for the systemd/sd-device` No. `do you take the information from the src files ?` I did here. You can also try udev. – KamilCuk Apr 28 '23 at 12:40
  • with libudev i had already made it work, but i had read that it is recommended to use systemd/sd-device. anyway thank you very much for your time and thank you very much for answering me so fast. –  Apr 28 '23 at 12:47