About

This is a small command-line utility that computes a 32-bit Fowler-Noll-Vo (FNV) hash of an input file supplied on the command line. The Fowler-Noll-Vo hash is a non-cryptographic hash function created by Glenn Fowler, Landon Curt Noll and Phong Vo. Compared to other hash functions, the FNV hash function is a small hashing function. The implementation in this package computes a 32-bit hash function from an input file and is implemented using AmigaOS functions - optionally benefiting from asyncio.library if present.

Download

Installing

  1. Extract the archive
  2. Copy any desired optimised variant of bin/fnv32_* to C: (or any other directory in the executable path)

Compiling

The current implementation was written to be compiled with SAS/C but you can compile it with whatever tool available that has the required AmigaOS libraries and include files. You may need to download dev/c/AsyncIO.lha by Magnus Holmgren since it contains the required include files. If needed, the include files and libraries should be moved to the SAS/C folder (libs under libs, include under include, etc…).

After all the includes and libraries are setup correctly, you can change directory to src and then issue the command:

sc link fnv32.c

and it should result in a fnv32 binary file.

Usage

After copying the binary to an executable path, issue:

fnv32 input.txt

where input.txt is file.

The program should print out the FNV hash of the file.

You can also specify which bits to mask off but MASK (the default is 32):

fnv32 mask=16 input.txt

Code

/*************************************************************************/
/*    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    */
/*************************************************************************/
/*                                                                       */
/*  fnv32                                                                */
/*                                                                       */
/*  $VER: fnv32 1.0 (14 Jul 2015) by Wizardry and Steamworks             */
/*                                                                       */
/*  Computes a 32-bit Fowler-Noll-Vo hash of a given input file.         */
/*                                                                       */
/*  Compile using SASC: sc link fnv32.c                                  */
/*                                                                       */
/*  More info on FNV: http://www.isthe.com/chongo/tech/comp/fnv/         */
/*                                                                       */
/*************************************************************************/
 
#include <string.h>
#include <stdlib.h>
 
#include <proto/asyncio.h>
#include <proto/dos.h>
#include <proto/exec.h>
 
GLOBAL TEXT version_string[] = 
    "\0$VER: fnv32 1.0 (14 Jul 2015) by Wizardry and Steamworks";
 
/*************************************************************************/
/*  Hash in chunks of 32 * 1024 for a 32-bit hash width.                 */
/*************************************************************************/
#define WIDTH 32
#define BUF_SIZE 32 * 1024
 
/*************************************************************************/
/*  Magic prime and initialization vector.                               */
/*************************************************************************/
#define FNV_32_PRIME ((ULONG)0x01000193)
#define FNV1_32_INIT ((ULONG)0x811c9dc5)
 
/*************************************************************************/
/*  Fowler-Noll-Vo hashing function.                                     */
/*************************************************************************/
ULONG fnv_32_buf(void *buf, LONG len, ULONG hval) {
    unsigned char *bp = (UBYTE *)buf;
    unsigned char *be = bp + len;
    while(bp < be) {
        hval *= FNV_32_PRIME;
        hval ^= (ULONG)*bp++;
    }
    return hval;
}
 
/* mask is optional, path to file is not */
STATIC CONST TEXT template[] = "MASK=MASK/K/N,PATH/A";
enum {
    MASK,
	PATH,
	NUM_ARGS
};
 
int main(int argc, char **argv) {
    struct Library *AsyncIOBase;
    LONG readsz;
    UBYTE *buf;
    APTR fh;
 
    /* initialize hash to 32-bit vector */
    ULONG hval = FNV1_32_INIT;
 
    /* setup command-line arguments to retrieve file and mask */
    LONG *arg_array;
	struct RDArgs *rdargs;
    STRPTR file;
    ULONG mask;
 
    /* allocate memory for arg array */
    arg_array = AllocMem(NUM_ARGS, MEMF_ANY|MEMF_CLEAR);
    if(arg_array == NULL) {
        Printf("Unable to allocate memory.\n");
        return 1;
    }
 
    /* read command-line arguments */
    rdargs = ReadArgs(template, arg_array, NULL);
    if(rdargs == NULL) {
        FreeArgs(rdargs);
        return 1;
    }
    /* assign file */
    file = (STRPTR)arg_array[PATH];
    /* assign mask */
    mask = (ULONG *)arg_array[MASK] != NULL ? 
           *(ULONG *)arg_array[MASK] : 
           WIDTH;
    FreeArgs(rdargs);
 
    /* if the mask is not between 0 and WIDTH (inclusive) then bail */
    if(mask < 0 || mask > WIDTH) {
        Printf("The MASK parameter must be between 0 and %ld.\n", WIDTH);
        return 1;
    }
    /* setup mask */
    switch(mask != (ULONG)WIDTH) {
        case TRUE:
            mask = (ULONG)((1 << mask) - 1);
            break;
        default:
            mask = (ULONG)0xffffffff;
            break;
    }
 
	/* allocate buffer */
	buf = AllocMem(BUF_SIZE + 1, MEMF_ANY|MEMF_CLEAR);
    if(buf == NULL) {
        Printf("Unable to allocate memory.\n");
        return 1;
    }
 
    /* attempt to open the asyncio library */
    AsyncIOBase = OpenLibrary("asyncio.library", 0);
 
    /* either use asyncio library if available or regular file-handling */
    switch(AsyncIOBase != NULL) {
        case TRUE:
            fh = OpenAsync(file, MODE_READ, BUF_SIZE);
            break;
        default:
            fh = (APTR)Open(file, MODE_OLDFILE);
            break;
    }
 
    /* the file could not be opened so bail */
    if(fh == NULL) {
        Printf("Unable to open file: %s\n", file);
        if(AsyncIOBase != NULL)
            CloseLibrary(AsyncIOBase);
        return 1;
    }
 
    /* compute the hash by reading chunks */
    switch(AsyncIOBase != NULL) {
        case TRUE:
            while((readsz = ReadAsync(fh, buf, BUF_SIZE)) > 0)
                hval = fnv_32_buf(buf, readsz, hval);
            break;
        default:
            while((readsz = Read((BPTR)fh, buf, BUF_SIZE)) > 0)
                hval = fnv_32_buf(buf, readsz, hval);
            break;
    }
 
    /* close file-handles */
    switch(AsyncIOBase != NULL) {
        case TRUE:
            CloseAsync(fh);
            break;
        default:
            Close((BPTR)fh);
            break;
    }
 
    /* print the hash and mask it */
    Printf("0x%08lx\n", hval & mask);
 
    /* graceful exit. */
    return 0;
}

amiga/development/os3/fowler-noll-vo.txt · Last modified: 2022/04/19 08:28 by 127.0.0.1

Access website using Tor Access website using i2p Wizardry and Steamworks PGP Key


For the contact, copyright, license, warranty and privacy terms for the usage of this website please see the contact, license, privacy, copyright.