logo

utils-extra

Collection of extra tools for Unixes git clone https://anongit.hacktivis.me/git/utils-extra.git/

disk_id.c (2473B)


  1. // utils-extra: Collection of extra tools for Unixes
  2. // SPDX-FileCopyrightText: 2017-2022 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: MPL-2.0
  4. #define _DEFAULT_SOURCE
  5. #include <string.h> // strerror
  6. #include <stdio.h>
  7. #include <errno.h>
  8. #include <stropts.h> // ioctl
  9. #include <fcntl.h> // open
  10. #include <linux/hdreg.h> // HDIO_GET_IDENTITY
  11. #include <unistd.h> // fsync, write
  12. #include <stdint.h> // uint16_t
  13. #include <ctype.h> // isalnum
  14. static char *
  15. strip(char *s, size_t *len)
  16. {
  17. while(*len > 0 && *s == ' ')
  18. {
  19. s++;
  20. (*len)--;
  21. }
  22. while(*len > 0 && s[(*len)-1] == ' ')
  23. {
  24. s[(*len)-1] = '\0';
  25. (*len)--;
  26. }
  27. return s;
  28. }
  29. static size_t
  30. strncpyalnum(char *dest, char *src, size_t len)
  31. {
  32. size_t i = 0;
  33. for(; i < len; i++)
  34. {
  35. if(src[i] == '\0') break;
  36. dest[i] = isalnum(src[i]) ? src[i] : '_';
  37. }
  38. return i;
  39. }
  40. int
  41. main(int argc, char *argv[]) {
  42. if(argc != 2)
  43. {
  44. fprintf(stderr, "disk_id: error: Need 1 argument, got %d\n", argc-1);
  45. fprintf(stderr, "Usage: disk_id <block_device_path>\n");
  46. return 1;
  47. }
  48. const char *dev = argv[1];
  49. int fd = open(dev, O_RDONLY|O_NONBLOCK|O_LARGEFILE);
  50. // IDENTITY is 512 bytes
  51. static uint16_t identity[256];
  52. int ret = ioctl(fd, HDIO_GET_IDENTITY, identity);
  53. if(ret < 0)
  54. {
  55. switch(errno)
  56. {
  57. case EINVAL:
  58. fprintf(stderr, "disk_id: error: Device '%s' -> ioctl(HDIO_GET_IDENTITY): [EINVAL] Is a partition not a disk\n", dev);
  59. return 1;
  60. case ENOMSG:
  61. fprintf(stderr, "disk_id: error: Device '%s' -> ioctl(HDIO_GET_IDENTITY): [ENOMSG] Information not available\n", dev);
  62. return 1;
  63. default:
  64. fprintf(stderr, "disk_id: error: Device '%s' -> ioctl(HDIO_GET_IDENTITY): %s\n", dev, strerror(errno));
  65. return 1;
  66. }
  67. }
  68. // TODO: Handle errno
  69. close(fd);
  70. static char serno_buf[20] = "";
  71. static char model_buf[40] = "";
  72. static char disk_id[40+20] = "";
  73. size_t serno_len = 20;
  74. memcpy(serno_buf, (char *)&identity[10], serno_len);
  75. char *serno = strip(serno_buf, &serno_len);
  76. //printf("serno: [%s] (%zd)\n", serno, serno_len);
  77. size_t model_len = 40;
  78. memcpy(model_buf, (char *)&identity[27], model_len);
  79. char *model = strip(model_buf, &model_len);
  80. //printf("model: [%s] (%zd)\n", model, model_len);
  81. size_t modelz = strncpyalnum(disk_id, model, model_len);
  82. if(modelz == 0) return 1;
  83. disk_id[modelz++] = '_';
  84. size_t serialz = strncpyalnum(disk_id+modelz, serno, serno_len);
  85. if(serialz == 0) return 1;
  86. printf("%s\n", disk_id);
  87. return 0;
  88. }