summaryrefslogtreecommitdiffstats
path: root/src/detection/physicaldisk/physicaldisk_haiku.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/detection/physicaldisk/physicaldisk_haiku.c')
-rw-r--r--src/detection/physicaldisk/physicaldisk_haiku.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/detection/physicaldisk/physicaldisk_haiku.c b/src/detection/physicaldisk/physicaldisk_haiku.c
new file mode 100644
index 0000000..e44ddce
--- /dev/null
+++ b/src/detection/physicaldisk/physicaldisk_haiku.c
@@ -0,0 +1,104 @@
+#include "physicaldisk.h"
+
+#include "common/io.h"
+#include "common/strutil.h"
+
+#include <OS.h>
+#include <StorageDefs.h>
+#include <Drivers.h>
+#include <sys/ioctl.h>
+
+static const char* searchRawDeviceFile(FFstrbuf* path, const char* diskType, FFlist* result, FFPhysicalDiskOptions* options) {
+ FF_AUTO_CLOSE_DIR DIR* dir = opendir(path->chars);
+ if (!dir) {
+ return "detectDiskType: opendir() failed";
+ }
+ uint32_t baseLen = path->length;
+
+ struct dirent* entry;
+ while ((entry = readdir(dir))) {
+ if (entry->d_name[0] == '.') {
+ continue;
+ }
+ ffStrbufAppendC(path, '/');
+ ffStrbufAppendS(path, entry->d_name);
+
+ struct stat st;
+ if (stat(path->chars, &st) != 0) {
+ ffStrbufSubstrBefore(path, baseLen);
+ continue;
+ }
+
+ if (S_ISDIR(st.st_mode)) {
+ searchRawDeviceFile(path, diskType, result, options);
+ } else if (ffStrEquals(entry->d_name, "raw")) {
+ FF_AUTO_CLOSE_FD int rawfd = open(path->chars, O_RDONLY | O_CLOEXEC);
+ if (rawfd < 0) {
+ continue;
+ }
+
+ device_geometry geometry;
+ if (ioctl(rawfd, B_GET_GEOMETRY, &geometry, sizeof(geometry)) < 0) {
+ continue;
+ }
+
+ char name[B_OS_NAME_LENGTH];
+ if (ioctl(rawfd, B_GET_DEVICE_NAME, name, sizeof(name)) != 0) {
+ // ioctl reports `not a tty` for NVME drives for some reason
+ snprintf(name, sizeof(name), "Unknown %s drive", diskType);
+ }
+
+ if (options->namePrefix.length && strncmp(name, options->namePrefix.chars, options->namePrefix.length) != 0) {
+ continue;
+ }
+
+ FFPhysicalDiskType type = FF_PHYSICALDISK_TYPE_NONE;
+ uint64_t size = (uint64_t) geometry.cylinder_count * geometry.head_count * geometry.sectors_per_track * geometry.bytes_per_sector;
+ if (size == 0) {
+ if (options->hideType & FF_PHYSICALDISK_TYPE_UNUSED) {
+ continue;
+ }
+
+ type |= FF_PHYSICALDISK_TYPE_UNUSED;
+ }
+
+ FFPhysicalDiskResult* device = FF_LIST_ADD(FFPhysicalDiskResult, *result);
+ ffStrbufInitS(&device->name, name);
+ ffStrbufInitCopy(&device->devPath, path);
+ ffStrbufInit(&device->serial);
+ ffStrbufInit(&device->revision);
+ ffStrbufInitS(&device->interconnect, diskType);
+ device->temperature = FF_PHYSICALDISK_TEMP_UNSET;
+ device->type = type |
+ (geometry.read_only ? FF_PHYSICALDISK_TYPE_READONLY : FF_PHYSICALDISK_TYPE_READWRITE) |
+ (geometry.removable ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED);
+ device->size = size;
+ }
+
+ ffStrbufSubstrBefore(path, baseLen);
+ }
+ return NULL;
+}
+
+const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) {
+ FF_AUTO_CLOSE_DIR DIR* dir = opendir("/dev/disk");
+ if (!dir) {
+ return "opendir(/dev/disk) failed";
+ }
+
+ FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateA(64);
+ ffStrbufAppendS(&path, "/dev/disk/");
+ uint32_t baseLen = path.length;
+
+ struct dirent* entry;
+ while ((entry = readdir(dir))) {
+ if (entry->d_name[0] == '.' || ffStrEquals(entry->d_name, "virtual")) {
+ continue;
+ }
+ ffStrbufAppendS(&path, entry->d_name);
+ searchRawDeviceFile(&path, entry->d_name, result, options);
+ ffStrbufSubstrBefore(&path, baseLen);
+ }
+
+ return NULL;
+}