master ohmu/fastfetch-openbsd / src / detection / physicaldisk / physicaldisk_haiku.c
ohmu  ·  2026-10-15
  1#include "physicaldisk.h"
  2
  3#include "common/debug.h"
  4#include "common/io.h"
  5#include "common/strutil.h"
  6
  7#include <OS.h>
  8#include <StorageDefs.h>
  9#include <Drivers.h>
 10#include <sys/ioctl.h>
 11
 12static const char* searchRawDeviceFile(FFstrbuf* path, const char* diskType, FFlist* result, FFPhysicalDiskOptions* options) {
 13    FF_AUTO_CLOSE_DIR DIR* dir = opendir(path->chars);
 14    if (!dir) {
 15        FF_DEBUG("opendir(\"%s\") failed: %s", path->chars, strerror(errno));
 16        return "detectDiskType: opendir() failed";
 17    }
 18    uint32_t baseLen = path->length;
 19
 20    struct dirent* entry;
 21    while ((entry = readdir(dir))) {
 22        if (entry->d_name[0] == '.') {
 23            continue;
 24        }
 25        ffStrbufAppendC(path, '/');
 26        ffStrbufAppendS(path, entry->d_name);
 27
 28        struct stat st;
 29        if (stat(path->chars, &st) != 0) {
 30            ffStrbufSubstrBefore(path, baseLen);
 31            continue;
 32        }
 33
 34        if (S_ISDIR(st.st_mode)) {
 35            searchRawDeviceFile(path, diskType, result, options);
 36        } else if (ffStrEquals(entry->d_name, "raw")) {
 37            FF_AUTO_CLOSE_FD int rawfd = open(path->chars, O_RDONLY | O_CLOEXEC);
 38            if (rawfd < 0) {
 39                continue;
 40            }
 41
 42            device_geometry geometry;
 43            if (ioctl(rawfd, B_GET_GEOMETRY, &geometry, sizeof(geometry)) < 0) {
 44                continue;
 45            }
 46
 47            char name[B_OS_NAME_LENGTH];
 48            if (ioctl(rawfd, B_GET_DEVICE_NAME, name, sizeof(name)) != 0) {
 49                // ioctl reports `not a tty` for NVME drives for some reason
 50                snprintf(name, sizeof(name), "Unknown %s drive", diskType);
 51            }
 52
 53            if (options->namePrefix.length && strncmp(name, options->namePrefix.chars, options->namePrefix.length) != 0) {
 54                continue;
 55            }
 56
 57            FFPhysicalDiskType type = FF_PHYSICALDISK_TYPE_NONE;
 58            uint64_t size = (uint64_t) geometry.cylinder_count * geometry.head_count * geometry.sectors_per_track * geometry.bytes_per_sector;
 59            if (size == 0) {
 60                if (options->hideType & FF_PHYSICALDISK_TYPE_UNUSED) {
 61                    continue;
 62                }
 63
 64                type |= FF_PHYSICALDISK_TYPE_UNUSED;
 65            }
 66
 67            FFPhysicalDiskResult* device = FF_LIST_ADD(FFPhysicalDiskResult, *result);
 68            ffStrbufInitS(&device->name, name);
 69            ffStrbufInitCopy(&device->devPath, path);
 70            ffStrbufInit(&device->serial);
 71            ffStrbufInit(&device->revision);
 72            ffStrbufInitS(&device->interconnect, diskType);
 73            device->temperature = FF_PHYSICALDISK_TEMP_UNSET;
 74            device->type = type |
 75                (geometry.read_only ? FF_PHYSICALDISK_TYPE_READONLY : FF_PHYSICALDISK_TYPE_READWRITE) |
 76                (geometry.removable ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED);
 77            device->size = size;
 78        }
 79
 80        ffStrbufSubstrBefore(path, baseLen);
 81    }
 82    return nullptr;
 83}
 84
 85const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) {
 86    FF_AUTO_CLOSE_DIR DIR* dir = opendir("/dev/disk");
 87    if (!dir) {
 88        FF_DEBUG("opendir(\"/dev/disk\") failed: %s", strerror(errno));
 89        return "opendir(/dev/disk) failed";
 90    }
 91
 92    FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateA(64);
 93    ffStrbufAppendS(&path, "/dev/disk/");
 94    uint32_t baseLen = path.length;
 95
 96    struct dirent* entry;
 97    while ((entry = readdir(dir))) {
 98        if (entry->d_name[0] == '.' || ffStrEquals(entry->d_name, "virtual")) {
 99            continue;
100        }
101        ffStrbufAppendS(&path, entry->d_name);
102        searchRawDeviceFile(&path, entry->d_name, result, options);
103        ffStrbufSubstrBefore(&path, baseLen);
104    }
105
106    return nullptr;
107}