logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git

sha512sum.c (5442B)


  1. // utils-std: Collection of commonly available Unix tools
  2. // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: MPL-2.0
  4. #define _POSIX_C_SOURCE 200809L
  5. #include "../lib/sha512.h" // sha512_*
  6. #include "../lib/strconv.h" // bytes2hex
  7. #include <assert.h>
  8. #include <ctype.h> // isxdigit
  9. #include <errno.h>
  10. #include <fcntl.h> // open, O_*
  11. #include <stdbool.h>
  12. #include <stdio.h> // fprintf
  13. #include <stdlib.h> // free
  14. #include <string.h> // strerror
  15. #include <unistd.h> // read, write, close, getopt
  16. #define SHA512SUM_LEN SHA512_DIGEST_LENGTH * 2 + 1
  17. static int
  18. sha512sum(int fd, const char *fdname, char sum[SHA512SUM_LEN])
  19. {
  20. struct sha512 ctx;
  21. sha512_init(&ctx);
  22. uint8_t buf[BUFSIZ];
  23. ssize_t nread = -1;
  24. while((nread = read(fd, buf, BUFSIZ)) > 0)
  25. {
  26. sha512_update(&ctx, buf, nread);
  27. }
  28. if(nread < 0)
  29. {
  30. fprintf(stderr,
  31. "sha512sum: I/O Error while reading file '%s': %s\n",
  32. fdname ? fdname : "<stdin>",
  33. strerror(errno));
  34. return -1;
  35. }
  36. uint8_t res[SHA512_DIGEST_LENGTH] = "";
  37. sha512_sum(&ctx, res);
  38. bytes2hex(res, SHA512_DIGEST_LENGTH, sum, SHA512SUM_LEN);
  39. return 0;
  40. }
  41. #define STR(s) #s
  42. #define XSTR(s) STR(s)
  43. static int
  44. check(FILE *file, const char *filename)
  45. {
  46. int err = 0;
  47. ssize_t nread = -1;
  48. char *line = NULL;
  49. size_t len = 0;
  50. errno = 0;
  51. while((nread = getline(&line, &len, file)) > 0)
  52. {
  53. assert(errno == 0);
  54. if(line[nread - 1] == '\n') line[nread - 1] = '\0';
  55. ssize_t i = 0;
  56. for(; i < nread; i++)
  57. {
  58. if(isxdigit(line[i])) continue;
  59. if(line[i] == ' ')
  60. {
  61. line[i] = '\0';
  62. break;
  63. }
  64. fprintf(stderr,
  65. "sha512sum: Error: Invalid character '%c' while reading hash in line: %s\n",
  66. line[i],
  67. line);
  68. if(len > 0) free(line);
  69. return -1;
  70. }
  71. if(line[i++] != '\0')
  72. {
  73. fprintf(stderr, "sha512sum: Error: Invalid line: %s\n", line);
  74. if(len > 0) free(line);
  75. return -1;
  76. }
  77. if(i != SHA512SUM_LEN)
  78. {
  79. fprintf(stderr,
  80. "sha512sum: Error: Got %zd hexadecimal digits while expected %d for a SHA512\n",
  81. i,
  82. SHA512SUM_LEN);
  83. if(len > 0) free(line);
  84. return -1;
  85. }
  86. while(i < nread && line[i] == ' ')
  87. i++;
  88. if(i < nread && line[i] == '*') i++;
  89. char *target = line + i;
  90. int fd = open(target, O_RDONLY | O_NOCTTY);
  91. if(fd < 0)
  92. {
  93. fprintf(stderr, "sha512sum: Error: Failed opening file '%s': %s\n", target, strerror(errno));
  94. if(len > 0) free(line);
  95. return -1;
  96. }
  97. int ret = posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
  98. if(ret != 0)
  99. fprintf(stderr,
  100. "sha512sum: Warning: posix_fadvise failed on file '%s': %s\n",
  101. target,
  102. strerror(ret));
  103. char got[SHA512SUM_LEN] = "";
  104. if(sha512sum(fd, target, got) < 0) err = 1;
  105. if(memcmp(line, got, SHA512SUM_LEN) == 0)
  106. {
  107. printf("%s: OK\n", target);
  108. }
  109. else
  110. {
  111. err = 1;
  112. printf("%s: FAILED\n", target);
  113. }
  114. if(close(fd) < 0)
  115. {
  116. fprintf(stderr, "sha512sum: Failed closing file '%s': %s\n", filename, strerror(errno));
  117. if(len > 0) free(line);
  118. return -1;
  119. }
  120. }
  121. if(nread < 0 && errno != 0)
  122. {
  123. err = 1;
  124. fprintf(
  125. stderr, "sha512sum: Failed reading line from file '%s': %s\n", filename, strerror(errno));
  126. }
  127. if(len > 0) free(line);
  128. return err;
  129. }
  130. int
  131. main(int argc, char *argv[])
  132. {
  133. bool opt_c = false;
  134. int c = -1;
  135. while((c = getopt(argc, argv, "c")) != -1)
  136. {
  137. switch(c)
  138. {
  139. case 'c':
  140. opt_c = true;
  141. break;
  142. default:
  143. fprintf(stderr, "sha512sum: Unhandled option '-%c'\n", c);
  144. return 1;
  145. }
  146. }
  147. argc -= optind;
  148. argv += optind;
  149. if(opt_c)
  150. {
  151. if(argc == 0)
  152. {
  153. if(check(stdin, "<stdin>") != 0) return 1;
  154. return 0;
  155. }
  156. int err = 0;
  157. for(int i = 0; i < argc; i++)
  158. {
  159. FILE *file = NULL;
  160. const char *filename = argv[i];
  161. if(filename[0] == '-' && filename[1] == '\0')
  162. {
  163. filename = "<stdin>";
  164. file = stdin;
  165. }
  166. else
  167. {
  168. file = fopen(filename, "rb");
  169. if(file == NULL)
  170. {
  171. fprintf(stderr,
  172. "sha512sum: Error: Failed opening file '%s': %s\n",
  173. filename,
  174. strerror(errno));
  175. return 1;
  176. }
  177. }
  178. if(check(file, filename) != 0) err = 1;
  179. if(fclose(file) < 0)
  180. {
  181. fprintf(stderr, "sha512sum: Failed closing file '%s': %s\n", filename, strerror(errno));
  182. return 1;
  183. }
  184. }
  185. return err;
  186. }
  187. if(argc == 0)
  188. {
  189. char sum[SHA512SUM_LEN] = "";
  190. if(sha512sum(STDIN_FILENO, NULL, sum) < 0) return 1;
  191. puts(sum);
  192. return 0;
  193. }
  194. for(int i = 0; i < argc; i++)
  195. {
  196. int fd = -1;
  197. const char *filename = argv[i];
  198. if(filename[0] == '-' && filename[1] == '\0')
  199. {
  200. filename = "<stdin>";
  201. fd = STDIN_FILENO;
  202. }
  203. else
  204. {
  205. fd = open(filename, O_RDONLY | O_NOCTTY);
  206. if(fd < 0)
  207. {
  208. fprintf(
  209. stderr, "sha512sum: Error: Failed opening file '%s': %s\n", filename, strerror(errno));
  210. return 1;
  211. }
  212. int ret = posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
  213. if(ret != 0)
  214. fprintf(stderr,
  215. "sha512sum: Warning: posix_fadvise failed on file '%s': %s\n",
  216. filename,
  217. strerror(ret));
  218. }
  219. int err = 0;
  220. char sum[SHA512SUM_LEN] = "";
  221. if(sha512sum(fd, filename, sum) < 0) err = 1;
  222. printf("%s %s\n", sum, filename);
  223. if(close(fd) < 0)
  224. {
  225. fprintf(stderr, "sha512sum: Failed closing file '%s': %s\n", filename, strerror(errno));
  226. return 1;
  227. }
  228. if(err == 1) return 1;
  229. }
  230. return 0;
  231. }