kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit b47f65e8fc00c584505e9490181138891e1a9059
parent 19bc7463d0bd485b162826f043b722cad87b1450
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Tue,  2 Jun 2026 17:39:17 -0700

driver: add standard-named aliases for hash and compress

Expose the hash and compress tools under the conventional command names so
they drop into existing toolchains:

  hash     -> sha256sum, b2sum, crc32   (algorithm pinned, -a rejected)
  compress -> gzip, gunzip, lz4, lz4c   (container + direction pinned,
                                         -z rejected, -d flips direction)

Each alias is a thin wrapper over a shared persona-driven core. sha256sum is
byte-for-byte compatible with coreutils; kit's b2sum is BLAKE2b-256 (GNU
defaults to 512, so digests differ in width). The compress aliases accept the
common gzip/lz4 flags (-c/-k/-f, levels, ...) as no-ops but always stream to
stdout/-o rather than rewriting the input in place. cksum is intentionally
not provided (different CRC variant + decimal output).

The aliases are tagged BYTEUTIL, so `kit install` lays them down by default
alongside xxd/cmp. Docs and tools/install smoke tests updated.

Diffstat:
MREADME.md | 3+++
Mdoc/DRIVER.md | 2++
Mdriver/cmd/compress.c | 124++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Mdriver/cmd/hash.c | 92++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Mdriver/cmd/install.c | 6+++---
Mdriver/driver.h | 7+++++++
Mdriver/main.c | 14++++++++++++++
Mtest/driver/run.sh | 2+-
Mtest/tools/run.sh | 30++++++++++++++++++++++++++++++
9 files changed, 245 insertions(+), 35 deletions(-)

