|
| 1 | +#include "physicaldisk.h" |
| 2 | + |
| 3 | +#include "common/io/io.h" |
| 4 | + |
| 5 | +#include <OS.h> |
| 6 | +#include <StorageDefs.h> |
| 7 | +#include <Drivers.h> |
| 8 | +#include <sys/ioctl.h> |
| 9 | + |
| 10 | +static const char* detectDisk(int dfd, const char* diskType, const char* diskId, FFlist* result) |
| 11 | +{ |
| 12 | + char buffer[64]; |
| 13 | + snprintf(buffer, sizeof(buffer), "%s/master/raw", diskId); |
| 14 | + FF_AUTO_CLOSE_FD int rawfd = openat(dfd, buffer, O_RDONLY); |
| 15 | + if (rawfd < 0) |
| 16 | + { |
| 17 | + snprintf(buffer, sizeof(buffer), "%s/raw", diskId); |
| 18 | + rawfd = openat(dfd, buffer, O_RDONLY); |
| 19 | + if (rawfd < 0) return "raw device file not found"; |
| 20 | + } |
| 21 | + |
| 22 | + device_geometry geometry; |
| 23 | + if (ioctl(rawfd, B_GET_GEOMETRY, &geometry, sizeof(geometry)) < 0) |
| 24 | + return "ioctl(B_GET_GEOMETRY) failed"; |
| 25 | + |
| 26 | + FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result); |
| 27 | + |
| 28 | + char name[B_OS_NAME_LENGTH]; |
| 29 | + if (ioctl(rawfd, B_GET_DEVICE_NAME, name, sizeof(name)) == 0) |
| 30 | + ffStrbufInitS(&device->name, name); |
| 31 | + else |
| 32 | + { |
| 33 | + // ioctl reports `not a tty` for NVME drives for some reason |
| 34 | + ffStrbufInitF(&device->name, "Unknown %s drive", diskType); |
| 35 | + } |
| 36 | + |
| 37 | + ffStrbufInitF(&device->devPath, "/dev/disk/%s/%s", diskType, buffer); |
| 38 | + ffStrbufInit(&device->serial); |
| 39 | + ffStrbufInit(&device->revision); |
| 40 | + ffStrbufInitS(&device->interconnect, diskType); |
| 41 | + device->temperature = 0.0/0.0; |
| 42 | + device->type = FF_PHYSICALDISK_TYPE_NONE; |
| 43 | + if (geometry.read_only) |
| 44 | + device->type |= FF_PHYSICALDISK_TYPE_READONLY; |
| 45 | + if (geometry.removable) |
| 46 | + device->type |= FF_PHYSICALDISK_TYPE_REMOVABLE; |
| 47 | + device->size = (uint64_t) geometry.cylinder_count * geometry.sectors_per_track * geometry.bytes_per_sector; |
| 48 | + |
| 49 | + return NULL; |
| 50 | +} |
| 51 | + |
| 52 | +static const char* detectDiskType(int dfd, const char* diskType, FFlist* result) |
| 53 | +{ |
| 54 | + int newfd = openat(dfd, diskType, O_RDONLY); |
| 55 | + if (newfd < 0) return "openat(dfd, diskType) failed"; |
| 56 | + |
| 57 | + FF_AUTO_CLOSE_DIR DIR* dir = fdopendir(newfd); |
| 58 | + if (!dir) return "fdopendir(newfd) failed"; |
| 59 | + |
| 60 | + struct dirent* entry; |
| 61 | + while((entry = readdir(dir))) |
| 62 | + { |
| 63 | + if (entry->d_name[0] == '.') continue; |
| 64 | + detectDisk(newfd, diskType, entry->d_name, result); |
| 65 | + } |
| 66 | + return NULL; |
| 67 | +} |
| 68 | + |
| 69 | +const char* ffDetectPhysicalDisk(FFlist* result, FF_MAYBE_UNUSED FFPhysicalDiskOptions* options) |
| 70 | +{ |
| 71 | + FF_AUTO_CLOSE_DIR DIR* dir = opendir("/dev/disk"); |
| 72 | + if (!dir) return "opendir(/dev/disk) failed"; |
| 73 | + |
| 74 | + struct dirent* entry; |
| 75 | + while((entry = readdir(dir))) |
| 76 | + { |
| 77 | + if (entry->d_name[0] == '.') continue; |
| 78 | + detectDiskType(dirfd(dir), entry->d_name, result); |
| 79 | + } |
| 80 | + |
| 81 | + return NULL; |
| 82 | +} |
0 commit comments