logo

utils-extra

Collection of extra tools for Unixes git clone https://anongit.hacktivis.me/git/utils-extra.git/
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:

Acmd/disk_id.c109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mconfigure5+++++
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