ldbuildid.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /* ldbuildid.c - Build Id support routines
  2. Copyright (C) 2013-2015 Free Software Foundation, Inc.
  3. This file is part of the GNU Binutils.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  15. MA 02110-1301, USA. */
  16. #include "sysdep.h"
  17. #include "bfd.h"
  18. #include "safe-ctype.h"
  19. #include "md5.h"
  20. #include "sha1.h"
  21. #include "ldbuildid.h"
  22. #define streq(a,b) strcmp ((a), (b)) == 0
  23. #define strneq(a,b,n) strncmp ((a), (b), (n)) == 0
  24. bfd_boolean
  25. validate_build_id_style (const char *style)
  26. {
  27. if ((streq (style, "md5")) || (streq (style, "sha1"))
  28. #ifndef __MINGW32__
  29. || (streq (style, "uuid"))
  30. #endif
  31. || (strneq (style, "0x", 2)))
  32. return TRUE;
  33. return FALSE;
  34. }
  35. bfd_size_type
  36. compute_build_id_size (const char *style)
  37. {
  38. if (streq (style, "md5") || streq (style, "uuid"))
  39. return 128 / 8;
  40. if (streq (style, "sha1"))
  41. return 160 / 8;
  42. if (strneq (style, "0x", 2))
  43. {
  44. bfd_size_type size = 0;
  45. /* ID is in string form (hex). Count the bytes. */
  46. const char *id = style + 2;
  47. do
  48. {
  49. if (ISXDIGIT (id[0]) && ISXDIGIT (id[1]))
  50. {
  51. ++size;
  52. id += 2;
  53. }
  54. else if (*id == '-' || *id == ':')
  55. ++id;
  56. else
  57. {
  58. size = 0;
  59. break;
  60. }
  61. } while (*id != '\0');
  62. return size;
  63. }
  64. return 0;
  65. }
  66. static unsigned char
  67. read_hex (const char xdigit)
  68. {
  69. if (ISDIGIT (xdigit))
  70. return xdigit - '0';
  71. if (ISUPPER (xdigit))
  72. return xdigit - 'A' + 0xa;
  73. if (ISLOWER (xdigit))
  74. return xdigit - 'a' + 0xa;
  75. abort ();
  76. return 0;
  77. }
  78. bfd_boolean
  79. generate_build_id (bfd *abfd,
  80. const char *style,
  81. checksum_fn checksum_contents,
  82. unsigned char *id_bits,
  83. int size ATTRIBUTE_UNUSED)
  84. {
  85. if (streq (style, "md5"))
  86. {
  87. struct md5_ctx ctx;
  88. md5_init_ctx (&ctx);
  89. if (!(*checksum_contents) (abfd, (sum_fn) &md5_process_bytes, &ctx))
  90. return FALSE;
  91. md5_finish_ctx (&ctx, id_bits);
  92. }
  93. else if (streq (style, "sha1"))
  94. {
  95. struct sha1_ctx ctx;
  96. sha1_init_ctx (&ctx);
  97. if (!(*checksum_contents) (abfd, (sum_fn) &sha1_process_bytes, &ctx))
  98. return FALSE;
  99. sha1_finish_ctx (&ctx, id_bits);
  100. }
  101. #ifndef __MINGW32__
  102. else if (streq (style, "uuid"))
  103. {
  104. int n;
  105. int fd = open ("/dev/urandom", O_RDONLY);
  106. if (fd < 0)
  107. return FALSE;
  108. n = read (fd, id_bits, size);
  109. close (fd);
  110. if (n < size)
  111. return FALSE;
  112. }
  113. #endif
  114. else if (strneq (style, "0x", 2))
  115. {
  116. /* ID is in string form (hex). Convert to bits. */
  117. const char *id = style + 2;
  118. size_t n = 0;
  119. do
  120. {
  121. if (ISXDIGIT (id[0]) && ISXDIGIT (id[1]))
  122. {
  123. id_bits[n] = read_hex (*id++) << 4;
  124. id_bits[n++] |= read_hex (*id++);
  125. }
  126. else if (*id == '-' || *id == ':')
  127. ++id;
  128. else
  129. abort (); /* Should have been validated earlier. */
  130. } while (*id != '\0');
  131. }
  132. else
  133. abort (); /* Should have been validated earlier. */
  134. return TRUE;
  135. }