diff --git a/include/sort_r.h b/include/sort_r.h new file mode 100644 index 000000000..a80f556b3 --- /dev/null +++ b/include/sort_r.h @@ -0,0 +1,225 @@ +/* Isaac Turner 29 April 2014 Public Domain */ +#ifndef SORT_R_H_ +#define SORT_R_H_ + +#include +#include + +/* + +sort_r function to be exported. + +Parameters: + base is the array to be sorted + nel is the number of elements in the array + width is the size in bytes of each element of the array + compar is the comparison function + arg is a pointer to be passed to the comparison function + +void sort_r(void *base, size_t nel, size_t width, + int (*compar)(const void *_a, const void *_b, void *_arg), + void *arg); + +Slightly modified to work with hashcat to no falsly detect _SORT_R_LINUX with mingw + +*/ + +#if (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || \ + defined __FreeBSD__ || defined __DragonFly__) +# define _SORT_R_BSD +# define _SORT_R_INLINE inline +#elif (defined __linux__) +# define _SORT_R_LINUX +# define _SORT_R_INLINE inline +#elif (defined _WIN32 || defined _WIN64 || defined __WINDOWS__) +# define _SORT_R_WINDOWS +# define _SORT_R_INLINE __inline +#else + /* Using our own recursive quicksort sort_r_simple() */ +#endif + +#if (defined NESTED_QSORT && NESTED_QSORT == 0) +# undef NESTED_QSORT +#endif + +/* swap a, b iff a>b */ +/* __restrict is same as restrict but better support on old machines */ +static _SORT_R_INLINE int sort_r_cmpswap(char *__restrict a, char *__restrict b, size_t w, + int (*compar)(const void *_a, const void *_b, + void *_arg), + void *arg) +{ + char tmp, *end = a+w; + if(compar(a, b, arg) > 0) { + for(; a < end; a++, b++) { tmp = *a; *a = *b; *b = tmp; } + return 1; + } + return 0; +} + +/* Implement recursive quicksort ourselves */ +/* Note: quicksort is not stable, equivalent values may be swapped */ +static _SORT_R_INLINE void sort_r_simple(void *base, size_t nel, size_t w, + int (*compar)(const void *_a, const void *_b, + void *_arg), + void *arg) +{ + char *b = (char *)base, *end = b + nel*w; + if(nel < 7) { + /* Insertion sort for arbitrarily small inputs */ + char *pi, *pj; + for(pi = b+w; pi < end; pi += w) { + for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {} + } + } + else + { + /* nel > 6; Quicksort */ + + /* Use median of first, middle and last items as pivot */ + char *x, *y, *xend, ch; + char *pl, *pr; + char *last = b+w*(nel-1), *tmp; + char *l[3]; + l[0] = b; + l[1] = b+w*(nel/2); + l[2] = last; + + if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; } + if(compar(l[1],l[2],arg) > 0) { + tmp=l[1]; l[1]=l[2]; l[2]=tmp; /* swap(l[1],l[2]) */ + if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; } + } + + /* swap l[id], l[2] to put pivot as last element */ + for(x = l[1], y = last, xend = x+w; xcompar)(a, b, ss->arg); + } + + #endif + + #if defined _SORT_R_LINUX + + typedef int(* __compar_d_fn_t)(const void *, const void *, void *); + extern void qsort_r(void *base, size_t nel, size_t width, + __compar_d_fn_t __compar, void *arg) + __attribute__((nonnull (1, 4))); + + #endif + + /* implementation */ + + static _SORT_R_INLINE void sort_r(void *base, size_t nel, size_t width, + int (*compar)(const void *_a, const void *_b, void *_arg), + void *arg) + { + #if defined _SORT_R_LINUX + + #if defined __GLIBC__ && ((__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 8)) + + /* no qsort_r in glibc before 2.8, need to use nested qsort */ + sort_r_simple(base, nel, width, compar, arg); + + #else + + qsort_r(base, nel, width, compar, arg); + + #endif + + #elif defined _SORT_R_BSD + + struct sort_r_data tmp; + tmp.arg = arg; + tmp.compar = compar; + qsort_r(base, nel, width, &tmp, sort_r_arg_swap); + + #elif defined _SORT_R_WINDOWS + + struct sort_r_data tmp; + tmp.arg = arg; + tmp.compar = compar; + qsort_s(base, nel, width, sort_r_arg_swap, &tmp); + + #else + + /* Fall back to our own quicksort implementation */ + sort_r_simple(base, nel, width, compar, arg); + + #endif + } + +#endif /* !NESTED_QSORT */ + +#undef _SORT_R_INLINE +#undef _SORT_R_WINDOWS +#undef _SORT_R_LINUX +#undef _SORT_R_BSD + +#endif /* SORT_R_H_ */ diff --git a/src/potfile.c b/src/potfile.c index 6b7d4ded4..6259fadb1 100644 --- a/src/potfile.c +++ b/src/potfile.c @@ -13,6 +13,14 @@ #include "outfile.h" #include "potfile.h" +#if defined (_WIN) +#define __WINDOWS__ +#endif +#include "sort_r.h" +#if defined (_WIN) +#undef __WINDOWS__ +#endif + // get rid of this later int sort_by_hash (const void *v1, const void *v2, void *v3); int sort_by_hash_no_salt (const void *v1, const void *v2, void *v3); @@ -110,38 +118,7 @@ int sort_by_hash_t_salt_hccap (const void *v1, const void *v2) void hc_qsort_r (void *base, size_t nmemb, size_t size, int (*compar) (const void *, const void *, void *), void *arg) { - /* - ** ssort() -- Fast, small, qsort()-compatible Shell sort - ** - ** by Ray Gardner, public domain 5/90 - * slightly modified to work with hashcat by Jens Steube - */ - - size_t wnel, gap, wgap, i, j, k; - char *a, *b, tmp; - - wnel = size * nmemb; - for (gap = 0; ++gap < nmemb;) - gap *= 3; - while ((gap /= 3) != 0) { - wgap = size * gap; - for (i = wgap; i < wnel; i += size) { - for (j = i - wgap; ;j -= wgap) { - a = j + (char *)base; - b = a + wgap; - if ((*compar)(a, b, arg) <= 0) - break; - k = size; - do { - tmp = *a; - *a++ = *b; - *b++ = tmp; - } while (--k); - if (j < wgap) - break; - } - } - } + sort_r (base, nmemb, size, compar, arg); } void *hc_bsearch_r (const void *key, const void *base, size_t nmemb, size_t size, int (*compar) (const void *, const void *, void *), void *arg)