Import Upstream version 1.8

parent 525656d7
...@@ -17,9 +17,9 @@ ...@@ -17,9 +17,9 @@
# #
# Normal output and testing dirs # Normal output and testing dirs
# #
/?dupes /jdupes
/?dupes-jody /jdupes*.exe
/?dupes*.exe /*.pkg.tar.xz
# #
# Backups / patches # Backups / patches
......
jdupes 1.8
- All files are now licensed under The MIT License exclusively
- Fixed a serious memory alloc bug; upgrading is *strongly* recommended
- Several huge improvements to progress indicators
- Fix some error message display problems and add more error checking
- Fixes for several potential crashes and buffer overflows
- Indicate no duplicates were found if printing matches and none exist
- On Linux, jdupes now auto-tunes I/O size based on CPU L1 D-cache size
- The -v switch now also shows info about bitness in the version string
jdupes 1.7 jdupes 1.7
- Incompatible change: zero-length files no longer duplicates by default - Incompatible change: zero-length files no longer duplicates by default
......
...@@ -6,8 +6,8 @@ make ...@@ -6,8 +6,8 @@ make
su root su root
make install make install
This will install the program in /usr/local/bin. You may change this This will install the program in /usr/bin. You may change this to a
to a different location by editing the Makefile. Please refer to the different location by editing the Makefile. Please refer to the
Makefile for an explanation of compile-time options. If you're having Makefile for an explanation of compile-time options. If you're having
trouble compiling, please take a look at the Makefile. trouble compiling, please take a look at the Makefile.
......
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2015-2016 Jody Lee Bruchon and contributors Copyright (C) 2015-2017 Jody Lee Bruchon and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in
......
...@@ -20,6 +20,10 @@ PREFIX = /usr ...@@ -20,6 +20,10 @@ PREFIX = /usr
# This can be enabled at build time: 'make LOW_MEMORY=1' # This can be enabled at build time: 'make LOW_MEMORY=1'
#LOW_MEMORY=1 #LOW_MEMORY=1
# Uncomment this to build in hardened mode.
# This can be enabled at build time: 'make HARDEN=1'
#HARDEN=1
##################################################################### #####################################################################
# Developer Configuration Section # # Developer Configuration Section #
##################################################################### #####################################################################
...@@ -63,6 +67,10 @@ endif ...@@ -63,6 +67,10 @@ endif
ifdef DEBUG ifdef DEBUG
COMPILER_OPTIONS += -DDEBUG COMPILER_OPTIONS += -DDEBUG
endif endif
ifdef HARDEN
COMPILER_OPTIONS += -Wformat -Wformat-security -D_FORTIFY_SOURCE=2 -fstack-protector-strong -fPIE -fpie -Wl,-z,relro -Wl,-z,now
endif
# MinGW needs this for printf() conversions to work # MinGW needs this for printf() conversions to work
ifeq ($(OS), Windows_NT) ifeq ($(OS), Windows_NT)
...@@ -83,6 +91,7 @@ endif ...@@ -83,6 +91,7 @@ endif
# New BTRFS support option # New BTRFS support option
ifdef ENABLE_BTRFS ifdef ENABLE_BTRFS
COMPILER_OPTIONS += -DENABLE_BTRFS COMPILER_OPTIONS += -DENABLE_BTRFS
OBJECT_FILES += act_dedupefiles.o
endif endif
# Low memory mode # Low memory mode
ifdef LOW_MEMORY ifdef LOW_MEMORY
...@@ -99,7 +108,8 @@ INSTALL_DATA = $(INSTALL) -c -m 0644 ...@@ -99,7 +108,8 @@ INSTALL_DATA = $(INSTALL) -c -m 0644
#ADDITIONAL_OBJECTS += getopt.o #ADDITIONAL_OBJECTS += getopt.o
OBJECT_FILES += jdupes.o jody_hash.o jody_paths.o jody_sort.o jody_win_unicode.o string_malloc.o OBJECT_FILES += jdupes.o jody_hash.o jody_paths.o jody_sort.o jody_win_unicode.o string_malloc.o
OBJECT_FILES += act_deletefiles.o act_dedupefiles.o act_linkfiles.o act_printmatches.o act_summarize.o OBJECT_FILES += jody_cacheinfo.o
OBJECT_FILES += act_deletefiles.o act_linkfiles.o act_printmatches.o act_summarize.o
OBJECT_FILES += $(ADDITIONAL_OBJECTS) OBJECT_FILES += $(ADDITIONAL_OBJECTS)
all: jdupes all: jdupes
...@@ -117,3 +127,9 @@ install: jdupes installdirs ...@@ -117,3 +127,9 @@ install: jdupes installdirs
clean: clean:
$(RM) $(OBJECT_FILES) $(PROGRAM_NAME) jdupes.exe *~ *.gcno *.gcda *.gcov $(RM) $(OBJECT_FILES) $(PROGRAM_NAME) jdupes.exe *~ *.gcno *.gcda *.gcov
distclean: clean
$(RM) *.pkg.tar.xz
package:
+./chroot_build.sh
...@@ -299,10 +299,9 @@ Please DO NOT contact Adrian Lopez about issues with jdupes. ...@@ -299,10 +299,9 @@ Please DO NOT contact Adrian Lopez about issues with jdupes.
Legal Information and Software License Legal Information and Software License
-------------------------------------------------------------------------- --------------------------------------------------------------------------
jdupes is Copyright (C) 2015-2016 by Jody Bruchon <jody@jodybruchon.com> jdupes is Copyright (C) 2015-2017 by Jody Bruchon <jody@jodybruchon.com>
Derived from the original 'fdupes' (C) 1999-2016 by Adrian Lopez Derived from the original 'fdupes' (C) 1999-2017 by Adrian Lopez
Includes jody_hash, jody_paths, jody_sort, and string_malloc, all of Includes other code libraries which are (C) 2015-2017 by Jody Bruchon
which are (C) 2015-2016 Jody Bruchon
The MIT License The MIT License
......
- A bug with -S shows wrong results.
- A bug causes the following behavior:
$ jdupes --symlinks testdir
testdir/with spaces b
testdir/with spaces a
testdir/zero_b
testdir/zero_a
testdir/symlink_two
testdir/twice_one
$ cp testdir/two testdir/two_again
$ jdupes --symlinks testdir
testdir/two_again
testdir/two
testdir/twice_one
testdir/symlink_two
testdir/with spaces b
testdir/with spaces a
testdir/zero_b
testdir/zero_a
** This is not the desired behavior. Likewise:
$ jdupes testdir
testdir/with spaces b
testdir/with spaces a
testdir/zero_b
testdir/zero_a
testdir/twice_one
testdir/two
$ jdupes --symlinks testdir
testdir/with spaces b
testdir/with spaces a
testdir/zero_b
testdir/zero_a
testdir/symlink_two
testdir/twice_one
- Option -R should not have to be separated from the rest, - Option -R should not have to be separated from the rest,
such that "jdupes -dR testdir", "jdupes -d -R testdir", such that "jdupes -dR testdir", "jdupes -d -R testdir",
"jdupes -Rd testdir", etc., all yield the same results. "jdupes -Rd testdir", etc., all yield the same results.
...@@ -61,19 +12,6 @@ ...@@ -61,19 +12,6 @@
explicit loading in future runs to speed up repeated calls to explicit loading in future runs to speed up repeated calls to
the program. the program.
- Add an option to exclude files in the same directory from being
matched. This should be extensible so that various exclusion
criteria can be added later.
- Also add code to make directory ordering of pair matching more
stable; for instance, if dirs 'foo' and 'bar' are specified,
always put 'foo' at the start of the dupe set (which makes it
take precedence over 'bar' in this example.)
- The way that duplicates are sorted does not seem to work properly. The
sorting needs to be separated into its own function that sorts fully.
As it stands, sorting is only correct on specific match pairs and is
sometimes overridden by other match pairs to mess up the sort.
- The --xsize option can be improved. Instead of simply specifying an - The --xsize option can be improved. Instead of simply specifying an
exclusion size min/max, the option should offer multiple ways to exclusion size min/max, the option should offer multiple ways to
specify allowed file sizes. Examples: specify allowed file sizes. Examples:
......
/* BTRFS deduplication of file blocks */ /* BTRFS deduplication of file blocks
* This file is part of jdupes; see jdupes.c for license information */
#include "jdupes.h" #include "jdupes.h"
...@@ -9,9 +10,8 @@ ...@@ -9,9 +10,8 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/btrfs.h> #include <linux/btrfs.h>
#include <sys/ioctl.h>
#include "act_dedupefiles.h" #include "act_dedupefiles.h"
/* Message to append to BTRFS warnings based on write permissions */ /* Message to append to BTRFS warnings based on write permissions */
......
/* jdupes action for BTRFS block-level deduplication */ /* jdupes action for BTRFS block-level deduplication
* This file is part of jdupes; see jdupes.c for license information */
#ifndef ACT_DEDUPEFILES_H #ifndef ACT_DEDUPEFILES_H
#define ACT_DEDUPEFILES_H #define ACT_DEDUPEFILES_H
......
/* Delete duplicate files automatically or interactively */ /* Delete duplicate files automatically or interactively
* This file is part of jdupes; see jdupes.c for license information */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
......
/* jdupes action for deleting duplicate files */ /* jdupes action for deleting duplicate files
* This file is part of jdupes; see jdupes.c for license information */
#ifndef ACT_DELETEFILES_H #ifndef ACT_DELETEFILES_H
#define ACT_DELETEFILES_H #define ACT_DELETEFILES_H
......
/* Hard link or symlink files */ /* Hard link or symlink files
* This file is part of jdupes; see jdupes.c for license information */
#include "jdupes.h" #include "jdupes.h"
......
/* jdupes action for hard and soft file linking */ /* jdupes action for hard and soft file linking
* This file is part of jdupes; see jdupes.c for license information */
#ifndef ACT_LINKFILES_H #ifndef ACT_LINKFILES_H
#define ACT_LINKFILES_H #define ACT_LINKFILES_H
......
/* Print matched file sets
* This file is part of jdupes; see jdupes.c for license information */
#include <stdio.h> #include <stdio.h>
#include "jdupes.h" #include "jdupes.h"
#include "jody_win_unicode.h" #include "jody_win_unicode.h"
...@@ -6,9 +9,11 @@ ...@@ -6,9 +9,11 @@
extern void printmatches(file_t * restrict files) extern void printmatches(file_t * restrict files)
{ {
file_t * restrict tmpfile; file_t * restrict tmpfile;
int printed = 0;
while (files != NULL) { while (files != NULL) {
if (ISFLAG(files->flags, F_HAS_DUPES)) { if (ISFLAG(files->flags, F_HAS_DUPES)) {
printed = 1;
if (!ISFLAG(flags, F_OMITFIRST)) { if (!ISFLAG(flags, F_OMITFIRST)) {
if (ISFLAG(flags, F_SHOWSIZE)) printf("%jd byte%c each:\n", (intmax_t)files->size, if (ISFLAG(flags, F_SHOWSIZE)) printf("%jd byte%c each:\n", (intmax_t)files->size,
(files->size != 1) ? 's' : ' '); (files->size != 1) ? 's' : ' ');
...@@ -25,5 +30,8 @@ extern void printmatches(file_t * restrict files) ...@@ -25,5 +30,8 @@ extern void printmatches(file_t * restrict files)
files = files->next; files = files->next;
} }
if (printed == 0) fprintf(stderr, "No duplicates found.\n");
return; return;
} }
/* jdupes action for printing matched file sets to stdout */ /* jdupes action for printing matched file sets to stdout
* This file is part of jdupes; see jdupes.c for license information */
#ifndef ACT_PRINTMATCHES_H #ifndef ACT_PRINTMATCHES_H
#define ACT_PRINTMATCHES_H #define ACT_PRINTMATCHES_H
......
/* Print summary of match statistics to stdout */ /* Print summary of match statistics to stdout
* This file is part of jdupes; see jdupes.c for license information */
#include <stdio.h> #include <stdio.h>
#include "jdupes.h" #include "jdupes.h"
......
/* jdupes action for printing a summary of match stats to stdout */ /* jdupes action for printing a summary of match stats to stdout
* This file is part of jdupes; see jdupes.c for license information */
#ifndef ACT_SUMMARIZE_H #ifndef ACT_SUMMARIZE_H
#define ACT_SUMMARIZE_H #define ACT_SUMMARIZE_H
......
#!/bin/sh
# Jody's generic chroot build script
# Version 1.0
ARCHES="i386 x86-64 uclibc-i386 uclibc-x86-64"
test -z "$NAME" && NAME="$(basename "$(pwd)")"
test -e "version.h" && VER="$(grep '#define VER ' version.h | tr -d \\\" | cut -d' ' -f3)"
test -z "$VER" && VER=0
export NAME
export VER
export CHROOT_BASE=/chroots
export WD="$(pwd)"
export PKG="pkg"
echo "chroot builder: building '$NAME' version '$VER'"
trap clean_exit INT QUIT ABRT HUP
clean_exit () {
umount $CHROOT/proc $CHROOT/sys $CHROOT/tmp $CHROOT/dev $CHROOT/usr/src $CHROOT/home
}
do_build () {
test -z "$WD" && echo "WD not set, aborting" && exit 1
test -z "$PKG" && echo "PKG not set, aborting" && exit 1
make clean
if ! make -j$JOBS all
then echo "Build failed"; exit 1
else
echo "WD/PKG: $WD/$PKG"
test -d $WD/$PKG && rm -rf $WD/$PKG
mkdir $WD/$PKG
make DESTDIR=$WD/$PKG install && \
tar -C pkg -c usr | xz -e > ${NAME}_$VER-$ARCH.pkg.tar.xz
echo "Built ${NAME}_$VER-$ARCH.pkg.tar.xz"
fi
}
if [ "$(id -u)" != "0" ]
then echo "You must be root to auto-build chroot packages."
exit 1
fi
if [ "$DO_CHROOT_BUILD" = "1" ]
then
test -z "$1" && echo "No arch specified" && exit 1
test ! -d "$1" && echo "Not a directory: $1" && exit 1
cd $1
export WD="$1"
do_build
echo "finished: $1"
exit
else
echo baz
export DO_CHROOT_BUILD=1
for ARCH in $ARCHES
do
export ARCH
export CHROOT="$CHROOT_BASE/$ARCH"
test ! -d $CHROOT && echo "$CHROOT not present, not building $ARCH package." && continue
echo "Performing package build for $CHROOT"
test ! -x $CHROOT/bin/sh && echo "$CHROOT does not seem to be a chroot; aborting." && exit 1
mount --bind /dev $CHROOT/dev || clean_exit
mount --bind /usr/src $CHROOT/usr/src || clean_exit
mount --bind /home $CHROOT/home || clean_exit
mount -t proc proc $CHROOT/proc || clean_exit
mount -t sysfs sysfs $CHROOT/sys || clean_exit
mount -t tmpfs tmpfs $CHROOT/tmp || clean_exit
if echo "$ARCH" | grep -q "i386"
then linux32 chroot $CHROOT $WD/$0 $WD
else chroot $CHROOT $WD/$0 $WD
fi
umount $CHROOT/proc $CHROOT/sys $CHROOT/tmp $CHROOT/dev $CHROOT/usr/src $CHROOT/home
test -d $WD/$PKG && rm -rf $WD/$PKG
done
fi
...@@ -52,7 +52,7 @@ reverse (invert) the sort order of matches ...@@ -52,7 +52,7 @@ reverse (invert) the sort order of matches
isolate each command-line parameter from one another; only match if the isolate each command-line parameter from one another; only match if the
files are under different parameter specifications files are under different parameter specifications
.TP .TP
.B -L --hardlink .B -L --linkhard
replace all duplicate files with hardlinks to the first file in each set replace all duplicate files with hardlinks to the first file in each set
of duplicates of duplicates
.TP .TP
...@@ -96,7 +96,7 @@ Examples section below for further explanation) ...@@ -96,7 +96,7 @@ Examples section below for further explanation)
.B -r --recurse .B -r --recurse
for every directory given follow subdirectories encountered within for every directory given follow subdirectories encountered within
.TP .TP
.B -s --linksoft .B -l --linksoft
replace all duplicate files with symlinks to the first file in each set replace all duplicate files with symlinks to the first file in each set
of duplicates of duplicates
.TP .TP
......
This diff is collapsed.
/* jdupes module header */ /* jdupes main program header
* See jdupes.c for license information */
#ifndef JDUPES_H #ifndef JDUPES_H
#define JDUPES_H #define JDUPES_H
...@@ -77,8 +78,6 @@ extern int out_mode; ...@@ -77,8 +78,6 @@ extern int out_mode;
/* Low memory option overrides */ /* Low memory option overrides */
#ifdef LOW_MEMORY #ifdef LOW_MEMORY
#undef DEBUG
#undef LOUD_DEBUG
#undef USE_TREE_REBALANCE #undef USE_TREE_REBALANCE
#ifndef NO_PERMS #ifndef NO_PERMS
#define NO_PERMS 1 #define NO_PERMS 1
...@@ -150,10 +149,6 @@ typedef enum { ...@@ -150,10 +149,6 @@ typedef enum {
ORDER_TIME ORDER_TIME
} ordertype_t; } ordertype_t;
/* Larger chunk size makes large files process faster but uses more RAM */
#ifndef CHUNK_SIZE
#define CHUNK_SIZE 65536
#endif
#ifndef PARTIAL_HASH_SIZE #ifndef PARTIAL_HASH_SIZE
#define PARTIAL_HASH_SIZE 4096 #define PARTIAL_HASH_SIZE 4096
#endif #endif
...@@ -215,6 +210,7 @@ extern struct stat s; ...@@ -215,6 +210,7 @@ extern struct stat s;
#endif #endif
extern void oom(const char * const restrict msg); extern void oom(const char * const restrict msg);
extern void nullptr(const char * restrict func);
extern int file_has_changed(file_t * const restrict file); extern int file_has_changed(file_t * const restrict file);
extern int getfilestats(file_t * const restrict file); extern int getfilestats(file_t * const restrict file);
extern int getdirstats(const char * const restrict name, extern int getdirstats(const char * const restrict name,
......
/* Detect and report size of CPU caches
*
* Copyright (C) 2017 by Jody Bruchon <jody@jodybruchon.com>
* Distributed under The MIT License
*
* If an error occurs or a cache is missing, zeroes are returned
* Unified caches populate l1/l2/l3; split caches populate lXi/lXd instead
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jody_cacheinfo.h"
static char *pathidx;
static char buf[16];
static char path[64] = "/sys/devices/system/cpu/cpu0/cache/index";
/*** End declarations, begin code ***/
/* Linux sysfs */
#ifndef ON_WINDOWS
static size_t read_procfile(const char * const restrict name)
{
FILE *fp;
size_t i;
if (name == NULL) return 0;
memset(buf, 0, 16);
/* Create path */
*pathidx = '\0';
strcpy(pathidx, name);
fp = fopen(path, "rb");
if (fp == NULL) return 0;
i = fread(buf, 1, 16, fp);
if (ferror(fp)) return 0;
fclose(fp);
return i;
}
void get_proc_cacheinfo(struct proc_cacheinfo *pci)
{
char *idx;
size_t i;
size_t size;
int level;
char type;
char index;
if (pci == NULL) return;
memset(pci, 0, sizeof(struct proc_cacheinfo));
i = strlen(path);
if (i > 48) return;
idx = path + i;
pathidx = idx + 1;
*pathidx = '/'; pathidx++;
for (index = '0'; index < '9'; index++) {
*idx = index;
/* Get the level for this index */
if (read_procfile("level") == 0) break;
if (*buf < '1' || *buf > '3') break;
else level = (*buf) + 1 - '1';
/* Get the size */
if (read_procfile("size") == 0) break;
size = (size_t)atoi(buf) * 1024;
if (size == 0) break;
/* Get the type */
if (read_procfile("type") == 0) break;
if (*buf != 'U' && *buf != 'I' && *buf != 'D') break;
type = *buf;
/* Act on it */
switch (type) {
case 'D':
switch (level) {
case 1: pci->l1d = size; break;
case 2: pci->l2d = size; break;
case 3: pci->l3d = size; break;
default: return;
};
break;
case 'I':
switch (level) {
case 1: pci->l1i = size; break;
case 2: pci->l2i = size; break;
case 3: pci->l3i = size; break;
default: return;
};
break;
case 'U':
switch (level) {
case 1: pci->l1 = size; break;
case 2: pci->l2 = size; break;
case 3: pci->l3 = size; break;
default: return;
};
break;
default: return;
}
/* Continue to next index */
}
return;
}
#else
#define get_proc_cacheinfo(a)
#endif /* ON_WINDOWS */
/* This is for testing only */
#if 0
int main(void)
{
static struct proc_cacheinfo pci;
get_proc_cacheinfo(&pci);
printf("Cache: L1 %d,%d,%d L2 %d,%d,%d L3 %d,%d,%d\n",
pci.l1, pci.l1i, pci.l1d,
pci.l2, pci.l2i, pci.l2d,
pci.l3, pci.l3i, pci.l3d);
return 0;
}
#endif
/* Detect size of CPU data caches
* See jody_cacheinfo.c for license information */
#ifndef JODY_CACHEINFO_H
#define JODY_CACHEINFO_H
#ifdef __cplusplus
extern "C" {
#endif
/* Cache information structure
* Split caches populate i/d, unified caches populate non-i/d */
struct proc_cacheinfo {
size_t l1;
size_t l1i;
size_t l1d;
size_t l2;
size_t l2i;
size_t l2d;
size_t l3;
size_t l3i;
size_t l3d;
};
extern void get_proc_cacheinfo(struct proc_cacheinfo *pci);
#ifdef __cplusplus
}
#endif
#endif /* JODY_CACHEINFO_H */
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
* a secure hash algorithm, but the calculation is drastically simpler * a secure hash algorithm, but the calculation is drastically simpler
* and faster. * and faster.
* *
* Copyright (C) 2014-2016 by Jody Bruchon <jody@jodybruchon.com> * Copyright (C) 2014-2017 by Jody Bruchon <jody@jodybruchon.com>
* Released under The MIT License or GNU GPL v2 (your choice) * Released under The MIT License
*/ */
#include <stdio.h> #include <stdio.h>
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
/* Set hash parameters based on requested hash width */ /* Set hash parameters based on requested hash width */
#if JODY_HASH_WIDTH == 64 #if JODY_HASH_WIDTH == 64
#define JODY_HASH_CONSTANT 0x1f3d5b79 #define JODY_HASH_CONSTANT 0x1f3d5b79U
static const hash_t tail_mask[] = { static const hash_t tail_mask[] = {
0x0000000000000000, 0x0000000000000000,
0x00000000000000ff, 0x00000000000000ff,
...@@ -46,7 +46,7 @@ static const hash_t tail_mask[] = { ...@@ -46,7 +46,7 @@ static const hash_t tail_mask[] = {
}; };
#endif /* JODY_HASH_WIDTH == 64 */ #endif /* JODY_HASH_WIDTH == 64 */
#if JODY_HASH_WIDTH == 32 #if JODY_HASH_WIDTH == 32
#define JODY_HASH_CONSTANT 0x1f3d5b79 #define JODY_HASH_CONSTANT 0x1f3d5b79U
static const hash_t tail_mask[] = { static const hash_t tail_mask[] = {
0x00000000, 0x00000000,
0x000000ff, 0x000000ff,
...@@ -56,7 +56,7 @@ static const hash_t tail_mask[] = { ...@@ -56,7 +56,7 @@ static const hash_t tail_mask[] = {
}; };
#endif /* JODY_HASH_WIDTH == 32 */ #endif /* JODY_HASH_WIDTH == 32 */
#if JODY_HASH_WIDTH == 16 #if JODY_HASH_WIDTH == 16
#define JODY_HASH_CONSTANT 0x1f5b #define JODY_HASH_CONSTANT 0x1f5bU
static const hash_t tail_mask[] = { static const hash_t tail_mask[] = {
0x0000, 0x0000,
0x00ff, 0x00ff,
...@@ -75,8 +75,8 @@ static const hash_t tail_mask[] = { ...@@ -75,8 +75,8 @@ static const hash_t tail_mask[] = {
extern hash_t jody_block_hash(const hash_t * restrict data, extern hash_t jody_block_hash(const hash_t * restrict data,
const hash_t start_hash, const size_t count) const hash_t start_hash, const size_t count)
{ {
register hash_t hash = start_hash; hash_t hash = start_hash;
register hash_t element; hash_t element;
hash_t partial_salt; hash_t partial_salt;
size_t len; size_t len;
......
/* Jody Bruchon's fast hashing function (headers) /* Jody Bruchon's fast hashing function (headers)
* * See jody_hash.c for license information */
* Copyright (C) 2014-2016 by Jody Bruchon <jody@jodybruchon.com>
* See jody_hash.c for more information.
*/
#ifndef JODY_HASH_H