cksum now accepts the --base64 (-b) option to print base64-encoded
checksums. It also accepts/checks such checksums.
+ cksum now accepts the --raw option to output a raw binary checksum.
+ No file name or other information is output in this mode.
+
factor now accepts the --exponents (-h) option to print factors
in the form p^e, rather than repeating the prime p, e times.
@opindex --debug
Output extra information to stderr, like the checksum implementation being used.
+@item --raw
+@opindex --raw
+@cindex raw binary checksum
+Print only the unencoded raw binary digest for a single input.
+Do not output the file name or anything else.
+Use network byte order (big endian) where applicable:
+for @samp{bsd}, @samp{crc}, and @samp{sysv}.
+This option works only with a single input.
+Unlike other output formats, @command{cksum} provides no way to
+@option{--check} a @option{--raw} checksum.
+
@item --untagged
@opindex --untagged
Output using the original Coreutils format used by the other
If ARGS is true, also print the FILE name. */
void
-output_crc (char const *file, int binary_file, void const *digest,
+output_crc (char const *file, int binary_file, void const *digest, bool raw,
bool tagged, unsigned char delim, bool args, uintmax_t length)
{
+ if (raw)
+ {
+ /* Output in network byte order (big endian). */
+ uint32_t out_int = SWAP (*(uint32_t *)digest);
+ fwrite (&out_int, 1, 32/8, stdout);
+ return;
+ }
+
char length_buf[INT_BUFSIZE_BOUND (uintmax_t)];
printf ("%u %s", *(unsigned int *)digest, umaxtostr (length, length_buf));
if (args)
crc_sum_stream (FILE *stream, void *resstream, uintmax_t *length);
extern void
-output_crc (char const *file, int binary_file, void const *digest,
+output_crc (char const *file, int binary_file, void const *digest, bool raw,
bool tagged, unsigned char delim, bool args, uintmax_t length)
_GL_ATTRIBUTE_NONNULL ((3));
#if !HASH_ALGO_SUM
static void
output_file (char const *file, int binary_file, void const *digest,
- bool tagged, unsigned char delim, bool args,
+ bool raw, bool tagged, unsigned char delim, bool args,
uintmax_t length);
#endif
static bool base64_digest = false;
#endif
+/* If true, print binary digests, not hex. */
+static bool raw_digest = false;
+
#if HASH_ALGO_BLAKE2 || HASH_ALGO_CKSUM
# define BLAKE2B_MAX_LEN BLAKE2B_OUTBYTES
static uintmax_t digest_length;
#endif /* HASH_ALGO_BLAKE2 */
-typedef void (*digest_output_fn)(char const *, int, void const *,
+typedef void (*digest_output_fn)(char const *, int, void const *, bool,
bool, unsigned char, bool, uintmax_t);
#if HASH_ALGO_SUM
enum Algorithm
TAG_OPTION,
UNTAG_OPTION,
DEBUG_PROGRAM_OPTION,
+ RAW_OPTION,
};
static struct option const long_options[] =
{ "algorithm", required_argument, NULL, 'a'},
{ "base64", no_argument, NULL, 'b' },
{ "debug", no_argument, NULL, DEBUG_PROGRAM_OPTION},
+ { "raw", no_argument, NULL, RAW_OPTION},
{ "untagged", no_argument, NULL, UNTAG_OPTION },
# else
{ "binary", no_argument, NULL, 'b' },
"), stdout);
# endif
# if HASH_ALGO_CKSUM
+ fputs (_("\
+ --raw emit a raw binary digest, not hexadecimal\
+\n\
+"), stdout);
fputs (_("\
--tag create a BSD-style checksum (the default)\n\
"), stdout);
#if !HASH_ALGO_SUM
static void
output_file (char const *file, int binary_file, void const *digest,
- bool tagged, unsigned char delim, MAYBE_UNUSED bool args,
+ bool raw, bool tagged, unsigned char delim, MAYBE_UNUSED bool args,
MAYBE_UNUSED uintmax_t length)
{
+# if HASH_ALGO_CKSUM
+ if (raw)
+ {
+ fwrite (digest, 1, digest_length / 8, stdout);
+ return;
+ }
+# endif
+
unsigned char const *bin_buffer = digest;
/* Output a leading backslash if the file name contains problematic chars.
case 'b':
base64_digest = true;
break;
+ case RAW_OPTION:
+ raw_digest = true;
+ break;
case UNTAG_OPTION:
prefix_tag = false;
break;
break;
}
+ if (base64_digest && raw_digest)
+ {
+ error (0, 0, _("--base64 and --raw are mutually exclusive"));
+ usage (EXIT_FAILURE);
+ }
#endif
if (prefix_tag && !binary)
char **operand_lim = argv + argc;
if (optind == argc)
*operand_lim++ = bad_cast ("-");
+ else if (1 < argc - optind && raw_digest)
+ {
+ die (EXIT_FAILURE, 0,
+ _("the --raw option is not supported with multiple files"));
+ }
for (char **operandp = argv + optind; operandp < operand_lim; operandp++)
{
ok = false;
else
{
- DIGEST_OUT (file, binary_file, bin_buffer, prefix_tag,
+ DIGEST_OUT (file, binary_file, bin_buffer, raw_digest, prefix_tag,
digest_delim, optind != argc, length);
}
}
#include "human.h"
#include "sum.h"
+#include <byteswap.h>
+#ifdef WORDS_BIGENDIAN
+# define SWAP(n) (n)
+#else
+# define SWAP(n) bswap_16 (n)
+#endif
+
/* Calculate the checksum and the size in bytes of stream STREAM.
Return -1 on error, 0 on success. */
void
output_bsd (char const *file, int binary_file, void const *digest,
- bool tagged, unsigned char delim, bool args,
+ bool raw, bool tagged, unsigned char delim, bool args,
uintmax_t length)
{
+ if (raw)
+ {
+ /* Output in network byte order (big endian). */
+ uint16_t out_int = SWAP (*(uint16_t *)digest);
+ fwrite (&out_int, 1, 16/8, stdout);
+ return;
+ }
char hbuf[LONGEST_HUMAN_READABLE + 1];
printf ("%05d %5s", *(int *)digest,
void
output_sysv (char const *file, int binary_file, void const *digest,
- bool tagged, unsigned char delim, bool args,
+ bool raw, bool tagged, unsigned char delim, bool args,
uintmax_t length)
{
+ if (raw)
+ {
+ /* Output in network byte order (big endian). */
+ uint16_t out_int = SWAP (*(uint16_t *)digest);
+ fwrite (&out_int, 1, 16/8, stdout);
+ return;
+ }
char hbuf[LONGEST_HUMAN_READABLE + 1];
printf ("%d %s", *(int *)digest,
extern void
output_bsd (char const *file, int binary_file, void const *digest,
- bool tagged, unsigned char delim, bool args,
+ bool raw, bool tagged, unsigned char delim, bool args,
uintmax_t length);
extern void
output_sysv (char const *file, int binary_file, void const *digest,
- bool tagged, unsigned char delim, bool args,
+ bool raw, bool tagged, unsigned char delim, bool args,
uintmax_t length);
tests/misc/cksum-a.sh \
tests/misc/cksum-c.sh \
tests/misc/cksum-base64.pl \
+ tests/misc/cksum-raw.sh \
tests/misc/comm.pl \
tests/misc/csplit.sh \
tests/misc/csplit-1000.sh \
--- /dev/null
+#!/bin/sh
+# Validate cksum --raw operation
+
+# Copyright (C) 2023 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ cksum date od
+
+cat > digest_types <<\EOF || framework_failure_
+bsd u2
+sysv u2
+crc u4
+md5 x1
+sha1 x1
+sha224 x1
+sha256 x1
+sha384 x1
+sha512 x1
+blake2b x1
+sm3 x1
+EOF
+
+date > file.in || framework_failure_
+
+while read algo type; do
+ # Binary converted back to text
+ cksum --raw --algorithm $algo file.in > digest.bin || fail=1
+ d='digest.bin.txt'
+ od --endian=big -An -w1024 -t$type < digest.bin | tr -d ' ' \
+ > "$d" || framework_failure_
+ # Pad the bsd checksum with leading 0's, if needed.
+ case $algo in bsd) n=$(cat "$d"); printf '%05d\n' "$n" > "$d" ;; esac
+
+ # Standard text output
+ cksum --untagged --algorithm $algo < file.in | cut -d ' ' -f1 \
+ > digest.txt || fail=1
+
+ compare digest.txt "$d" || fail=1
+done < digest_types
+
+# Ensure --base64 and --raw not used together
+returns_ 1 cksum --base64 --raw </dev/null || fail=1
+
+# Ensure --raw not supported with multiple files
+returns_ 1 cksum --raw /dev/null /dev/null || fail=1
+
+Exit $fail