commit: eb6a25e1ec9c063d1498f7adf9ef01bf8ebd99d4
parent aa5fe6585c792c800eb06b6c945e65b24131bc65
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Thu, 19 Feb 2026 15:49:47 +0100
cmd/disk_id.c: Add
Diffstat:
| A | cmd/disk_id.c | 119 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 119 insertions(+), 0 deletions(-)
diff --git a/cmd/disk_id.c b/cmd/disk_id.c
@@ -0,0 +1,119 @@
+// mdev-helpers: Collection of helpers for mdev/mdevd
+// SPDX-FileCopyrightText: 2017-2022 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
+// SPDX-License-Identifier: BSD-3-Clause
+
+#define _DEFAULT_SOURCE
+#include <ctype.h> // isalnum
+#include <errno.h>
+#include <fcntl.h> // open
+#include <linux/hdreg.h> // HDIO_GET_IDENTITY
+#include <stdint.h> // uint16_t
+#include <stdio.h>
+#include <string.h> // strerror
+#include <stropts.h> // ioctl
+#include <unistd.h> // fsync, write
+
+static char *
+strip(char *s, size_t *len)
+{
+ while(*len > 0 && *s == ' ')
+ {
+ s++;
+ (*len)--;
+ }
+
+ while(*len > 0 && s[(*len) - 1] == ' ')
+ {
+ s[(*len) - 1] = '\0';
+ (*len)--;
+ }
+
+ return s;
+}
+
+static size_t
+strncpyalnum(char *dest, char *src, size_t len)
+{
+ size_t i = 0;
+
+ for(; i < len; i++)
+ {
+ if(src[i] == '\0') break;
+
+ dest[i] = isalnum(src[i]) ? src[i] : '_';
+ }
+
+ return i;
+}
+
+int
+main(int argc, char *argv[])
+{
+ if(argc != 2)
+ {
+ fprintf(stderr, "disk_id: error: Need 1 argument, got %d\n", argc - 1);
+ fprintf(stderr, "Usage: disk_id <block_device_path>\n");
+ return 1;
+ }
+
+ const char *dev = argv[1];
+
+ int fd = open(dev, O_RDONLY | O_NONBLOCK | O_LARGEFILE);
+
+ // IDENTITY is 512 bytes
+ static uint16_t identity[256];
+ int ret = ioctl(fd, HDIO_GET_IDENTITY, identity);
+ if(ret < 0)
+ {
+ switch(errno)
+ {
+ case EINVAL:
+ fprintf(stderr,
+ "disk_id: error: Device '%s' -> ioctl(HDIO_GET_IDENTITY): [EINVAL] Is a partition "
+ "not a disk\n",
+ dev);
+ return 1;
+ case ENOMSG:
+ fprintf(stderr,
+ "disk_id: error: Device '%s' -> ioctl(HDIO_GET_IDENTITY): [ENOMSG] Information not "
+ "available\n",
+ dev);
+ return 1;
+ default:
+ fprintf(stderr,
+ "disk_id: error: Device '%s' -> ioctl(HDIO_GET_IDENTITY): %s\n",
+ dev,
+ strerror(errno));
+ return 1;
+ }
+ }
+
+ // TODO: Handle errno
+ close(fd);
+
+ static char serno_buf[20] = "";
+ static char model_buf[40] = "";
+ static char disk_id[40 + 20] = "";
+
+ size_t serno_len = 20;
+ memcpy(serno_buf, (char *)&identity[10], serno_len);
+ char *serno = strip(serno_buf, &serno_len);
+ //printf("serno: [%s] (%zd)\n", serno, serno_len);
+
+ size_t model_len = 40;
+ memcpy(model_buf, (char *)&identity[27], model_len);
+ char *model = strip(model_buf, &model_len);
+ //printf("model: [%s] (%zd)\n", model, model_len);
+
+ size_t modelz = strncpyalnum(disk_id, model, model_len);
+ if(modelz == 0) return 1;
+
+ disk_id[modelz++] = '_';
+
+ size_t serialz = strncpyalnum(disk_id + modelz, serno, serno_len);
+ if(serialz == 0) return 1;
+
+ printf("%s\n", disk_id);
+
+ return 0;
+}