diff --git a/README.md b/README.md @@ -27,6 +27,9 @@ It features: addr2line, strings - Standalone gzip and LZ4-frame compression (`compress`), interoperable with stock `gzip`/`lz4` +- Content hashing (`hash`: SHA-256, BLAKE2b-256, CRC-32) +- Drop-in standard names for the above: `sha256sum`, `b2sum`, `crc32`, `gzip`, + `gunzip`, `lz4`, `lz4c` - A single multi-call binary, with an `install` command that drops per-tool symlinks (hard links on Windows) into a directory for drop-in toolchain use - Debug info generation and consumption (DWARF) diff --git a/doc/DRIVER.md b/doc/DRIVER.md @@ -96,7 +96,9 @@ tool reaches into compiler internals. | `xxd` | Hex dump *any* file (format-agnostic, unlike `objdump -s`); reverse a dump to binary (`-r`), plain (`-p`), C array (`-i`). | | `cmp` | Compare two files byte by byte; GNU/BSD-compatible messages and 0/1/2 exit codes. | | `hash` | SHA-256, BLAKE2b-256, or CRC-32 (`-a`) of files or stdin; coreutils-style output. Backed by the public `<kit/hash.h>`. | +| `sha256sum` / `b2sum` / `crc32` | `hash` under standard names, each pinning its algorithm (`-a` rejected). `sha256sum` is byte-compatible with coreutils; kit's `b2sum` is BLAKE2b-**256** (GNU defaults to 512). | | `compress` | Compress/decompress a stream with gzip (`.gz`, default) or the LZ4 frame format (`.lz4`); `-d` decompresses (format auto-detected from magic). Output interoperates with stock `gzip`/`lz4`. Backed by the public `<kit/compress.h>`. | +| `gzip` / `gunzip` / `lz4` / `lz4c` | `compress` under standard names: a pinned container + default direction. `-d` flips direction, `-z` is rejected, and the common gzip/lz4 flags (`-c`/`-k`/`-f`, `-1..-9`, …) are accepted as no-ops; output always streams to stdout/`-o` (no in-place rewrite). | | `disas` | Disassemble a raw, headerless byte buffer (file/stdin/inline `-x` hex) for a `-target` arch. | | `mc` | Assemble one instruction and show its encoding (llvm-mc style); lists any relocations. | | `run` | JIT-compile inputs and call the entry symbol in-process. | diff --git a/driver/cmd/compress.c b/driver/cmd/compress.c @@ -11,13 +11,41 @@ * interoperable containers: gzip (`.gz`, default) or the LZ4 frame format * (`.lz4`). Reads a FILE operand or stdin, writes to `-o OUT` or stdout. On * decompress the format is auto-detected from the input's magic bytes unless - * `-z` forces it. Drives the public kit/compress.h API. */ + * `-z` forces it. Drives the public kit/compress.h API. + * + * The same core backs the standard-named aliases, each pinning a container and + * a default direction so it drops in for the matching command: + * gzip -> compress, gzip gunzip -> decompress, gzip + * lz4 -> compress, LZ4 frame lz4c -> compress, LZ4 frame (legacy name) + * Under an alias -z is rejected (the container is fixed), the common + * gzip/lz4 flags (-c/-k/-f, levels, ...) are accepted, and -d still flips the + * direction. kit always streams to stdout/`-o` and never rewrites the input in + * place, so the in-place file flags are deliberately not emulated. */ #define COMPRESS_TOOL "compress" +/* Invocation personality. The generic `compress` leaves format and direction + * to flags; the aliases pin a container and a starting direction. */ +typedef struct CompressPersona { + const char* name; /* tool name for diagnostics: compress/gzip/... */ + KitCompressFormat format; /* default (and, when locked, the only) container */ + int locked_format; /* alias pins the container: -z is rejected, no + * decompress auto-detection */ + int default_decompress; /* alias starts in decompress mode (gunzip) */ + int compat; /* accept gzip/lz4-style compatibility flags */ +} CompressPersona; + +static const CompressPersona CZ_GENERIC = {"compress", KIT_COMPRESS_GZIP, 0, 0, + 0}; +static const CompressPersona CZ_GZIP = {"gzip", KIT_COMPRESS_GZIP, 1, 0, 1}; +static const CompressPersona CZ_GUNZIP = {"gunzip", KIT_COMPRESS_GZIP, 1, 1, 1}; +static const CompressPersona CZ_LZ4 = {"lz4", KIT_COMPRESS_LZ4_FRAME, 1, 0, 1}; +static const CompressPersona CZ_LZ4C = {"lz4c", KIT_COMPRESS_LZ4_FRAME, 1, 0, + 1}; + typedef struct CompressOpts { int decompress; /* -d */ - int have_format; /* whether -z/--format was given */ + int have_format; /* whether -z/--format (or a pinned container) was given */ KitCompressFormat format; int seen_input; /* a FILE or `-` operand was seen */ const char* in; /* input path, or NULL = stdin */ @@ -36,6 +64,31 @@ static int compress_parse_format(const char* s, KitCompressFormat* out) { return 1; } +/* gzip/lz4-style flags accepted (as no-ops) under an alias so the tool works + * as a drop-in. kit always streams stdin/-o to stdout and never mutates the + * input in place, so -c/--stdout, -k/--keep and -f/--force have nothing to do; + * the codecs expose no level, so -1..-9 / --fast[=N] / --best are ignored too. + * Direction (-d) and the long decompress spellings are handled by the caller. + * Returns 1 if `a` is one of these accepted no-ops. */ +static int compress_compat_noop(const char* a) { + if (driver_streq(a, "-c") || driver_streq(a, "--stdout") || + driver_streq(a, "--to-stdout")) + return 1; + if (driver_streq(a, "-k") || driver_streq(a, "--keep")) return 1; + if (driver_streq(a, "-f") || driver_streq(a, "--force")) return 1; + if (driver_streq(a, "-n") || driver_streq(a, "--no-name")) return 1; + if (driver_streq(a, "-q") || driver_streq(a, "--quiet")) return 1; + if (driver_streq(a, "--best") || driver_streq(a, "--fast")) return 1; + if (driver_strneq(a, "--fast=", 7)) return 1; + /* -N / -NN compression level (gzip 1-9, lz4 up to 12): a dash then digits. */ + if (a[0] == '-' && a[1] >= '1' && a[1] <= '9') { + size_t k = 2; + while (a[k] >= '0' && a[k] <= '9') ++k; + if (a[k] == '\0') return 1; + } + return 0; +} + void driver_help_compress(void) { driver_printf( "%.*s", @@ -60,11 +113,21 @@ void driver_help_compress(void) { " -o OUT write output to OUT (default: stdout)\n" " -h, --help show this help\n" "\n" + "ALIASES\n" + " Invoked as gzip / lz4 (or lz4c) compresses to that container; as\n" + " gunzip decompresses gzip. -d flips direction; -z is rejected " + "(the\n" + " container is fixed). Common gzip/lz4 flags (-c/--stdout, -k, -f,\n" + " -1..-9, --fast, --best) are accepted; output still goes to " + "stdout\n" + " or -o, never rewriting the input in place.\n" + "\n" "EXIT CODES\n" " 0 success 1 I/O or codec error 2 bad usage\n"))); } -int driver_compress(int argc, char** argv) { +static int compress_main(int argc, char** argv, + const CompressPersona* persona) { DriverEnv env; KitContext ctx; CompressOpts o; @@ -83,19 +146,31 @@ int driver_compress(int argc, char** argv) { } memset(&o, 0, sizeof o); - o.format = KIT_COMPRESS_GZIP; + o.format = persona->format; + /* A pinned container both fixes the format and disables decompress + * auto-detection (gunzip only reads gzip, lz4 only reads LZ4). */ + o.have_format = persona->locked_format; + o.decompress = persona->default_decompress; driver_env_init(&env); ctx = driver_env_to_context(&env); for (i = 1; i < argc; ++i) { const char* a = argv[i]; - if (driver_streq(a, "-d")) { + if (driver_streq(a, "-d") || + (persona->compat && (driver_streq(a, "--decompress") || + driver_streq(a, "--uncompress")))) { o.decompress = 1; continue; } if (driver_streq(a, "-z") || driver_streq(a, "--format")) { + if (persona->locked_format) { + driver_errf(persona->name, "-z is not accepted; %s always uses %s", + persona->name, + persona->format == KIT_COMPRESS_GZIP ? "gzip" : "lz4"); + goto done; + } if (i + 1 >= argc || compress_parse_format(argv[++i], &o.format) != 0) { - driver_errf(COMPRESS_TOOL, "-z requires gzip or lz4"); + driver_errf(persona->name, "-z requires gzip or lz4"); goto done; } o.have_format = 1; @@ -103,7 +178,7 @@ int driver_compress(int argc, char** argv) { } if (driver_streq(a, "-o")) { if (i + 1 >= argc) { - driver_errf(COMPRESS_TOOL, "-o requires a file path"); + driver_errf(persona->name, "-o requires a file path"); goto done; } o.out = argv[++i]; @@ -111,18 +186,19 @@ int driver_compress(int argc, char** argv) { } if (driver_streq(a, "-")) { /* explicit stdin */ if (o.seen_input) { - driver_errf(COMPRESS_TOOL, "only one input may be given"); + driver_errf(persona->name, "only one input may be given"); goto done; } o.seen_input = 1; continue; } + if (persona->compat && compress_compat_noop(a)) continue; if (a[0] == '-' && a[1] != '\0') { - driver_errf(COMPRESS_TOOL, "unknown option: %s", a); + driver_errf(persona->name, "unknown option: %s", a); goto done; } if (o.seen_input) { - driver_errf(COMPRESS_TOOL, "only one input may be given"); + driver_errf(persona->name, "only one input may be given"); goto done; } o.seen_input = 1; @@ -132,7 +208,7 @@ int driver_compress(int argc, char** argv) { /* Load the whole input. */ if (o.in) { KitSlice input; - if (driver_load_bytes(&env.file_io, COMPRESS_TOOL, o.in, &ld, &input) != + if (driver_load_bytes(&env.file_io, persona->name, o.in, &ld, &input) != 0) { rc = 1; goto done; @@ -142,7 +218,7 @@ int driver_compress(int argc, char** argv) { len = input.len; } else { if (!driver_read_stdin(&env, &sbuf, &sbuf_len)) { - driver_errf(COMPRESS_TOOL, "failed to read stdin"); + driver_errf(persona->name, "failed to read stdin"); rc = 1; goto done; } @@ -155,7 +231,7 @@ int driver_compress(int argc, char** argv) { fmt = o.format; if (o.decompress && !o.have_format) { if (kit_compress_detect(data, len, &fmt) != KIT_OK) { - driver_errf(COMPRESS_TOOL, "cannot detect input format; use -z gzip|lz4"); + driver_errf(persona->name, "cannot detect input format; use -z gzip|lz4"); rc = 1; goto done; } @@ -164,7 +240,7 @@ int driver_compress(int argc, char** argv) { /* Open the output. */ if (o.out) { if (ctx.file_io->open_writer(ctx.file_io->user, o.out, &w) != KIT_OK) { - driver_errf(COMPRESS_TOOL, "failed to open output: %s", o.out); + driver_errf(persona->name, "failed to open output: %s", o.out); rc = 1; goto done; } @@ -189,3 +265,23 @@ done: driver_env_fini(&env); return rc; } + +int driver_compress(int argc, char** argv) { + return compress_main(argc, argv, &CZ_GENERIC); +} + +int driver_gzip(int argc, char** argv) { + return compress_main(argc, argv, &CZ_GZIP); +} + +int driver_gunzip(int argc, char** argv) { + return compress_main(argc, argv, &CZ_GUNZIP); +} + +int driver_lz4(int argc, char** argv) { + return compress_main(argc, argv, &CZ_LZ4); +} + +int driver_lz4c(int argc, char** argv) { + return compress_main(argc, argv, &CZ_LZ4C); +} diff --git a/driver/cmd/hash.c b/driver/cmd/hash.c @@ -11,16 +11,45 @@ * input. Output is coreutils-style ("<hex> <name>"), so it diffs cleanly * against sha256sum / b2sum / cksum -a output. With no FILE, or with `-`, * reads stdin. Drives the streaming kit_hasher_* API (the one-shot - * kit_hash stays for library callers). */ - -#define HASH_TOOL "hash" + * kit_hash stays for library callers). + * + * The same core also backs the standard-named aliases, each of which pins the + * algorithm so the tool is a drop-in for the matching command: + * sha256sum -> SHA-256 b2sum -> BLAKE2b-256 crc32 -> CRC-32 + * (Note: GNU b2sum defaults to BLAKE2b-512; kit's BLAKE2b is 256-bit, so the + * digests differ in width.) The aliases reject -a, since their algorithm is + * fixed; the generic `hash` tool keeps -a for selecting any of the three. */ static const char HASH_HEX[] = "0123456789abcdef"; +/* Invocation personality: which algorithm, and whether the name pins it. */ +typedef struct HashPersona { + const char* name; /* tool name for diagnostics: hash/sha256sum/... */ + KitHashAlgo algo; /* default (and, when locked, the only) algorithm */ + int locked; /* alias pins the algorithm: -a is rejected */ +} HashPersona; + +static const HashPersona HASH_GENERIC = {"hash", KIT_HASH_SHA256, 0}; +static const HashPersona HASH_SHA256SUM = {"sha256sum", KIT_HASH_SHA256, 1}; +static const HashPersona HASH_B2SUM = {"b2sum", KIT_HASH_BLAKE2B, 1}; +static const HashPersona HASH_CRC32 = {"crc32", KIT_HASH_CRC32, 1}; + typedef struct HashOpts { KitHashAlgo algo; } HashOpts; +static const char* hash_algo_name(KitHashAlgo algo) { + switch (algo) { + case KIT_HASH_SHA256: + return "sha256"; + case KIT_HASH_BLAKE2B: + return "blake2b"; + case KIT_HASH_CRC32: + return "crc32"; + } + return "?"; +} + static int hash_parse_algo(const char* s, KitHashAlgo* out) { if (driver_streq(s, "sha256")) { *out = KIT_HASH_SHA256; @@ -54,21 +83,27 @@ void driver_help_hash(void) { " -a ALGO sha256 (default) | blake2b | crc32\n" " -h, --help show this help\n" "\n" + "ALIASES\n" + " Invoked as sha256sum, b2sum, or crc32 the algorithm is fixed to\n" + " SHA-256, BLAKE2b-256, or CRC-32 respectively and -a is rejected.\n" + " (GNU b2sum defaults to BLAKE2b-512; this BLAKE2b is 256-bit.)\n" + "\n" "EXIT CODES\n" " 0 success 1 I/O error 2 bad usage\n"))); } /* Hash data[0..len) with opts->algo and print "<hex> <name>". Returns 0 on - * success, 1 on failure (error already reported). */ + * success, 1 on failure (error already reported under `tool`). */ static int hash_one(const KitContext* ctx, const HashOpts* opts, - const uint8_t* data, size_t len, const char* name) { + const char* tool, const uint8_t* data, size_t len, + const char* name) { KitHasher* h = NULL; uint8_t digest[KIT_HASH_MAX_LEN]; char hex[KIT_HASH_MAX_LEN * 2 + 1]; size_t dlen = 0, i; if (kit_hasher_new(ctx, opts->algo, &h) != KIT_OK) { - driver_errf(HASH_TOOL, "failed to start hasher"); + driver_errf(tool, "failed to start hasher"); return 1; } kit_hasher_update(h, data, len); @@ -84,7 +119,7 @@ static int hash_one(const KitContext* ctx, const HashOpts* opts, return 0; } -int driver_hash(int argc, char** argv) { +static int hash_main(int argc, char** argv, const HashPersona* persona) { DriverEnv env; KitContext ctx; HashOpts opts; @@ -96,7 +131,7 @@ int driver_hash(int argc, char** argv) { } memset(&opts, 0, sizeof opts); - opts.algo = KIT_HASH_SHA256; + opts.algo = persona->algo; driver_env_init(&env); ctx = driver_env_to_context(&env); @@ -104,8 +139,14 @@ int driver_hash(int argc, char** argv) { for (i = 1; i < argc; ++i) { const char* a = argv[i]; if (driver_streq(a, "-a")) { + if (persona->locked) { + driver_errf(persona->name, "-a is not accepted; %s always uses %s", + persona->name, hash_algo_name(persona->algo)); + rc = 2; + goto done; + } if (i + 1 >= argc || hash_parse_algo(argv[++i], &opts.algo) != 0) { - driver_errf(HASH_TOOL, "-a requires sha256, blake2b, or crc32"); + driver_errf(persona->name, "-a requires sha256, blake2b, or crc32"); rc = 2; goto done; } @@ -116,7 +157,7 @@ int driver_hash(int argc, char** argv) { continue; } if (a[0] == '-' && a[1] != '\0') { - driver_errf(HASH_TOOL, "unknown option: %s", a); + driver_errf(persona->name, "unknown option: %s", a); rc = 2; goto done; } @@ -128,11 +169,11 @@ int driver_hash(int argc, char** argv) { uint8_t* buf = NULL; size_t n = 0; if (!driver_read_stdin(&env, &buf, &n)) { - driver_errf(HASH_TOOL, "failed to read stdin"); + driver_errf(persona->name, "failed to read stdin"); rc = 1; goto done; } - rc = hash_one(&ctx, &opts, buf, n, "-"); + rc = hash_one(&ctx, &opts, persona->name, buf, n, "-"); driver_free(&env, buf, n); goto done; } @@ -142,29 +183,30 @@ int driver_hash(int argc, char** argv) { for (i = 1; i < argc; ++i) { const char* a = argv[i]; if (driver_streq(a, "-a")) { - ++i; /* skip its value */ + ++i; /* skip its value (only reachable for the generic, unlocked tool) */ continue; } if (driver_streq(a, "-")) { uint8_t* buf = NULL; size_t n = 0; if (!driver_read_stdin(&env, &buf, &n)) { - driver_errf(HASH_TOOL, "failed to read stdin"); + driver_errf(persona->name, "failed to read stdin"); rc = 1; continue; } - if (hash_one(&ctx, &opts, buf, n, "-") != 0) rc = 1; + if (hash_one(&ctx, &opts, persona->name, buf, n, "-") != 0) rc = 1; driver_free(&env, buf, n); continue; } { DriverLoad ld = {0}; KitSlice input; - if (driver_load_bytes(&env.file_io, HASH_TOOL, a, &ld, &input) != 0) { + if (driver_load_bytes(&env.file_io, persona->name, a, &ld, &input) != 0) { rc = 1; continue; } - if (hash_one(&ctx, &opts, input.data, input.len, a) != 0) rc = 1; + if (hash_one(&ctx, &opts, persona->name, input.data, input.len, a) != 0) + rc = 1; driver_release_bytes(&env.file_io, &ld); } } @@ -173,3 +215,19 @@ done: driver_env_fini(&env); return rc; } + +int driver_hash(int argc, char** argv) { + return hash_main(argc, argv, &HASH_GENERIC); +} + +int driver_sha256sum(int argc, char** argv) { + return hash_main(argc, argv, &HASH_SHA256SUM); +} + +int driver_b2sum(int argc, char** argv) { + return hash_main(argc, argv, &HASH_B2SUM); +} + +int driver_crc32(int argc, char** argv) { + return hash_main(argc, argv, &HASH_CRC32); +} diff --git a/driver/cmd/install.c b/driver/cmd/install.c @@ -37,9 +37,9 @@ void driver_help_install(void) { "\n" " With no TOOL given, installs the default set: the binutils/compiler\n" " toolchain (cc cpp as ld ar ranlib strip objcopy objdump nm size\n" - " addr2line strings) plus the standard-named byte utilities (xxd cmp).\n" - " Use --all for every tool, or name specific TOOLs to install just\n" - " those.\n" + " addr2line strings) plus the standard-named byte utilities (xxd cmp\n" + " sha256sum b2sum crc32 gzip gunzip lz4 lz4c). Use --all for every\n" + " tool, or name specific TOOLs to install just those.\n" "\n" "OPTIONS\n" " -s, --symlink create symlinks (default except on Windows)\n" diff --git a/driver/driver.h b/driver/driver.h @@ -59,7 +59,14 @@ int driver_pkg(int argc, char** argv); int driver_xxd(int argc, char** argv); int driver_cmp(int argc, char** argv); int driver_hash(int argc, char** argv); +int driver_sha256sum(int argc, char** argv); +int driver_b2sum(int argc, char** argv); +int driver_crc32(int argc, char** argv); int driver_compress(int argc, char** argv); +int driver_gzip(int argc, char** argv); +int driver_gunzip(int argc, char** argv); +int driver_lz4(int argc, char** argv); +int driver_lz4c(int argc, char** argv); int driver_disas(int argc, char** argv); int driver_mc(int argc, char** argv); diff --git a/driver/main.c b/driver/main.c @@ -131,10 +131,24 @@ static const DriverToolDesc driver_tools[] = { #if KIT_TOOL_HASH_ENABLED {"hash", driver_hash, driver_help_hash, "Hash files with SHA-256, BLAKE2b, or CRC-32", DRIVER_GROUP_OTHER}, + {"sha256sum", driver_sha256sum, driver_help_hash, + "SHA-256 of files or stdin (sha256sum-compatible)", DRIVER_GROUP_BYTEUTIL}, + {"b2sum", driver_b2sum, driver_help_hash, + "BLAKE2b-256 of files or stdin (b2sum-style)", DRIVER_GROUP_BYTEUTIL}, + {"crc32", driver_crc32, driver_help_hash, "CRC-32 of files or stdin", + DRIVER_GROUP_BYTEUTIL}, #endif #if KIT_TOOL_COMPRESS_ENABLED {"compress", driver_compress, driver_help_compress, "Compress or decompress data (gzip, lz4 frame)", DRIVER_GROUP_OTHER}, + {"gzip", driver_gzip, driver_help_compress, + "Compress to gzip (.gz); -d to decompress", DRIVER_GROUP_BYTEUTIL}, + {"gunzip", driver_gunzip, driver_help_compress, + "Decompress gzip (.gz) streams", DRIVER_GROUP_BYTEUTIL}, + {"lz4", driver_lz4, driver_help_compress, + "Compress to LZ4 frame (.lz4); -d to decompress", DRIVER_GROUP_BYTEUTIL}, + {"lz4c", driver_lz4c, driver_help_compress, + "Compress to LZ4 frame (.lz4) (lz4 alias)", DRIVER_GROUP_BYTEUTIL}, #endif #if KIT_TOOL_DISAS_ENABLED {"disas", driver_disas, driver_help_disas, diff --git a/test/driver/run.sh b/test/driver/run.sh @@ -964,7 +964,7 @@ fi inst_dir="$work/inst" run_ok "install-default" "$KIT" install "$inst_dir" for t in cc cpp as ld ar ranlib strip objcopy objdump nm size addr2line \ - strings xxd cmp; do + strings xxd cmp sha256sum b2sum crc32 gzip gunzip lz4 lz4c; do assert_file_exists "install-has-$t" "$inst_dir/$t" done is_executable "install-cc-executable" "$inst_dir/cc" diff --git a/test/tools/run.sh b/test/tools/run.sh @@ -59,6 +59,18 @@ printf 'abc' | "$KIT" hash -a sha256 > "$work/sha.out" 2>&1 contains hash-sha256 "$work/sha.out" \ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" +# Standard-named aliases pin the algorithm and match `hash -a` exactly. +printf 'abc' | "$KIT" sha256sum > "$work/sha256sum.out" 2>&1 +contains alias-sha256sum "$work/sha256sum.out" \ + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad -" +printf 'abc' | "$KIT" b2sum > "$work/b2sum.out" 2>&1 +printf 'abc' | "$KIT" hash -a blake2b > "$work/b2ref.out" 2>&1 +same_file alias-b2sum-matches-hash "$work/b2sum.out" "$work/b2ref.out" +"$KIT" crc32 "$work/crc.in" > "$work/crc32.out" 2>&1 +contains alias-crc32 "$work/crc32.out" "cbf43926" +# A pinned alias rejects -a (its algorithm is fixed). +run_fail alias-sha256sum-no-a "$KIT" sha256sum -a blake2b "$work/crc.in" + # ---- disas ----------------------------------------------------------------- "$KIT" disas -target aarch64 -x "1f 20 03 d5" > "$work/d-aa64.out" 2>&1 contains disas-aa64-nop "$work/d-aa64.out" "nop" @@ -111,6 +123,24 @@ done "$KIT" compress "$work/cz.txt" | "$KIT" compress -d > "$work/cz.def" same_file compress-default-gzip "$work/cz.txt" "$work/cz.def" +# Standard-named aliases: gzip/gunzip and lz4 round-trip through each other and +# through the generic tool; gunzip is just `compress -d` pinned to gzip. +"$KIT" gzip "$work/cz.txt" | "$KIT" gunzip > "$work/cz.gzalias" +same_file alias-gzip-gunzip "$work/cz.txt" "$work/cz.gzalias" +"$KIT" gzip "$work/cz.txt" | "$KIT" compress -d > "$work/cz.gz2generic" +same_file alias-gzip-to-generic "$work/cz.txt" "$work/cz.gz2generic" +"$KIT" lz4 "$work/cz.txt" | "$KIT" lz4 -d > "$work/cz.lz4alias" +same_file alias-lz4-roundtrip "$work/cz.txt" "$work/cz.lz4alias" +"$KIT" lz4c "$work/cz.txt" | "$KIT" lz4 -d > "$work/cz.lz4calias" +same_file alias-lz4c-roundtrip "$work/cz.txt" "$work/cz.lz4calias" +# gzip -d flips direction; the common gzip flags (-c, level -9) are no-ops. +"$KIT" gzip -9 -c "$work/cz.txt" | "$KIT" gzip -d > "$work/cz.compat" +same_file alias-gzip-compat-flags "$work/cz.txt" "$work/cz.compat" +# A pinned alias rejects -z, and gunzip will not auto-detect a foreign container. +run_fail alias-gzip-no-z "$KIT" gzip -z lz4 "$work/cz.txt" +"$KIT" lz4 "$work/cz.txt" > "$work/cz.lz4only" +run_fail alias-gunzip-wrong-format "$KIT" gunzip "$work/cz.lz4only" + # Error exits: bad format / two inputs / missing file all exit non-zero. run_fail compress-err-bad-format "$KIT" compress -z bogus "$work/cz.txt" run_fail compress-err-two-inputs "$KIT" compress "$work/cz.txt" "$work/cz.empty"