sha1sum.c (5691B)
- // utils-std: Collection of commonly available Unix tools
- // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
- // SPDX-License-Identifier: MPL-2.0
- #define _POSIX_C_SOURCE 200809L
- #include "../lib/sha1.h" // sha1_*
- #include "../lib/strconv.h" // bytes2hex
- #include <ctype.h> // isxdigit
- #include <errno.h>
- #include <fcntl.h> // open, O_*
- #include <stdbool.h>
- #include <stdio.h> // fprintf
- #include <stdlib.h> // free
- #include <string.h> // strerror
- #include <unistd.h> // read, write, close, getopt
- #define SHA1SUM_LEN SHA1_DIGEST_LENGTH * 2 + 1
- const char *argv0 = "sha1sum";
- static int
- sha1sum(int fd, const char *fdname, char sum[SHA1SUM_LEN])
- {
- struct sha1 ctx;
- sha1_init(&ctx);
- uint8_t buf[BUFSIZ];
- ssize_t nread = -1;
- while((nread = read(fd, buf, BUFSIZ)) > 0)
- {
- sha1_update(&ctx, buf, nread);
- }
- if(nread < 0)
- {
- fprintf(stderr,
- "%s: error: Failed reading file '%s': %s\n",
- argv0,
- fdname ? fdname : "<stdin>",
- strerror(errno));
- return -1;
- }
- uint8_t res[SHA1_DIGEST_LENGTH] = "";
- sha1_sum(&ctx, res);
- bytes2hex(res, SHA1_DIGEST_LENGTH, sum, SHA1SUM_LEN);
- return 0;
- }
- #define STR(s) #s
- #define XSTR(s) STR(s)
- static int
- check(FILE *file, const char *filename)
- {
- int err = 0;
- ssize_t nread = -1;
- char *line = NULL;
- size_t len = 0;
- errno = 0;
- while((nread = getline(&line, &len, file)) > 0)
- {
- if(line[nread - 1] == '\n') line[nread - 1] = '\0';
- ssize_t i = 0;
- for(; i < nread; i++)
- {
- if(isxdigit(line[i])) continue;
- if(line[i] == ' ')
- {
- line[i] = '\0';
- break;
- }
- fprintf(stderr,
- "%s: error: Invalid character '%c' while reading hash in line: %s\n",
- argv0,
- line[i],
- line);
- if(len > 0) free(line);
- return -1;
- }
- if(line[i++] != '\0')
- {
- fprintf(stderr, "%s: error: Invalid line: %s\n", argv0, line);
- if(len > 0) free(line);
- return -1;
- }
- if(i != SHA1SUM_LEN)
- {
- fprintf(stderr,
- "%s: error: Got %zd hexadecimal digits while expected %d for a SHA1\n",
- argv0,
- i,
- SHA1SUM_LEN);
- if(len > 0) free(line);
- return -1;
- }
- while(i < nread && line[i] == ' ')
- i++;
- if(i < nread && line[i] == '*') i++;
- char *target = line + i;
- int fd = open(target, O_RDONLY | O_NOCTTY);
- if(fd < 0)
- {
- fprintf(stderr, "%s: error: Failed opening file '%s': %s\n", argv0, target, strerror(errno));
- if(len > 0) free(line);
- return -1;
- }
- int ret = posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
- if(ret != 0)
- fprintf(stderr,
- "%s: warning: posix_fadvise failed on file '%s': %s\n",
- argv0,
- target,
- strerror(ret));
- char got[SHA1SUM_LEN] = "";
- if(sha1sum(fd, target, got) < 0) err = 1;
- if(memcmp(line, got, SHA1SUM_LEN) == 0)
- {
- printf("%s: OK\n", target);
- }
- else
- {
- err = 1;
- printf("%s: FAILED\n", target);
- }
- if(close(fd) < 0)
- {
- fprintf(
- stderr, "%s: error: Failed closing file '%s': %s\n", argv0, filename, strerror(errno));
- if(len > 0) free(line);
- return -1;
- }
- }
- if(nread < 0 && errno != 0)
- {
- err = 1;
- fprintf(stderr,
- "%s: error: Failed reading line from file '%s': %s\n",
- argv0,
- filename,
- strerror(errno));
- }
- if(len > 0) free(line);
- return err;
- }
- int
- main(int argc, char *argv[])
- {
- bool opt_c = false;
- int c = -1;
- while((c = getopt(argc, argv, ":c")) != -1)
- {
- switch(c)
- {
- case 'c':
- opt_c = true;
- break;
- case ':':
- fprintf(stderr, "%s: error: Missing operand for option: '-%c'\n", argv0, optopt);
- return 1;
- case '?':
- fprintf(stderr, "%s: error: Unrecognised option: '-%c'\n", argv0, optopt);
- return 1;
- default:
- abort();
- }
- }
- argc -= optind;
- argv += optind;
- if(opt_c)
- {
- if(argc == 0)
- {
- if(check(stdin, "<stdin>") != 0) return 1;
- return 0;
- }
- int err = 0;
- for(int i = 0; i < argc; i++)
- {
- FILE *file = NULL;
- const char *filename = argv[i];
- if(filename[0] == '-' && filename[1] == '\0')
- {
- filename = "<stdin>";
- file = stdin;
- }
- else
- {
- file = fopen(filename, "rb");
- if(file == NULL)
- {
- fprintf(stderr,
- "%s: error: Failed opening file '%s': %s\n",
- argv0,
- filename,
- strerror(errno));
- return 1;
- }
- }
- if(check(file, filename) != 0) err = 1;
- if(fclose(file) < 0)
- {
- fprintf(
- stderr, "%s: error: Failed closing file '%s': %s\n", argv0, filename, strerror(errno));
- return 1;
- }
- }
- return err;
- }
- if(argc == 0)
- {
- char sum[SHA1SUM_LEN] = "";
- if(sha1sum(STDIN_FILENO, NULL, sum) < 0) return 1;
- puts(sum);
- return 0;
- }
- for(int i = 0; i < argc; i++)
- {
- int fd = -1;
- const char *filename = argv[i];
- if(filename[0] == '-' && filename[1] == '\0')
- {
- filename = "<stdin>";
- fd = STDIN_FILENO;
- }
- else
- {
- fd = open(filename, O_RDONLY | O_NOCTTY);
- if(fd < 0)
- {
- fprintf(
- stderr, "%s: error: Failed opening file '%s': %s\n", argv0, filename, strerror(errno));
- return 1;
- }
- int ret = posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
- if(ret != 0)
- fprintf(stderr,
- "%s: warning: posix_fadvise failed on file '%s': %s\n",
- argv0,
- filename,
- strerror(ret));
- }
- int err = 0;
- char sum[SHA1SUM_LEN] = "";
- if(sha1sum(fd, filename, sum) < 0) err = 1;
- printf("%s %s\n", sum, filename);
- if(close(fd) < 0)
- {
- fprintf(
- stderr, "%s: error: Failed closing file '%s': %s\n", argv0, filename, strerror(errno));
- return 1;
- }
- if(err == 1) return 1;
- }
- return 0;
- }