disk_id.c (2473B)
- // 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;
- }