aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile30
-rw-r--r--b224sum.16
-rw-r--r--b256sum.16
-rw-r--r--b2sum.188
-rw-r--r--b2sum.c295
-rw-r--r--b384sum.16
-rw-r--r--b512sum.16
-rw-r--r--bsum.18
-rw-r--r--bsum.c269
-rw-r--r--common.c228
-rw-r--r--common.h10
12 files changed, 710 insertions, 243 deletions
diff --git a/.gitignore b/.gitignore
index d17d682..f43afce 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@
*.gcno
*.gcda
/bsum
+/b2sum
diff --git a/Makefile b/Makefile
index 3f743a8..e09140b 100644
--- a/Makefile
+++ b/Makefile
@@ -3,31 +3,43 @@
CONFIGFILE = config.mk
include $(CONFIGFILE)
+BIN =\
+ bsum\
+ b2sum
+
OBJ =\
- bsum.o
+ $(BIN:=.o)\
+ common.o
HDR =\
arg.h\
common.h
-all: bsum
+all: $(BIN)
$(OBJ): $(HDR)
.c.o:
$(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS)
-bsum: $(OBJ)
- $(CC) -o $@ $(OBJ) $(LDFLAGS)
+bsum: bsum.o common.o
+ $(CC) -o $@ $@.o common.o $(LDFLAGS)
+
+b2sum: b2sum.o common.o
+ $(CC) -o $@ $@.o common.o $(LDFLAGS)
-install: bsum
+install: $(BIN)
mkdir -p -- "$(DESTDIR)$(PREFIX)/bin"
mkdir -p -- "$(DESTDIR)$(MANPREFIX)/man1/"
- cp -- bsum "$(DESTDIR)$(PREFIX)/bin/"
+ cp -- $(BIN) "$(DESTDIR)$(PREFIX)/bin/"
ln -sf -- bsum "$(DESTDIR)$(PREFIX)/bin/b224sum"
ln -sf -- bsum "$(DESTDIR)$(PREFIX)/bin/b256sum"
ln -sf -- bsum "$(DESTDIR)$(PREFIX)/bin/b384sum"
ln -sf -- bsum "$(DESTDIR)$(PREFIX)/bin/b512sum"
- cp -- bsum.1 "$(DESTDIR)$(MANPREFIX)/man1/"
+ cp -- $(BIN:=.1) "$(DESTDIR)$(MANPREFIX)/man1/"
+ cp -- b224sum.1 "$(DESTDIR)$(MANPREFIX)/man1/b224sum.1"
+ cp -- b256sum.1 "$(DESTDIR)$(MANPREFIX)/man1/b256sum.1"
+ cp -- b384sum.1 "$(DESTDIR)$(MANPREFIX)/man1/b384sum.1"
+ cp -- b512sum.1 "$(DESTDIR)$(MANPREFIX)/man1/b512sum.1"
uninstall:
-rm -f -- "$(DESTDIR)$(PREFIX)/bin/bsum"
@@ -35,15 +47,17 @@ uninstall:
-rm -f -- "$(DESTDIR)$(PREFIX)/bin/b256sum"
-rm -f -- "$(DESTDIR)$(PREFIX)/bin/b384sum"
-rm -f -- "$(DESTDIR)$(PREFIX)/bin/b512sum"
+ -rm -f -- "$(DESTDIR)$(PREFIX)/bin/b2sum"
-rm -f -- "$(DESTDIR)$(MANPREFIX)/man1/bsum.1"
-rm -f -- "$(DESTDIR)$(MANPREFIX)/man1/b224sum.1"
-rm -f -- "$(DESTDIR)$(MANPREFIX)/man1/b256sum.1"
-rm -f -- "$(DESTDIR)$(MANPREFIX)/man1/b384sum.1"
-rm -f -- "$(DESTDIR)$(MANPREFIX)/man1/b512sum.1"
+ -rm -f -- "$(DESTDIR)$(MANPREFIX)/man1/b2sum.1"
clean:
-rm -f -- *.o *.su *.gcov *.gcno *.gcda
- -rm -f -- bsum
+ -rm -f -- $(BIN)
.SUFFIXES:
.SUFFIXES: .o .c
diff --git a/b224sum.1 b/b224sum.1
index 82c6a48..874535a 100644
--- a/b224sum.1
+++ b/b224sum.1
@@ -66,3 +66,9 @@ Checksums did not match or a file did not exist.
.TP
2
An error occurred.
+.SH SEE ALSO
+.BR bsum (1),
+.BR b2sum (1),
+.BR b256sum (1),
+.BR b384sum (1),
+.BR b512sum (1)
diff --git a/b256sum.1 b/b256sum.1
index 4998b57..039ee51 100644
--- a/b256sum.1
+++ b/b256sum.1
@@ -66,3 +66,9 @@ Checksums did not match or a file did not exist.
.TP
2
An error occurred.
+.SH SEE ALSO
+.BR bsum (1),
+.BR b2sum (1),
+.BR b224sum (1),
+.BR b384sum (1),
+.BR b512sum (1)
diff --git a/b2sum.1 b/b2sum.1
new file mode 100644
index 0000000..a4e1f4b
--- /dev/null
+++ b/b2sum.1
@@ -0,0 +1,88 @@
+.TH B2SUM 1 blakesum
+.SH NAME
+b2sum - Compute and check BLAKE2 message digests
+.SH SYNOPSIS
+.B bsum
+[-l bits | -X bits] [-c | -B | -L | -U] [-sxz]
+.RI [ file "] ..."
+.SH DESCRIPTION
+Print or check BLAKE2 checksums, using BLAKE2b by default.
+.SH OPTIONS
+The
+.B b2sum
+utility conforms to the Base Definitions volume of POSIX.1-2017,
+.IR "Section 12.2" ,
+.IR "Utility Syntax Guidelines" .
+.PP
+The following options are supported:
+.TP
+.B -B
+Output checksums in binary representation. This suppresses
+the filenames and checksum delimiters. Only the checksums
+are printed.
+.TP
+.B -c
+Read BLAKE2 sums from the file and check them against the
+files on your systems. The input files files should be
+formatted as the output of this program, or similarly.
+This is not going to work if any of the filenames in the
+input files starts with <space> or <tab>, or if they
+contain a <newline, unless the
+.B -z
+option is also used.
+.TP
+.B -L
+Output checksums in lower-case hexadecimal representation. (Default)
+.TP
+.BI "-l " bits
+Select output size, valid values are multiples of 8
+between 8 and 512, inclusively, or if the
+.B -s
+option is used between 8 and 256, inclusively.
+(Default is maximum.)
+.TP
+.B -s
+Use BLAKE2s instead of BLAKE2b.
+.TP
+.B -U
+Output checksums in upper-case hexadecimal representation.
+.TP
+.BI "-X " bits
+Use BLAKE2Xb instead of BLAKE2b or BLAKE2Xs instead of BLAKE2s,
+and select the extended output function output length, int bits,
+must be a non-zero multiple of 8, and no greater than
+34359738360 or (if the
+.B -s
+option is used) 524280.
+.TP
+.B -x
+Convert input files from hexadecimal form to binary form
+before calculating the checksums.
+.TP
+.B -z
+Lines end with NUL instead of LF. If used with
+.BR -c ,
+this applies to read files (not the output), but it will
+also apply more strict parsing and allow any whitespace
+in file names.
+.SH OPERANDS
+The following operands are supported:
+.TP
+.I file
+File to read. The standard input will be used
+.B -
+or no
+.I file
+is specified.
+.SH EXIT STATUS
+.TP
+0
+Successful completion.
+.TP
+1
+Checksums did not match or a file did not exist.
+.TP
+2
+An error occurred.
+.SJ SEE ALSO
+.BR bsum (1)
diff --git a/b2sum.c b/b2sum.c
new file mode 100644
index 0000000..b70aad8
--- /dev/null
+++ b/b2sum.c
@@ -0,0 +1,295 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+const char *argv0 = "b2sum";
+
+static int flag_check = 0;
+static int flag_binary = 0;
+static int flag_lower = 0;
+static int flag_upper = 0;
+static int flag_small = 0;
+static int flag_extended = 0;
+static int flag_hex = 0;
+static int flag_zero = 0;
+static int length = 0;
+static long long int xlength = 0;
+
+static size_t hashlen;
+
+static void
+usage(void)
+{
+ /* TODO add support for key, salt, and personalization */
+ /* TODO add support for parallel versions */
+ fprintf(stderr, "usage: %s [-l bits | -X bits] [-c | -B | -L | -U] [-sxz] [file] ...", argv0);
+ exit(2);
+}
+
+static int
+hash_fd_blake2bs(int fd, const char *fname, int decode_hex, unsigned char hash[])
+{
+ struct libblake_blake2b_state state2b;
+ struct libblake_blake2b_params params2b;
+ struct libblake_blake2s_state state2s;
+ struct libblake_blake2s_params params2s;
+ char *buf = NULL;
+ size_t size = 0;
+ size_t len = 0;
+ size_t off = 0;
+ size_t req;
+ ssize_t r;
+ int ok;
+ if (flag_small) {
+ memset(&params2s, 0, sizeof(params2s));
+ params2s.digest_len = (uint_least8_t)length;
+ params2s.fanout = 1;
+ params2s.depth = 1;
+ libblake_blake2s_init(&state2s, &params2s, NULL);
+ } else {
+ memset(&params2b, 0, sizeof(params2b));
+ params2b.digest_len = (uint_least8_t)length;
+ params2b.fanout = 1;
+ params2b.depth = 1;
+ libblake_blake2b_init(&state2b, &params2b, NULL);
+ }
+ for (;;) {
+ if (len == size)
+ buf = erealloc(buf, size += 8 << 10);
+ r = read(fd, &buf[len], size - len);
+ if (r <= 0) {
+ if (!r)
+ break;
+ if (errno == EINTR)
+ continue;
+ fprintf(stderr, "%s: %s: %s\n", argv0, fname, strerror(errno));
+ free(buf);
+ return -1;
+ }
+ len += (size_t)r;
+ if (!decode_hex) {
+ if (flag_small)
+ off += libblake_blake2s_update(&state2s, &buf[off], len - off);
+ else
+ off += libblake_blake2b_update(&state2b, &buf[off], len - off);
+ if (off == len)
+ off = 0;
+ }
+ }
+ if (off)
+ memmove(&buf[0], &buf[off], len -= off);
+ if (decode_hex) {
+ len = libblake_decode_hex(buf, len, buf, &ok);
+ if (!ok) {
+ fprintf(stderr, "%s: %s: %s\n", argv0, fname, "invalid hexadecimal input");
+ free(buf);
+ return -1;
+ }
+ }
+ if (flag_small)
+ req = libblake_blake2s_digest_get_required_input_size(len);
+ else
+ req = libblake_blake2b_digest_get_required_input_size(len);
+ if (req > size)
+ buf = erealloc(buf, size);
+ if (flag_small)
+ libblake_blake2s_digest(&state2s, buf, len, 0, hashlen / 8, hash);
+ else
+ libblake_blake2b_digest(&state2b, buf, len, 0, hashlen / 8, hash);
+ free(buf);
+ return 0;
+}
+
+static int
+hash_fd_blake2bsx(int fd, const char *fname, int decode_hex, unsigned char hash[])
+{
+ struct libblake_blake2xb_state state2xb;
+ struct libblake_blake2xb_params params2xb;
+ struct libblake_blake2xs_state state2xs;
+ struct libblake_blake2xs_params params2xs;
+ char *buf = NULL;
+ size_t size = 0;
+ size_t len = 0;
+ size_t off = 0;
+ size_t req;
+ size_t i, n;
+ ssize_t r;
+ int ok;
+ if (flag_small) {
+ memset(&params2xs, 0, sizeof(params2xs));
+ params2xs.digest_len = (uint_least8_t)length;
+ params2xs.fanout = 1;
+ params2xs.depth = 1;
+ params2xs.xof_len = (uint_least16_t)xlength;
+ libblake_blake2xs_init(&state2xs, &params2xs, NULL);
+ } else {
+ memset(&params2xb, 0, sizeof(params2xb));
+ params2xb.digest_len = (uint_least8_t)length;
+ params2xb.fanout = 1;
+ params2xb.depth = 1;
+ params2xb.xof_len = (uint_least32_t)xlength;
+ libblake_blake2xb_init(&state2xb, &params2xb, NULL);
+ }
+ for (;;) {
+ if (len == size)
+ buf = erealloc(buf, size += 8 << 10);
+ r = read(fd, &buf[len], size - len);
+ if (r <= 0) {
+ if (!r)
+ break;
+ if (errno == EINTR)
+ continue;
+ fprintf(stderr, "%s: %s: %s\n", argv0, fname, strerror(errno));
+ free(buf);
+ return -1;
+ }
+ len += (size_t)r;
+ if (!decode_hex) {
+ if (flag_small)
+ off += libblake_blake2xs_update(&state2xs, &buf[off], len - off);
+ else
+ off += libblake_blake2xb_update(&state2xb, &buf[off], len - off);
+ if (off == len)
+ off = 0;
+ }
+ }
+ if (off)
+ memmove(&buf[0], &buf[off], len -= off);
+ if (decode_hex) {
+ len = libblake_decode_hex(buf, len, buf, &ok);
+ if (!ok) {
+ fprintf(stderr, "%s: %s: %s\n", argv0, fname, "invalid hexadecimal input");
+ free(buf);
+ return -1;
+ }
+ }
+ if (flag_small)
+ req = libblake_blake2xs_predigest_get_required_input_size(&state2xs);
+ else
+ req = libblake_blake2xb_predigest_get_required_input_size(&state2xb);
+ if (req > size)
+ buf = erealloc(buf, size);
+ if (flag_small)
+ libblake_blake2xs_predigest(&state2xs, buf, len, 0);
+ else
+ libblake_blake2xb_predigest(&state2xb, buf, len, 0);
+ if (flag_small) {
+ for (i = 0; i * 32 < hashlen / 8; i++) { /* TODO this could be done parallel (also below) */
+ n = (i + 1) * 32 > hashlen / 8 ? hashlen / 8 - i * 32 : 32;
+ libblake_blake2xs_digest(&state2xs, (uint_least32_t)i, (uint_least8_t)n, &hash[i * 32]);
+ }
+ } else {
+ for (i = 0; i * 64 < hashlen / 8; i++) {
+ n = (i + 1) * 64 > hashlen / 8 ? hashlen / 8 - i * 64 : 64;
+ libblake_blake2xb_digest(&state2xb, (uint_least32_t)i, (uint_least8_t)n, &hash[i * 64]);
+ }
+ }
+ free(buf);
+ return 0;
+}
+
+int
+hash_fd(int fd, const char *fname, int decode_hex, unsigned char hash[])
+{
+ int ret;
+
+ if (flag_extended)
+ ret = hash_fd_blake2bsx(fd, fname, decode_hex, hash);
+ else
+ ret = hash_fd_blake2bs(fd, fname, decode_hex, hash);
+
+ return ret;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int status = 0;
+ int output_case;
+ char newline;
+
+ ARGBEGIN {
+ case 'c':
+ flag_check = 1;
+ break;
+ case 'B':
+ flag_binary = 1;
+ break;
+ case 'L':
+ flag_lower = 1;
+ flag_upper = 0;
+ break;
+ case 'U':
+ flag_upper = 1;
+ flag_lower = 0;
+ break;
+ case 's':
+ flag_small = 1;
+ break;
+ case 'x':
+ flag_hex = 1;
+ break;
+ case 'z':
+ flag_zero = 1;
+ break;
+ case 'l':
+ if (length)
+ usage();
+ length = atoi(ARG());
+ if (length & 7 || !length || length > 512) {
+ fprintf(stderr, "%s: valid arguments for -l\n", argv0);
+ return 2;
+ }
+ break;
+ case 'X':
+ if (flag_extended)
+ usage();
+ flag_extended = 1;
+ xlength = atoll(ARG());
+ if (xlength & 7 || !xlength || xlength > 34359738360LL) {
+ fprintf(stderr, "%s: valid arguments for -X\n", argv0);
+ return 2;
+ }
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (flag_check + flag_binary + flag_lower + flag_upper > 1 ||
+ (length && flag_extended))
+ usage();
+
+ if (!length)
+ length = flag_small ? 256 : 512;
+ else if (flag_small && length > 256)
+ fprintf(stderr, "%s: valid arguments for -l\n", argv0);
+ else if (flag_small && xlength > 524280LL)
+ fprintf(stderr, "%s: valid arguments for -X\n", argv0);
+
+ hashlen = flag_extended ? (size_t)xlength : (size_t)length;
+ length /= 8;
+ xlength /= 8;
+
+ newline = flag_zero ? '\0' : '\n';
+ if (flag_check) {
+ if (!argc) {
+ status |= -check_and_print("-", hashlen, flag_hex, newline);
+ } else {
+ for (; *argv; argv++)
+ status |= -check_and_print(*argv, hashlen, flag_hex, newline);
+ }
+ } else {
+ output_case = flag_binary ? -1 : flag_upper;
+ if (!argc) {
+ status |= -hash_and_print("-", hashlen, flag_hex, newline, output_case);
+ } else {
+ for (; *argv; argv++)
+ status |= -hash_and_print(*argv, hashlen, flag_hex, newline, output_case);
+ }
+ }
+
+ if (fflush(stdout) || ferror(stdout) || fclose(stdout)) {
+ fprintf(stderr, "%s: %s\n", argv0, strerror(errno));
+ return 2;
+ }
+ return status;
+}
diff --git a/b384sum.1 b/b384sum.1
index 925b698..d7f2eaf 100644
--- a/b384sum.1
+++ b/b384sum.1
@@ -66,3 +66,9 @@ Checksums did not match or a file did not exist.
.TP
2
An error occurred.
+.SH SEE ALSO
+.BR bsum (1),
+.BR b2sum (1),
+.BR b224sum (1),
+.BR b256sum (1),
+.BR b512sum (1)
diff --git a/b512sum.1 b/b512sum.1
index ebaf844..2c0fd00 100644
--- a/b512sum.1
+++ b/b512sum.1
@@ -66,3 +66,9 @@ Checksums did not match or a file did not exist.
.TP
2
An error occurred.
+.SH SEE ALSO
+.BR bsum (1),
+.BR b2sum (1),
+.BR b224sum (1),
+.BR b256sum (1),
+.BR b384sum (1)
diff --git a/bsum.1 b/bsum.1
index d8ca915..442af70 100644
--- a/bsum.1
+++ b/bsum.1
@@ -34,7 +34,7 @@ option is also used.
.B -L
Output checksums in lower-case hexadecimal representation. (Default)
.TP
-.B -l
+.BI "-l " bits
Select version of the BLAKE algorithm. Valid values
are 224 (default), 256, 384, and 512.
.TP
@@ -70,3 +70,9 @@ Checksums did not match or a file did not exist.
.TP
2
An error occurred.
+.SH SEE ALSO
+.BR b2sum (1),
+.BR b224sum (1),
+.BR b256sum (1),
+.BR b384sum (1),
+.BR b512sum (1)
diff --git a/bsum.c b/bsum.c
index cbc8b51..1940cf2 100644
--- a/bsum.c
+++ b/bsum.c
@@ -5,6 +5,14 @@ const char *argv0 = "bsum";
static int lenght_by_command_name = 0;
+static int flag_check = 0;
+static int flag_binary = 0;
+static int flag_lower = 0;
+static int flag_upper = 0;
+static int flag_hex = 0;
+static int flag_zero = 0;
+static int length;
+
static void
usage(void)
{
@@ -13,36 +21,24 @@ usage(void)
exit(2);
}
-static void *
-erealloc(void *ptr, size_t n)
-{
- ptr = realloc(ptr, n);
- if (!ptr) {
- fprintf(stderr, "%s: %s\n", argv0, strerror(errno));
- exit(2);
- }
- return ptr;
-}
-
static void
get_lenght_by_command_name(const char *command)
{
const char *p;
p = strrchr(command, '/');
p = p ? &p[1] : command;
- if (strstr(p, "b224sum")) {
+ if (strstr(p, "b224sum"))
lenght_by_command_name = 224;
- } else if (strstr(p, "b256sum")) {
+ else if (strstr(p, "b256sum"))
lenght_by_command_name = 256;
- } else if (strstr(p, "b384sum")) {
+ else if (strstr(p, "b384sum"))
lenght_by_command_name = 384;
- } else if (strstr(p, "b512sum")) {
+ else if (strstr(p, "b512sum"))
lenght_by_command_name = 512;
- }
}
static int
-hash_file_blake224(int fd, const char *fname, int decode_hex, unsigned char hash[], size_t *hash_lenp)
+hash_fd_blake224(int fd, const char *fname, int decode_hex, unsigned char hash[])
{
struct libblake_blake224_state state;
char *buf = NULL;
@@ -63,6 +59,7 @@ hash_file_blake224(int fd, const char *fname, int decode_hex, unsigned char hash
if (errno == EINTR)
continue;
fprintf(stderr, "%s: %s: %s\n", argv0, fname, strerror(errno));
+ free(buf);
return -1;
}
len += (size_t)r;
@@ -78,6 +75,7 @@ hash_file_blake224(int fd, const char *fname, int decode_hex, unsigned char hash
len = libblake_decode_hex(buf, len, buf, &ok);
if (!ok) {
fprintf(stderr, "%s: %s: %s\n", argv0, fname, "invalid hexadecimal input");
+ free(buf);
return -1;
}
}
@@ -85,13 +83,12 @@ hash_file_blake224(int fd, const char *fname, int decode_hex, unsigned char hash
if (req > size)
buf = erealloc(buf, size);
libblake_blake224_digest(&state, buf, len, 0, NULL, hash);
- *hash_lenp = LIBBLAKE_BLAKE224_OUTPUT_SIZE;
free(buf);
return 0;
}
static int
-hash_file_blake256(int fd, const char *fname, int decode_hex, unsigned char hash[], size_t *hash_lenp)
+hash_fd_blake256(int fd, const char *fname, int decode_hex, unsigned char hash[])
{
struct libblake_blake256_state state;
char *buf = NULL;
@@ -112,6 +109,7 @@ hash_file_blake256(int fd, const char *fname, int decode_hex, unsigned char hash
if (errno == EINTR)
continue;
fprintf(stderr, "%s: %s: %s\n", argv0, fname, strerror(errno));
+ free(buf);
return -1;
}
len += (size_t)r;
@@ -127,6 +125,7 @@ hash_file_blake256(int fd, const char *fname, int decode_hex, unsigned char hash
len = libblake_decode_hex(buf, len, buf, &ok);
if (!ok) {
fprintf(stderr, "%s: %s: %s\n", argv0, fname, "invalid hexadecimal input");
+ free(buf);
return -1;
}
}
@@ -134,13 +133,12 @@ hash_file_blake256(int fd, const char *fname, int decode_hex, unsigned char hash
if (req > size)
buf = erealloc(buf, size);
libblake_blake256_digest(&state, buf, len, 0, NULL, hash);
- *hash_lenp = LIBBLAKE_BLAKE256_OUTPUT_SIZE;
free(buf);
return 0;
}
static int
-hash_file_blake384(int fd, const char *fname, int decode_hex, unsigned char hash[], size_t *hash_lenp)
+hash_fd_blake384(int fd, const char *fname, int decode_hex, unsigned char hash[])
{
struct libblake_blake384_state state;
char *buf = NULL;
@@ -161,6 +159,7 @@ hash_file_blake384(int fd, const char *fname, int decode_hex, unsigned char hash
if (errno == EINTR)
continue;
fprintf(stderr, "%s: %s: %s\n", argv0, fname, strerror(errno));
+ free(buf);
return -1;
}
len += (size_t)r;
@@ -176,6 +175,7 @@ hash_file_blake384(int fd, const char *fname, int decode_hex, unsigned char hash
len = libblake_decode_hex(buf, len, buf, &ok);
if (!ok) {
fprintf(stderr, "%s: %s: %s\n", argv0, fname, "invalid hexadecimal input");
+ free(buf);
return -1;
}
}
@@ -183,13 +183,12 @@ hash_file_blake384(int fd, const char *fname, int decode_hex, unsigned char hash
if (req > size)
buf = erealloc(buf, size);
libblake_blake384_digest(&state, buf, len, 0, NULL, hash);
- *hash_lenp = LIBBLAKE_BLAKE384_OUTPUT_SIZE;
free(buf);
return 0;
}
static int
-hash_file_blake512(int fd, const char *fname, int decode_hex, unsigned char hash[], size_t *hash_lenp)
+hash_fd_blake512(int fd, const char *fname, int decode_hex, unsigned char hash[])
{
struct libblake_blake512_state state;
char *buf = NULL;
@@ -210,6 +209,7 @@ hash_file_blake512(int fd, const char *fname, int decode_hex, unsigned char hash
if (errno == EINTR)
continue;
fprintf(stderr, "%s: %s: %s\n", argv0, fname, strerror(errno));
+ free(buf);
return -1;
}
len += (size_t)r;
@@ -225,6 +225,7 @@ hash_file_blake512(int fd, const char *fname, int decode_hex, unsigned char hash
len = libblake_decode_hex(buf, len, buf, &ok);
if (!ok) {
fprintf(stderr, "%s: %s: %s\n", argv0, fname, "invalid hexadecimal input");
+ free(buf);
return -1;
}
}
@@ -232,232 +233,32 @@ hash_file_blake512(int fd, const char *fname, int decode_hex, unsigned char hash
if (req > size)
buf = erealloc(buf, size);
libblake_blake512_digest(&state, buf, len, 0, NULL, hash);
- *hash_lenp = LIBBLAKE_BLAKE512_OUTPUT_SIZE;
free(buf);
return 0;
}
-static int
-parse_fd(const char *name)
-{
- long int num;
- char *end;
- if (!isdigit(*name))
- return -1;
- errno = 0;
- num = strtol(name, &end, 10);
- if (num > INT_MAX || *end || errno)
- return -1;
- return (int)num;
-}
-
-static int
-open_file(const char *path, int *closep)
-{
- int fd = -1;
-
- *closep = 0;
-
- if (!strcmp(path, "-"))
- fd = STDIN_FILENO;
- else if (!strcmp(path, "/dev/stdin"))
- fd = STDIN_FILENO;
- else if (!strcmp(path, "/dev/stdout"))
- fd = STDOUT_FILENO;
- else if (!strcmp(path, "/dev/stderr"))
- fd = STDERR_FILENO;
- else if (!strncmp(path, "/dev/fd/", sizeof("/dev/fd/") - 1))
- fd = parse_fd(&path[sizeof("/dev/fd/") - 1]);
- else if (!strncmp(path, "/proc/self/fd/", sizeof("/proc/self/fd/") - 1))
- fd = parse_fd(&path[sizeof("/proc/self/fd/") - 1]);
-
- if (fd < 0) {
- fd = open(path, O_RDONLY);
- if (fd < 0)
- return -1;
- *closep = 1;
- }
-
- return fd;
-}
-
-static int
-hash_file(const char *path, int length, int decode_hex, unsigned char hash[], size_t *hash_lenp)
+int
+hash_fd(int fd, const char *fname, int decode_hex, unsigned char hash[])
{
- int ret, fd, close_fd;
-
- fd = open_file(path, &close_fd);
- if (fd < 0) {
- fprintf(stderr, "%s: %s: %s\n", argv0, path, strerror(errno));
- return -1;
- }
+ int ret;
if (length == 224)
- ret = hash_file_blake224(fd, path, decode_hex, hash, hash_lenp);
+ ret = hash_fd_blake224(fd, fname, decode_hex, hash);
else if (length == 256)
- ret = hash_file_blake256(fd, path, decode_hex, hash, hash_lenp);
+ ret = hash_fd_blake256(fd, fname, decode_hex, hash);
else if (length == 384)
- ret = hash_file_blake384(fd, path, decode_hex, hash, hash_lenp);
+ ret = hash_fd_blake384(fd, fname, decode_hex, hash);
else if (length == 512)
- ret = hash_file_blake512(fd, path, decode_hex, hash, hash_lenp);
+ ret = hash_fd_blake512(fd, fname, decode_hex, hash);
else
abort();
- if (close_fd)
- close(fd);
return ret;
}
-static int
-hash_and_print(const char *path, int length, int decode_hex, char newline, int output_case)
-{
- unsigned char hash[LIBBLAKE_BLAKE512_OUTPUT_SIZE];
- char hex[LIBBLAKE_BLAKE512_OUTPUT_SIZE * 2 + 1];
- size_t hash_len;
-
- if (hash_file(path, length, decode_hex, hash, &hash_len))
- return -1;
-
- if (output_case < 0) {
- fwrite(hash, 1, hash_len, stdout);
- } else {
- libblake_encode_hex(hash, hash_len, hex, output_case);
- printf("%s %s%c", hex, path, newline);
- }
-
- return 0;
-}
-
-static int
-check_and_print_file(const char *path, int length, int decode_hex, char *expected)
-{
- unsigned char hash[LIBBLAKE_BLAKE512_OUTPUT_SIZE];
- int r, fd, close_fd;
-
- fd = open_file(path, &close_fd);
- if (fd < 0) {
- if (errno != ENOENT)
- fprintf(stderr, "%s: %s: %s\n", argv0, path, strerror(errno));
- missing:
- printf("%s: Missing\n", path);
- return -1;
- }
-
- if (length == 224)
- r = hash_file_blake224(fd, path, decode_hex, hash, &(size_t){0});
- else if (length == 256)
- r = hash_file_blake256(fd, path, decode_hex, hash, &(size_t){0});
- else if (length == 384)
- r = hash_file_blake384(fd, path, decode_hex, hash, &(size_t){0});
- else if (length == 512)
- r = hash_file_blake512(fd, path, decode_hex, hash, &(size_t){0});
- else
- abort();
-
- if (close_fd)
- close(fd);
-
- if (r < 0)
- goto missing;
-
- libblake_decode_hex(expected, (size_t)length / 4, expected, &(int){0});
- if (!memcmp(hash, expected, (size_t)length / 8)) {
- printf("%s: OK\n", path);
- return 0;
- } else {
- printf("%s: Fail\n", path);
- return -1;
- }
-}
-
-static int
-check_and_print(const char *path, int length, int decode_hex, char newline)
-{
- int fd, close_fd, status = 0;
- char *buf = NULL;
- size_t size = 0;
- size_t len = 0;
- ssize_t r;
- size_t i, j, k;
-
- fd = open_file(path, &close_fd);
- if (fd < 0) {
- fprintf(stderr, "%s: %s: %s\n", argv0, path, strerror(errno));
- exit(2);
- }
-
- for (;;) {
- if (len == size)
- buf = erealloc(buf, size += 8 << 10);
- r = read(fd, &buf[len], size - len);
- if (r > 0) {
- len += (size_t)r;
- } else if (!r) {
- break;
- } else if (errno == EINTR) {
- continue;
- } else {
- fprintf(stderr, "%s: %s: %s\n", argv0, path, strerror(errno));
- exit(2);
- }
- }
- buf = erealloc(buf, len + 1);
- buf[len] = '\0';
-
- if (newline) {
- for (i = 0; i < len; i = k + 1) {
- while (isspace(buf[i]))
- i++;
- for (j = i; j - i < (size_t)length / 4; j++)
- if (!isxdigit(buf[j]))
- goto corrupt;
- if (j == len || !isblank(buf[j]))
- goto corrupt;
- buf[j] = '\0';
- j++;
- while (isblank(buf[j]))
- j++;
- if (!buf[j])
- goto corrupt;
- for (k = j; buf[k] && buf[k] != newline;)
- k++;
- buf[k] = '\0';
- status |= check_and_print_file(&buf[j], length, decode_hex, &buf[i]);
- }
- } else {
- for (i = 0; i < len; i = k + 1) {
- for (j = i; j - i < (size_t)length / 4; j++)
- if (!isxdigit(buf[j]))
- goto corrupt;
- if (buf[j + 0] != ' ' || buf[j + 1] != ' ')
- goto corrupt;
- buf[j] = '\0';
- j += 2;
- k = j + strlen(&buf[j]);
- status |= check_and_print_file(&buf[j], length, decode_hex, &buf[i]);
- }
- }
-
- if (close_fd)
- close(fd);
- return status;
-
-corrupt:
- fprintf(stderr, "%s: %s: invalid file content\n", argv0, path);
- exit(2);
-}
-
int
main(int argc, char *argv[])
{
- int flag_check = 0;
- int flag_binary = 0;
- int flag_lower = 0;
- int flag_upper = 0;
- int flag_hex = 0;
- int flag_zero = 0;
- int length;
-
int status = 0;
int output_case;
char newline;
@@ -510,18 +311,18 @@ main(int argc, char *argv[])
newline = flag_zero ? '\0' : '\n';
if (flag_check) {
if (!argc) {
- status |= -check_and_print("-", length, flag_hex, newline);
+ status |= -check_and_print("-", (size_t)length, flag_hex, newline);
} else {
for (; *argv; argv++)
- status |= -check_and_print(*argv, length, flag_hex, newline);
+ status |= -check_and_print(*argv, (size_t)length, flag_hex, newline);
}
} else {
output_case = flag_binary ? -1 : flag_upper;
if (!argc) {
- status |= -hash_and_print("-", length, flag_hex, newline, output_case);
+ status |= -hash_and_print("-", (size_t)length, flag_hex, newline, output_case);
} else {
for (; *argv; argv++)
- status |= -hash_and_print(*argv, length, flag_hex, newline, output_case);
+ status |= -hash_and_print(*argv, (size_t)length, flag_hex, newline, output_case);
}
}
diff --git a/common.c b/common.c
new file mode 100644
index 0000000..c389285
--- /dev/null
+++ b/common.c
@@ -0,0 +1,228 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+void *
+erealloc(void *ptr, size_t n)
+{
+ ptr = realloc(ptr, n);
+ if (!ptr) {
+ fprintf(stderr, "%s: %s\n", argv0, strerror(errno));
+ exit(2);
+ }
+ return ptr;
+}
+
+void *
+emalloc(size_t n)
+{
+ void *ptr = malloc(n);
+ if (!ptr) {
+ fprintf(stderr, "%s: %s\n", argv0, strerror(errno));
+ exit(2);
+ }
+ return ptr;
+}
+
+static int
+parse_fd(const char *name)
+{
+ long int num;
+ char *end;
+ if (!isdigit(*name))
+ return -1;
+ errno = 0;
+ num = strtol(name, &end, 10);
+ if (num > INT_MAX || *end || errno)
+ return -1;
+ return (int)num;
+}
+
+int
+open_file(const char *path, int *closep)
+{
+ int fd = -1;
+
+ *closep = 0;
+
+ if (!strcmp(path, "-"))
+ fd = STDIN_FILENO;
+ else if (!strcmp(path, "/dev/stdin"))
+ fd = STDIN_FILENO;
+ else if (!strcmp(path, "/dev/stdout"))
+ fd = STDOUT_FILENO;
+ else if (!strcmp(path, "/dev/stderr"))
+ fd = STDERR_FILENO;
+ else if (!strncmp(path, "/dev/fd/", sizeof("/dev/fd/") - 1))
+ fd = parse_fd(&path[sizeof("/dev/fd/") - 1]);
+ else if (!strncmp(path, "/proc/self/fd/", sizeof("/proc/self/fd/") - 1))
+ fd = parse_fd(&path[sizeof("/proc/self/fd/") - 1]);
+
+ if (fd < 0) {
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return -1;
+ *closep = 1;
+ }
+
+ return fd;
+}
+
+static int
+check_and_print_file(const char *path, size_t hashlen, int decode_hex, char *expected)
+{
+ unsigned char *hash;
+ int r, fd, close_fd;
+
+ fd = open_file(path, &close_fd);
+ if (fd < 0) {
+ if (errno != ENOENT)
+ fprintf(stderr, "%s: %s: %s\n", argv0, path, strerror(errno));
+ missing:
+ printf("%s: Missing\n", path);
+ return -1;
+ }
+
+ hash = hashlen ? emalloc(hashlen / 8) : NULL;
+ r = hash_fd(fd, path, decode_hex, hash);
+
+ if (close_fd)
+ close(fd);
+
+ if (r < 0) {
+ free(hash);
+ goto missing;
+ }
+
+ libblake_decode_hex(expected, hashlen / 4, expected, &(int){0});
+ if (!memcmp(hash, expected, hashlen / 8)) {
+ free(hash);
+ printf("%s: OK\n", path);
+ return 0;
+ } else {
+ free(hash);
+ printf("%s: Fail\n", path);
+ return -1;
+ }
+}
+
+int
+check_and_print(const char *path, size_t hashlen, int decode_hex, char newline)
+{
+ int fd, close_fd, status = 0;
+ char *buf = NULL;
+ size_t size = 0;
+ size_t len = 0;
+ ssize_t r;
+ size_t i, j, k;
+
+ fd = open_file(path, &close_fd);
+ if (fd < 0) {
+ fprintf(stderr, "%s: %s: %s\n", argv0, path, strerror(errno));
+ exit(2);
+ }
+
+ for (;;) {
+ if (len == size)
+ buf = erealloc(buf, size += 8 << 10);
+ r = read(fd, &buf[len], size - len);
+ if (r > 0) {
+ len += (size_t)r;
+ } else if (!r) {
+ break;
+ } else if (errno == EINTR) {
+ continue;
+ } else {
+ fprintf(stderr, "%s: %s: %s\n", argv0, path, strerror(errno));
+ exit(2);
+ }
+ }
+ buf = erealloc(buf, len + 1);
+ buf[len] = '\0';
+
+ if (newline) {
+ for (i = 0; i < len; i = k + 1) {
+ while (isspace(buf[i]))
+ i++;
+ for (j = i; j - i < hashlen / 4; j++)
+ if (!isxdigit(buf[j]))
+ goto corrupt;
+ if (j == len || !isblank(buf[j]))
+ goto corrupt;
+ buf[j] = '\0';
+ j++;
+ while (isblank(buf[j]))
+ j++;
+ if (!buf[j])
+ goto corrupt;
+ for (k = j; buf[k] && buf[k] != newline;)
+ k++;
+ buf[k] = '\0';
+ status |= check_and_print_file(&buf[j], hashlen, decode_hex, &buf[i]);
+ }
+ } else {
+ for (i = 0; i < len; i = k + 1) {
+ for (j = i; j - i < hashlen / 4; j++)
+ if (!isxdigit(buf[j]))
+ goto corrupt;
+ if (buf[j + 0] != ' ' || buf[j + 1] != ' ')
+ goto corrupt;
+ buf[j] = '\0';
+ j += 2;
+ k = j + strlen(&buf[j]);
+ status |= check_and_print_file(&buf[j], hashlen, decode_hex, &buf[i]);
+ }
+ }
+
+ if (close_fd)
+ close(fd);
+ return status;
+
+corrupt:
+ fprintf(stderr, "%s: %s: invalid file content\n", argv0, path);
+ exit(2);
+}
+
+static int
+hash_file(const char *path, int decode_hex, unsigned char hash[])
+{
+ int ret, fd, close_fd;
+
+ fd = open_file(path, &close_fd);
+ if (fd < 0) {
+ fprintf(stderr, "%s: %s: %s\n", argv0, path, strerror(errno));
+ return -1;
+ }
+
+ ret = hash_fd(fd, path, decode_hex, hash);
+
+ if (close_fd)
+ close(fd);
+ return ret;
+}
+
+int
+hash_and_print(const char *path, size_t hashlen, int decode_hex, char newline, int output_case)
+{
+ unsigned char *hash;
+ char *hex;
+
+ hash = hashlen ? emalloc(hashlen / 8) : 0;
+ hex = emalloc(hashlen / 4 + 1);
+
+ if (hash_file(path, decode_hex, hash)) {
+ free(hash);
+ free(hex);
+ return -1;
+ }
+
+ if (output_case < 0) {
+ fwrite(hash, 1, hashlen / 8, stdout);
+ } else {
+ libblake_encode_hex(hash, hashlen / 8, hex, output_case);
+ printf("%s %s%c", hex, path, newline);
+ }
+
+ free(hash);
+ free(hex);
+ return 0;
+}
diff --git a/common.h b/common.h
index b0cbd63..96998a8 100644
--- a/common.h
+++ b/common.h
@@ -12,3 +12,13 @@
#include <libblake.h>
#include "arg.h"
+
+/* common.c */
+void *erealloc(void *ptr, size_t n);
+void *emalloc(size_t n);
+int open_file(const char *path, int *closep);
+int check_and_print(const char *path, size_t hashlen, int decode_hex, char newline);
+int hash_and_print(const char *path, size_t hashlen, int decode_hex, char newline, int output_case);
+
+/* *sum.c */
+int hash_fd(int fd, const char *fname, int decode_hex, unsigned char hash[]);