Skip to content

Commit 2a103f6

Browse files
committed
PhysicalDisk (NetBSD): adds support
Requires root permission
1 parent 8d0ceff commit 2a103f6

File tree

2 files changed

+156
-1
lines changed

2 files changed

+156
-1
lines changed

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ elseif(NetBSD)
793793
src/detection/cursor/cursor_linux.c
794794
src/detection/disk/disk_bsd.c
795795
src/detection/dns/dns_linux.c
796-
src/detection/physicaldisk/physicaldisk_nosupport.c
796+
src/detection/physicaldisk/physicaldisk_nbsd.c
797797
src/detection/physicalmemory/physicalmemory_linux.c
798798
src/detection/diskio/diskio_nbsd.c
799799
src/detection/displayserver/linux/displayserver_linux.c
@@ -1774,6 +1774,7 @@ elseif(NetBSD)
17741774
PRIVATE "bluetooth"
17751775
PRIVATE "m"
17761776
PRIVATE "prop"
1777+
PRIVATE "util"
17771778
)
17781779
elseif(SunOS)
17791780
target_link_libraries(libfastfetch
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
#define DKTYPENAMES
2+
#include "physicaldisk.h"
3+
#include "common/io.h"
4+
#include "common/sysctl.h"
5+
6+
#include <util.h>
7+
#include <prop/proplib.h>
8+
#include <sys/ioctl.h>
9+
#include <sys/disklabel.h>
10+
#include <sys/dkio.h>
11+
#include <sys/scsiio.h>
12+
#include <dev/scsipi/scsipi_all.h>
13+
#include <dev/scsipi/scsi_spc.h>
14+
#include <fcntl.h>
15+
#include <errno.h>
16+
17+
const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) {
18+
FF_STRBUF_AUTO_DESTROY diskNames = ffStrbufCreate();
19+
const char* error = ffSysctlGetString("hw.disknames", &diskNames);
20+
if (error) {
21+
return error;
22+
}
23+
24+
char* diskName = NULL;
25+
size_t len = 0;
26+
while (ffStrbufGetdelim(&diskName, &len, ' ', &diskNames)) {
27+
char devPath[256];
28+
FF_AUTO_CLOSE_FD int f = opendisk(diskName, O_RDONLY, devPath, ARRAY_SIZE(devPath), 0);
29+
if (f < 0) {
30+
if (errno == EACCES) {
31+
return "Permission denied; root required";
32+
} else {
33+
continue;
34+
}
35+
}
36+
37+
struct disklabel dl;
38+
if (ioctl(f, DIOCGDINFO, &dl) < 0) {
39+
continue;
40+
}
41+
42+
unsigned long sectorsPerUnit, sectorSize;
43+
44+
const char* devType = NULL;
45+
46+
prop_dictionary_t dict = NULL;
47+
if (prop_dictionary_recv_ioctl(f, DIOCGDISKINFO, &dict) == 0) {
48+
prop_dictionary_get_string(dict, "type", &devType);
49+
50+
prop_dictionary_t geometry;
51+
if (prop_dictionary_get_dict(dict, "geometry", &geometry)) {
52+
prop_dictionary_get_ulong(geometry, "sectors-per-unit", &sectorsPerUnit);
53+
prop_dictionary_get_ulong(geometry, "sector-size", &sectorSize);
54+
} else {
55+
sectorsPerUnit = dl.d_secperunit;
56+
sectorSize = dl.d_secsize;
57+
}
58+
} else {
59+
sectorsPerUnit = dl.d_secperunit;
60+
sectorSize = dl.d_secsize;
61+
}
62+
63+
bool isVirtual = false;
64+
switch (dl.d_type) {
65+
case DKTYPE_VND:
66+
case DKTYPE_LD:
67+
case DKTYPE_RAID:
68+
case DKTYPE_CGD:
69+
case DKTYPE_VINUM:
70+
case DKTYPE_DM:
71+
case DKTYPE_RUMPD:
72+
case DKTYPE_MD:
73+
isVirtual = true;
74+
}
75+
76+
bool isUnknown = sectorsPerUnit == 0;
77+
FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result);
78+
ffStrbufInitS(&device->name, devType ?: dl.d_packname);
79+
ffStrbufInitS(&device->devPath, devPath);
80+
ffStrbufInit(&device->serial);
81+
ffStrbufInit(&device->revision);
82+
ffStrbufInitS(&device->interconnect, dktypenames[dl.d_type]);
83+
device->type = (!isVirtual ? FF_PHYSICALDISK_TYPE_NONE : FF_PHYSICALDISK_TYPE_VIRTUAL) |
84+
(!isUnknown ? FF_PHYSICALDISK_TYPE_NONE : FF_PHYSICALDISK_TYPE_UNKNOWN) |
85+
(dl.d_flags & D_REMOVABLE ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED);
86+
device->size = sectorsPerUnit * sectorSize;
87+
device->temperature = FF_PHYSICALDISK_TEMP_UNSET;
88+
89+
if (dict) {
90+
prop_object_release(dict);
91+
dict = NULL;
92+
}
93+
94+
struct scsipi_inquiry_data inquiry = {};
95+
scsireq_t req = {
96+
.cmd = { [0] = INQUIRY, [4] = sizeof(inquiry) },
97+
.cmdlen = 6,
98+
.databuf = (caddr_t) &inquiry,
99+
.datalen = sizeof(inquiry),
100+
.timeout = 1000,
101+
.flags = SCCMD_READ,
102+
};
103+
if (ioctl(f, SCIOCCOMMAND, &req) == 0 && req.retsts == SCCMD_OK) {
104+
ffStrbufClear(&device->name);
105+
ffStrbufAppendNS(&device->name, (uint32_t) ARRAY_SIZE(inquiry.vendor), inquiry.vendor);
106+
ffStrbufTrimRight(&device->name, '\0');
107+
ffStrbufTrimRight(&device->name, ' ');
108+
ffStrbufAppendC(&device->name, ' ');
109+
ffStrbufAppendNS(&device->name, (uint32_t) ARRAY_SIZE(inquiry.product), inquiry.product);
110+
ffStrbufTrimRight(&device->name, '\0');
111+
ffStrbufTrimRight(&device->name, ' ');
112+
113+
ffStrbufSetNS(&device->revision, (uint32_t) ARRAY_SIZE(inquiry.revision), inquiry.revision);
114+
ffStrbufTrimRight(&device->name, '\0');
115+
ffStrbufTrimRight(&device->revision, ' ');
116+
} else {
117+
continue;
118+
}
119+
120+
struct {
121+
struct scsipi_inquiry_evpd_header header;
122+
struct scsipi_inquiry_evpd_serial body;
123+
} evpd = {};
124+
req = (scsireq_t) {
125+
.cmd = { [0] = INQUIRY, [1] = SINQ_EVPD, [2] = SINQ_VPD_UNIT_SERIAL, [4] = sizeof(evpd) },
126+
.cmdlen = 6,
127+
.databuf = (caddr_t) &evpd,
128+
.datalen = sizeof(evpd),
129+
.timeout = 1000,
130+
.flags = SCCMD_READ,
131+
};
132+
if (ioctl(f, SCIOCCOMMAND, &req) == 0 && req.retsts == SCCMD_OK && evpd.header.pagecode == SINQ_VPD_UNIT_SERIAL) {
133+
for (uint8_t i = 0; i < evpd.header.length[1]; ++i) {
134+
ffStrbufAppendF(&device->serial, "%02X", evpd.body.serial_number[i]);
135+
}
136+
ffStrbufTrimRight(&device->serial, ' ');
137+
}
138+
139+
struct scsi_mode_parameter_header_6 mode = {};
140+
req = (scsireq_t) {
141+
.cmd = { [0] = SCSI_MODE_SENSE_6, [2] = SMS_PAGE_MASK, [4] = sizeof(mode) },
142+
.cmdlen = 6,
143+
.databuf = (caddr_t) &mode,
144+
.datalen = sizeof(mode),
145+
.timeout = 1000,
146+
.flags = SCCMD_READ,
147+
};
148+
if (ioctl(f, SCIOCCOMMAND, &req) == 0 && req.retsts == SCCMD_OK && mode.data_length > 0) {
149+
device->type |= mode.dev_spec & 0x80 ? FF_PHYSICALDISK_TYPE_READONLY : FF_PHYSICALDISK_TYPE_READWRITE;
150+
}
151+
}
152+
153+
return NULL;
154+
}

0 commit comments

Comments
 (0)