commit: cc6e10d731ffa93a6303302f66417bdd9627ec08
parent ee07ab9d0f2a8609f97a3924bb500bc0dac79455
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Wed, 20 Aug 2025 16:57:51 +0200
cmd/disk_id: new
Effectively linux-only but I don't feel like bothering with creating
another repo for it yet.
Diffstat:
A | cmd/disk_id.c | 109 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | configure | 5 | +++++ |
2 files changed, 114 insertions(+), 0 deletions(-)
diff --git a/cmd/disk_id.c b/cmd/disk_id.c
@@ -0,0 +1,109 @@
+// utils-extra: Collection of extra tools for Unixes
+// SPDX-FileCopyrightText: 2017-2022 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
+// SPDX-License-Identifier: MPL-2.0
+
+#define _DEFAULT_SOURCE
+#include <string.h> // strerror
+#include <stdio.h>
+#include <errno.h>
+#include <stropts.h> // ioctl
+#include <fcntl.h> // open
+#include <linux/hdreg.h> // HDIO_GET_IDENTITY
+#include <unistd.h> // fsync, write
+#include <stdint.h> // uint16_t
+#include <ctype.h> // isalnum
+
+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;
+}
diff --git a/configure b/configure
@@ -170,6 +170,11 @@ then
FLAWFINDER="true"
fi
+if ! check_header linux/hdreg.h
+then
+ target_filter="-e cmd/disk_id"
+fi
+
echo
## Configuration write