logo

utils-extra

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

disk_id.c (2611B)


  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 <ctype.h> // isalnum
  6. #include <errno.h>
  7. #include <fcntl.h> // open
  8. #include <linux/hdreg.h> // HDIO_GET_IDENTITY
  9. #include <stdint.h> // uint16_t
  10. #include <stdio.h>
  11. #include <string.h> // strerror
  12. #include <stropts.h> // ioctl
  13. #include <unistd.h> // fsync, write
  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. {
  43. if(argc != 2)
  44. {
  45. fprintf(stderr, "disk_id: error: Need 1 argument, got %d\n", argc - 1);
  46. fprintf(stderr, "Usage: disk_id <block_device_path>\n");
  47. return 1;
  48. }
  49. const char *dev = argv[1];
  50. int fd = open(dev, O_RDONLY | O_NONBLOCK | O_LARGEFILE);
  51. // IDENTITY is 512 bytes
  52. static uint16_t identity[256];
  53. int ret = ioctl(fd, HDIO_GET_IDENTITY, identity);
  54. if(ret < 0)
  55. {
  56. switch(errno)
  57. {
  58. case EINVAL:
  59. fprintf(stderr,
  60. "disk_id: error: Device '%s' -> ioctl(HDIO_GET_IDENTITY): [EINVAL] Is a partition "
  61. "not a disk\n",
  62. dev);
  63. return 1;
  64. case ENOMSG:
  65. fprintf(stderr,
  66. "disk_id: error: Device '%s' -> ioctl(HDIO_GET_IDENTITY): [ENOMSG] Information not "
  67. "available\n",
  68. dev);
  69. return 1;
  70. default:
  71. fprintf(stderr,
  72. "disk_id: error: Device '%s' -> ioctl(HDIO_GET_IDENTITY): %s\n",
  73. dev,
  74. strerror(errno));
  75. return 1;
  76. }
  77. }
  78. // TODO: Handle errno
  79. close(fd);
  80. static char serno_buf[20] = "";
  81. static char model_buf[40] = "";
  82. static char disk_id[40 + 20] = "";
  83. size_t serno_len = 20;
  84. memcpy(serno_buf, (char *)&identity[10], serno_len);
  85. char *serno = strip(serno_buf, &serno_len);
  86. //printf("serno: [%s] (%zd)\n", serno, serno_len);
  87. size_t model_len = 40;
  88. memcpy(model_buf, (char *)&identity[27], model_len);
  89. char *model = strip(model_buf, &model_len);
  90. //printf("model: [%s] (%zd)\n", model, model_len);
  91. size_t modelz = strncpyalnum(disk_id, model, model_len);
  92. if(modelz == 0) return 1;
  93. disk_id[modelz++] = '_';
  94. size_t serialz = strncpyalnum(disk_id + modelz, serno, serno_len);
  95. if(serialz == 0) return 1;
  96. printf("%s\n", disk_id);
  97. return 0;
  98. }