6 ex__sha256_8c
gullradriel edited this page 2026-10-09 00:55:18 +02:00

examples/ex_sha256.c

Functions

Name
int process_args(int argc, char ** argv)
read -V
int main(int argc, char ** argv)
run the checks
int hex_is(const void * data, size_t len, const char * want)
the hex digest of a buffer equals the expected one
void expect_true(const char * what, int ok)
count a failed check

Attributes

Name
int log_level
log level from -V
int failures
failed checks

Functions Documentation

function process_args

static int process_args(
    int argc,
    char ** argv
)

read -V

Parameters:

  • argc argument count
  • argv arguments

Return: 0, or -1 on a bad argument

function main

int main(
    int argc,
    char ** argv
)

run the checks

Parameters:

  • argc argument count
  • argv arguments

Return: 0 on success

function hex_is

static int hex_is(
    const void * data,
    size_t len,
    const char * want
)

the hex digest of a buffer equals the expected one

Parameters:

  • data the bytes
  • len how many
  • want expected lowercase hex

Return: non-zero when equal

function expect_true

static void expect_true(
    const char * what,
    int ok
)

count a failed check

Parameters:

  • what the check
  • ok its result

Attributes Documentation

variable log_level

static int log_level = 3;

log level from -V

variable failures

static int failures = 0;

failed checks

Source code

/*
 * Nilorea Library
 * Copyright (C) 2005-2026 Castagnier Mickael
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * SPDX-License-Identifier: Apache-2.0
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "nilorea/n_common.h"
#include "nilorea/n_log.h"
#include "nilorea/n_sha256.h"

static int log_level = LOG_ERR;
static int failures = 0;

static void expect_true(const char* what, int ok) {
    if (!ok) {
        n_log(LOG_ERR, "FAIL: %s", what);
        failures++;
    } else {
        n_log(LOG_INFO, "ok: %s", what);
    }
}

static int process_args(int argc, char** argv) {
    int opt = 0;

    while ((opt = getopt(argc, argv, "V:")) != -1) {
        if (opt == 'V') {
            log_level = atoi(optarg);
        } else {
            return -1;
        }
    }
    return 0;
}

static int hex_is(const void* data, size_t len, const char* want) {
    unsigned char digest[N_SHA256_LEN];
    char hex[N_SHA256_HEX_LEN];

    n_sha256(data, len, digest);
    n_sha256_hex(digest, hex);
    return strcmp(hex, want) == 0;
}

int main(int argc, char** argv) {
    static const char* two_blocks = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
    unsigned char whole[N_SHA256_LEN], pieces[N_SHA256_LEN];
    char* million = NULL;
    size_t step = 0;

    set_log_level(LOG_ERR);
    if (process_args(argc, argv) != 0) {
        fprintf(stderr, "Usage: %s [-V LOG_LEVEL]\n", argv[0]);
        return 2;
    }
    set_log_level(log_level);

    expect_true("the empty string", hex_is("", 0, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"));
    expect_true("abc", hex_is("abc", 3, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"));
    expect_true("two blocks", hex_is(two_blocks, strlen(two_blocks),
                                     "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"));
    million = (char*)malloc(1000000);
    if (million) {
        memset(million, 'a', 1000000);
        expect_true("a million a", hex_is(million, 1000000,
                                          "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"));
        /* Fed in pieces of every size from 1 to 130: the block boundary
         * crossed in every way, the same digest. */
        n_sha256(million, 100000, whole);
        for (step = 1; step <= 130; step++) {
            N_SHA256 ctx;
            size_t done = 0;

            n_sha256_init(&ctx);
            while (done < 100000) {
                size_t take = 100000 - done < step ? 100000 - done : step;

                n_sha256_update(&ctx, million + done, take);
                done += take;
            }
            n_sha256_final(&ctx, pieces);
            if (memcmp(whole, pieces, N_SHA256_LEN) != 0) break;
        }
        expect_true("pieces of every size give the one call's digest", step > 130);
        {
            /* A name of its own in the working directory: mkstemp() is not in
             * every C library this builds against. */
            static const char* path = "ex_sha256.tmp";
            unsigned char from_file[N_SHA256_LEN];
            FILE* f = fopen(path, "wb");

            if (f) {
                size_t wrote = fwrite(million, 1, 1000000, f);

                fclose(f);
                n_sha256(million, 1000000, whole);
                expect_true("a file hashes as its bytes", wrote == 1000000 && n_sha256_file(path, from_file) == 0 &&
                                                              memcmp(whole, from_file, N_SHA256_LEN) == 0);
                remove(path);
            }
            /* Where n_sha256_file() stops reading: empty, and exactly one
             * and two of its 65536 byte reads, where the last read comes back
             * with nothing after full ones. */
            {
                static const size_t sizes[] = {0, 65536, 131072};
                size_t k = 0;

                for (k = 0; k < sizeof(sizes) / sizeof(sizes[0]); k++) {
                    char what[64];
                    size_t wrote = 0;

                    f = fopen(path, "wb");
                    if (!f)
                        continue;
                    wrote = sizes[k] ? fwrite(million, 1, sizes[k], f) : 0;
                    fclose(f);
                    n_sha256(million, sizes[k], whole);
                    snprintf(what, sizeof(what), "a file of %zu bytes hashes as its bytes", sizes[k]);
                    expect_true(what, wrote == sizes[k] && n_sha256_file(path, from_file) == 0 &&
                                          memcmp(whole, from_file, N_SHA256_LEN) == 0);
                    remove(path);
                }
            }
        }
        free(million);
    }
    expect_true("a missing file is refused", n_sha256_file("/nonexistent/ex_sha256", whole) == -1);

    if (failures) {
        fprintf(stderr, "ex_sha256: %d failure(s)\n", failures);
        return 1;
    }
    printf("ex_sha256: ok\n");
    return 0;
}