fargo 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/fargo/tiger.c ADDED
@@ -0,0 +1,245 @@
1
+ /* (PD) 2001 The Bitzi Corporation
2
+ * Please see file COPYING or http://bitzi.com/publicdomain
3
+ * for more info.
4
+ *
5
+ * Created and released into the public domain by Eli Biham
6
+ *
7
+ * $Id: tiger.c,v 1.2 2006/11/16 11:21:20 chugunov Exp $
8
+ */
9
+ #include "tiger.h"
10
+
11
+ #ifdef _WIN32
12
+ #undef WORDS_BIGENDIAN
13
+ #else
14
+ #endif
15
+
16
+ #define _ULL(x) x##ull
17
+
18
+ #ifdef WORDS_BIGENDIAN
19
+ # define USE_BIG_ENDIAN 1
20
+ #else
21
+ # define USE_BIG_ENDIAN 0
22
+ #endif
23
+
24
+ /* The following macro denotes that an optimization */
25
+ /* for Alpha is required. It is used only for */
26
+ /* optimization of time. Otherwise it does nothing. */
27
+ #ifdef __alpha
28
+ #define OPTIMIZE_FOR_ALPHA
29
+ #endif
30
+
31
+ /* NOTE that this code is NOT FULLY OPTIMIZED for any */
32
+ /* machine. Assembly code might be much faster on some */
33
+ /* machines, especially if the code is compiled with */
34
+ /* gcc. */
35
+
36
+ /* The number of passes of the hash function. */
37
+ /* Three passes are recommended. */
38
+ /* Use four passes when you need extra security. */
39
+ /* Must be at least three. */
40
+ #define PASSES 3
41
+
42
+ extern word64 table[4*256];
43
+
44
+ #define t1 (table)
45
+ #define t2 (table+256)
46
+ #define t3 (table+256*2)
47
+ #define t4 (table+256*3)
48
+
49
+ #define save_abc \
50
+ aa = a; \
51
+ bb = b; \
52
+ cc = c;
53
+
54
+ #ifdef OPTIMIZE_FOR_ALPHA
55
+ /* This is the official definition of round */
56
+ #define round(a,b,c,x,mul) \
57
+ c ^= x; \
58
+ a -= t1[((c)>>(0*8))&0xFF] ^ t2[((c)>>(2*8))&0xFF] ^ \
59
+ t3[((c)>>(4*8))&0xFF] ^ t4[((c)>>(6*8))&0xFF] ; \
60
+ b += t4[((c)>>(1*8))&0xFF] ^ t3[((c)>>(3*8))&0xFF] ^ \
61
+ t2[((c)>>(5*8))&0xFF] ^ t1[((c)>>(7*8))&0xFF] ; \
62
+ b *= mul;
63
+ #else
64
+ /* This code works faster when compiled on 32-bit machines */
65
+ /* (but works slower on Alpha) */
66
+ #define round(a,b,c,x,mul) \
67
+ c ^= x; \
68
+ a -= t1[(byte)(c)] ^ \
69
+ t2[(byte)(((word32)(c))>>(2*8))] ^ \
70
+ t3[(byte)((c)>>(4*8))] ^ \
71
+ t4[(byte)(((word32)((c)>>(4*8)))>>(2*8))] ; \
72
+ b += t4[(byte)(((word32)(c))>>(1*8))] ^ \
73
+ t3[(byte)(((word32)(c))>>(3*8))] ^ \
74
+ t2[(byte)(((word32)((c)>>(4*8)))>>(1*8))] ^ \
75
+ t1[(byte)(((word32)((c)>>(4*8)))>>(3*8))]; \
76
+ b *= mul;
77
+ #endif
78
+
79
+ #define pass(a,b,c,mul) \
80
+ round(a,b,c,x0,mul) \
81
+ round(b,c,a,x1,mul) \
82
+ round(c,a,b,x2,mul) \
83
+ round(a,b,c,x3,mul) \
84
+ round(b,c,a,x4,mul) \
85
+ round(c,a,b,x5,mul) \
86
+ round(a,b,c,x6,mul) \
87
+ round(b,c,a,x7,mul)
88
+
89
+ #define key_schedule \
90
+ x0 -= x7 ^ _ULL(0xA5A5A5A5A5A5A5A5); \
91
+ x1 ^= x0; \
92
+ x2 += x1; \
93
+ x3 -= x2 ^ ((~x1)<<19); \
94
+ x4 ^= x3; \
95
+ x5 += x4; \
96
+ x6 -= x5 ^ ((~x4)>>23); \
97
+ x7 ^= x6; \
98
+ x0 += x7; \
99
+ x1 -= x0 ^ ((~x7)<<19); \
100
+ x2 ^= x1; \
101
+ x3 += x2; \
102
+ x4 -= x3 ^ ((~x2)>>23); \
103
+ x5 ^= x4; \
104
+ x6 += x5; \
105
+ x7 -= x6 ^ _ULL(0x0123456789ABCDEF);
106
+
107
+ #define feedforward \
108
+ a ^= aa; \
109
+ b -= bb; \
110
+ c += cc;
111
+
112
+ #ifdef OPTIMIZE_FOR_ALPHA
113
+ /* The loop is unrolled: works better on Alpha */
114
+ #define compress \
115
+ save_abc \
116
+ pass(a,b,c,5) \
117
+ key_schedule \
118
+ pass(c,a,b,7) \
119
+ key_schedule \
120
+ pass(b,c,a,9) \
121
+ for(pass_no=3; pass_no<PASSES; pass_no++) { \
122
+ key_schedule \
123
+ pass(a,b,c,9) \
124
+ tmpa=a; a=c; c=b; b=tmpa;} \
125
+ feedforward
126
+ #else
127
+ /* loop: works better on PC and Sun (smaller cache?) */
128
+ #define compress \
129
+ save_abc \
130
+ for(pass_no=0; pass_no<PASSES; pass_no++) { \
131
+ if(pass_no != 0) {key_schedule} \
132
+ pass(a,b,c,(pass_no==0?5:pass_no==1?7:9)); \
133
+ tmpa=a; a=c; c=b; b=tmpa;} \
134
+ feedforward
135
+ #endif
136
+
137
+ /*
138
+ #define tiger_compress_macro(str, state) \
139
+ { \
140
+ register word64 a, b, c, tmpa; \
141
+ word64 aa, bb, cc; \
142
+ register word64 x0, x1, x2, x3, x4, x5, x6, x7; \
143
+ register word32 i; \
144
+ int pass_no; \
145
+ \
146
+ a = state[0]; \
147
+ b = state[1]; \
148
+ c = state[2]; \
149
+ \
150
+ x0=str[0]; x1=str[1]; x2=str[2]; x3=str[3]; \
151
+ x4=str[4]; x5=str[5]; x6=str[6]; x7=str[7]; \
152
+ \
153
+ compress; \
154
+ \
155
+ state[0] = a; \
156
+ state[1] = b; \
157
+ state[2] = c; \
158
+ }
159
+ */
160
+
161
+ #define tiger_compress_macro(str, state) \
162
+ { \
163
+ register word64 a, b, c, tmpa; \
164
+ word64 aa, bb, cc; \
165
+ register word64 x0, x1, x2, x3, x4, x5, x6, x7; \
166
+ int pass_no; \
167
+ \
168
+ a = state[0]; \
169
+ b = state[1]; \
170
+ c = state[2]; \
171
+ \
172
+ x0=str[0]; x1=str[1]; x2=str[2]; x3=str[3]; \
173
+ x4=str[4]; x5=str[5]; x6=str[6]; x7=str[7]; \
174
+ \
175
+ compress; \
176
+ \
177
+ state[0] = a; \
178
+ state[1] = b; \
179
+ state[2] = c; \
180
+ }
181
+
182
+ /* The compress function is a function. Requires smaller cache? */
183
+ void tiger_compress(word64 *str, word64 state[3])
184
+ {
185
+ tiger_compress_macro(((word64*)str), ((word64*)state));
186
+ }
187
+
188
+ #ifdef OPTIMIZE_FOR_ALPHA
189
+ /* The compress function is inlined: works better on Alpha. */
190
+ /* Still leaves the function above in the code, in case some other */
191
+ /* module calls it directly. */
192
+ #define tiger_compress(str, state) \
193
+ tiger_compress_macro(((word64*)str), ((word64*)state))
194
+ #endif
195
+
196
+ void tiger(word64 *str, word64 length, word64 res[3])
197
+ {
198
+ register word64 i, j;
199
+ unsigned char temp[64];
200
+
201
+ res[0]=_ULL(0x0123456789ABCDEF);
202
+ res[1]=_ULL(0xFEDCBA9876543210);
203
+ res[2]=_ULL(0xF096A5B4C3B2E187);
204
+
205
+ for(i=length; i>=64; i-=64)
206
+ {
207
+ #if USE_BIG_ENDIAN
208
+ for(j=0; j<64; j++)
209
+ temp[j^7] = ((byte*)str)[j];
210
+ tiger_compress(((word64*)temp), res);
211
+ #else
212
+ tiger_compress(str, res);
213
+ #endif
214
+ str += 8;
215
+ }
216
+
217
+ #if USE_BIG_ENDIAN
218
+ for(j=0; j<i; j++)
219
+ temp[j^7] = ((byte*)str)[j];
220
+
221
+ temp[j^7] = 0x01;
222
+ j++;
223
+ for(; j&7; j++)
224
+ temp[j^7] = 0;
225
+ #else
226
+ for(j=0; j<i; j++)
227
+ temp[j] = ((byte*)str)[j];
228
+
229
+ temp[j++] = 0x01;
230
+ for(; j&7; j++)
231
+ temp[j] = 0;
232
+ #endif
233
+ if(j>56)
234
+ {
235
+ for(; j<64; j++)
236
+ temp[j] = 0;
237
+ tiger_compress(((word64*)temp), res);
238
+ j=0;
239
+ }
240
+
241
+ for(; j<56; j++)
242
+ temp[j] = 0;
243
+ ((word64*)(&(temp[56])))[0] = ((word64)length)<<3;
244
+ tiger_compress(((word64*)temp), res);
245
+ }
data/ext/fargo/tiger.h ADDED
@@ -0,0 +1,41 @@
1
+ /* (PD) 2001 The Bitzi Corporation
2
+ * Please see file COPYING or http://bitzi.com/publicdomain
3
+ * for more info.
4
+ *
5
+ * $Id: tiger.h,v 1.1 2006/11/16 11:21:20 chugunov Exp $
6
+ */
7
+ #ifndef TIGER_H
8
+ #define TIGER_H
9
+
10
+ #ifdef _WIN32
11
+
12
+ #if defined (_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS >= 64)
13
+ typedef unsigned __int64 word64;
14
+ #else
15
+ #error __int64 type not supported
16
+ #endif
17
+ typedef unsigned long int tword;
18
+
19
+ #else
20
+ #include <sys/types.h>
21
+ typedef u_int64_t word64;
22
+ typedef u_int32_t word32;
23
+ typedef u_int16_t word16;
24
+ #endif
25
+
26
+ #ifndef __BYTE__
27
+ #define __BYTE__
28
+ typedef unsigned char byte;
29
+ #endif
30
+
31
+ #if defined(__cplusplus)
32
+ extern "C" {
33
+ #endif
34
+
35
+ void tiger(word64 *str, word64 length, word64 *res);
36
+
37
+ #if defined(__cplusplus)
38
+ }
39
+ #endif
40
+
41
+ #endif
@@ -0,0 +1,184 @@
1
+ /* (PD) 2001 The Bitzi Corporation
2
+ * Copyright (C) 2006 Alexey Illarionov <littlesavage@rambler.ru>
3
+ *
4
+ * Please see file COPYING or http://bitzi.com/publicdomain
5
+ * for more info.
6
+ *
7
+ * tigertree.c - Implementation of the TigerTree algorithm
8
+ *
9
+ * NOTE: The TigerTree hash value cannot be calculated using a
10
+ * constant amount of memory; rather, the memory required grows
11
+ * with the size of input. (Roughly, one more interim value must
12
+ * be remembered for each doubling of the input size.) The
13
+ * default TT_CONTEXT struct size reserves enough memory for
14
+ * input up to 2^64 in length
15
+ *
16
+ * Requires the tiger() function as defined in the reference
17
+ * implementation provided by the creators of the Tiger
18
+ * algorithm. See
19
+ *
20
+ * http://www.cs.technion.ac.il/~biham/Reports/Tiger/
21
+ *
22
+ */
23
+
24
+ #include <assert.h>
25
+ #include <string.h>
26
+ #include "tigertree.h"
27
+
28
+ //#define _TRACE
29
+ #if defined(_TRACE)
30
+ #include <stdio.h>
31
+ #define TRACE(x) printf x; fflush(stdout);
32
+ #else
33
+ #define TRACE(x)
34
+ #endif
35
+
36
+ #ifdef _WIN32
37
+ #undef WORDS_BIGENDIAN
38
+ #else
39
+ #endif
40
+
41
+ #ifdef WORDS_BIGENDIAN
42
+ # define USE_BIG_ENDIAN 1
43
+ void tt_endian(byte *s);
44
+ #else
45
+ # define USE_BIG_ENDIAN 0
46
+ #endif
47
+
48
+ /* Initialize the tigertree context */
49
+ void tt_init(TT_CONTEXT *ctx, unsigned char *tthl, unsigned depth)
50
+ {
51
+ ctx->count = 0;
52
+ ctx->node[0] = '\1'; // flag for inner node calculation -- never changed
53
+ ctx->index = 0; // partial block pointer/block length
54
+ ctx->top = ctx->nodes;
55
+ ctx->tthl = tthl;
56
+ ctx->depth = depth;
57
+ }
58
+
59
+ static void tt_compose(TT_CONTEXT *ctx) {
60
+ byte *node = ctx->top - NODESIZE;
61
+ memmove((ctx->node)+1,node,NODESIZE); // copy to scratch area
62
+ tiger((word64*)(ctx->node),(word64)(NODESIZE+1),(word64*)(ctx->top)); // combine two nodes
63
+ #if USE_BIG_ENDIAN
64
+ tt_endian((byte *)ctx->top);
65
+ #endif
66
+ memmove(node,ctx->top,TIGERSIZE); // move up result
67
+ ctx->top -= TIGERSIZE; // update top ptr
68
+ }
69
+
70
+ void tt_block(TT_CONTEXT *ctx)
71
+ {
72
+ word64 b;
73
+ unsigned depth;
74
+
75
+ tiger((word64*)ctx->leaf,(word64)ctx->index+1,(word64*)ctx->top);
76
+ #if USE_BIG_ENDIAN
77
+ tt_endian((byte *)ctx->top);
78
+ #endif
79
+ ctx->top += TIGERSIZE;
80
+ ++ctx->count;
81
+ b = ctx->count;
82
+ depth = 0;
83
+ while(b == ((b >> 1)<<1)) { // while evenly divisible by 2...
84
+ /*
85
+ if (depth == ctx->depth) {
86
+ TRACE(("depth = %d, b == %lld\n", depth, b));
87
+ memmove(ctx->tthl, ctx->top - 2*TIGERSIZE, 2*TIGERSIZE);
88
+ ctx->tthl += 2*TIGERSIZE;
89
+ }
90
+ */
91
+ tt_compose(ctx);
92
+ b = b >> 1;
93
+ depth++;
94
+ }
95
+ }
96
+
97
+ // no need to call this directly; tt_digest calls it for you
98
+ static void tt_final(TT_CONTEXT *ctx)
99
+ {
100
+ // do last partial block, unless index is 1 (empty leaf)
101
+ // AND we're past the first block
102
+ if((ctx->index>0)||(ctx->top==ctx->nodes))
103
+ tt_block(ctx);
104
+ }
105
+
106
+ void tt_digest(TT_CONTEXT *ctx, byte *s)
107
+ {
108
+ unsigned dth_top0 = 0, dth_top1 = 0;
109
+ word64 tmp, cnt;
110
+ tt_final(ctx);
111
+
112
+ /*
113
+ dth_top0 = 0;
114
+ cnt = ctx->count;
115
+ tmp = cnt;
116
+ while(tmp == ((tmp >> 1)<<1)) {
117
+ dth_top0++;
118
+ tmp >>= 1;
119
+ }
120
+ cnt -= ((word64)1 << dth_top0);
121
+
122
+ TRACE(("ctx->top-TIGERSIZE - ctx->nodes == %d\n", ctx->top-TIGERSIZE - ctx->nodes));
123
+ */
124
+
125
+ while( (ctx->top-TIGERSIZE) > ctx->nodes) {
126
+ /*
127
+ assert(cnt > 0);
128
+
129
+ dth_top1 = 0;
130
+ tmp = cnt;
131
+ while (tmp == ((tmp >> 1)<<1)) {
132
+ dth_top1++;
133
+ tmp >>= 1;
134
+ }
135
+ cnt -= ((word64)1 << dth_top1);
136
+
137
+ if ((ctx->depth <= dth_top1) && (ctx->depth >= dth_top0)) {
138
+ if ( dth_top1 == ctx->depth) {
139
+ TRACE(("depth = %d, dth_top0 == %d, dth_top1 == %d\n", ctx->depth, dth_top0, dth_top1));
140
+ memmove(ctx->tthl, ctx->top - 2*TIGERSIZE, 2*TIGERSIZE);
141
+ ctx->tthl += 2*TIGERSIZE;
142
+ } else {
143
+ TRACE(("depth = %d, dth_top0 == %d, dth_top1 == %d\n", ctx->depth, dth_top0, dth_top1));
144
+ memmove(ctx->tthl, ctx->top - TIGERSIZE, TIGERSIZE);
145
+ ctx->tthl += TIGERSIZE;
146
+ }
147
+ }
148
+ */
149
+ tt_compose(ctx);
150
+ dth_top0 = dth_top1 + 1;
151
+ }
152
+
153
+ memmove(s,ctx->nodes, TIGERSIZE);
154
+ }
155
+
156
+ #if USE_BIG_ENDIAN
157
+ void tt_endian(byte *s)
158
+ {
159
+ word64 *i;
160
+ byte *b, btemp;
161
+ word16 *w, wtemp;
162
+
163
+ for(w = (word16 *)s; w < ((word16 *)s) + 12; w++)
164
+ {
165
+ b = (byte *)w;
166
+ btemp = *b;
167
+ *b = *(b + 1);
168
+ *(b + 1) = btemp;
169
+ }
170
+
171
+ for(i = (word64 *)s; i < ((word64 *)s) + 3; i++)
172
+ {
173
+ w = (word16 *)i;
174
+
175
+ wtemp = *w;
176
+ *w = *(w + 3);
177
+ *(w + 3) = wtemp;
178
+
179
+ wtemp = *(w + 1);
180
+ *(w + 1) = *(w + 2);
181
+ *(w + 2) = wtemp;
182
+ }
183
+ }
184
+ #endif
@@ -0,0 +1,48 @@
1
+ /* (PD) 2001 The Bitzi Corporation
2
+ * Copyright (C) 2006 Alexey Illarionov <littlesavage@rambler.ru>
3
+ * Please see file COPYING or http://bitzi.com/publicdomain
4
+ * for more info.
5
+ *
6
+ */
7
+ #include "tiger.h"
8
+
9
+ /* tiger hash result size, in bytes */
10
+ #define TIGERSIZE 24
11
+
12
+ /* size of each block independently tiger-hashed, not counting leaf 0x00 prefix */
13
+ #define BLOCKSIZE 1024
14
+
15
+ /* size of input to each non-leaf hash-tree node, not counting node 0x01 prefix */
16
+ #define NODESIZE (TIGERSIZE*2)
17
+
18
+ /* default size of interim values stack, in TIGERSIZE
19
+ * blocks. If this overflows (as it will for input
20
+ * longer than 2^64 in size), havoc may ensue. */
21
+ #define STACKSIZE TIGERSIZE*56
22
+
23
+ typedef struct tt_context {
24
+ word64 count; /* total blocks processed */
25
+ #if 0
26
+ unsigned char leaf[1+BLOCKSIZE]; /* leaf in progress */
27
+ unsigned char *block; /* leaf data */
28
+ #endif
29
+ unsigned char *leaf; /* leaf in progress */
30
+ unsigned char node[1+NODESIZE]; /* node scratch space */
31
+ int index; /* index into block */
32
+ unsigned char *top; /* top (next empty) stack slot */
33
+ unsigned char *tthl; /* index into buf for tth leaves */
34
+ unsigned depth; /* num of generations in tree to discard */
35
+ unsigned char nodes[STACKSIZE]; /* stack of interim node values */
36
+ } TT_CONTEXT;
37
+
38
+ #if defined(__cplusplus)
39
+ extern "C" {
40
+ #endif
41
+ void tt_init(TT_CONTEXT *ctx, unsigned char *tthl, unsigned depth);
42
+ //void tt_update(TT_CONTEXT *ctx, unsigned char *buffer, word32 len);
43
+ void tt_block(TT_CONTEXT *ctx);
44
+ void tt_digest(TT_CONTEXT *ctx, unsigned char *hash);
45
+ void tt_copy(TT_CONTEXT *dest, TT_CONTEXT *src);
46
+ #if defined(__cplusplus)
47
+ }
48
+ #endif
data/ext/fargo/tth.c ADDED
@@ -0,0 +1,100 @@
1
+ /*
2
+ * tth.c
3
+ * This file is part of microdc
4
+ *
5
+ * Copyright (C) 2006 Alexey Illarionov <littlesavage@rambler.ru>
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU Library General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License along
18
+ * with this program; if not, write to the Free Software Foundation,
19
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
+ */
21
+
22
+ #include <sys/types.h>
23
+ #include <sys/stat.h>
24
+ #include <fcntl.h>
25
+ #include <unistd.h>
26
+ #include <stdio.h>
27
+ #include <stdlib.h>
28
+ #include <string.h>
29
+
30
+ #include "tigertree.h"
31
+ #include "base32.h"
32
+
33
+ //#define _TRACE
34
+ #if defined(_TRACE)
35
+ #define TRACE(x) printf x; fflush(stdout);
36
+ #else
37
+ #define TRACE(x)
38
+ #endif
39
+
40
+ const size_t default_block_level = 6;
41
+ const int max_block_count = (1 << 6);
42
+
43
+ #define MAXHASHES ( ((word64)1) << 9 )
44
+ /* blocksize for one leaf is 65536 bytes */
45
+ #define STARTDEPTH 6
46
+
47
+ int calc_block_level(word64 filesize, int max_block_count)
48
+ {
49
+ int level;
50
+ for (level = default_block_level; (((word64)1) << (level+10)) * max_block_count < filesize; level++);
51
+ return level;
52
+ }
53
+
54
+ char* tth(const char* filename, char **tthl, size_t *tthl_len)
55
+ {
56
+ char *tth;
57
+ size_t numbytes;
58
+ unsigned char root[24];
59
+ unsigned char *cur;
60
+ TT_CONTEXT tt;
61
+ unsigned char buf[1 + 512 * BLOCKSIZE];
62
+ struct stat sb;
63
+ unsigned level;
64
+ size_t leaf_blocksize;
65
+
66
+ int fd = open(filename, O_RDONLY);
67
+ if ((fd == -1) || ( fstat(fd, &sb) == -1)) {
68
+ return NULL;
69
+ }
70
+
71
+ level = calc_block_level(sb.st_size, max_block_count);
72
+ leaf_blocksize = 1 << (level+10);
73
+
74
+ *tthl_len = 0;
75
+ *tthl = NULL;
76
+
77
+ tt_init(&tt, *tthl, level);
78
+ tt.leaf = buf;
79
+ buf[0] = '\0';
80
+
81
+ while ( (numbytes = read(fd, &buf[1], sizeof(buf) - 1) ) > 0) {
82
+ tt.index = BLOCKSIZE;
83
+ for (cur = &buf[1]; cur + BLOCKSIZE <= &buf[numbytes + 1]; cur += BLOCKSIZE) {
84
+ tt.leaf = cur - 1;
85
+ tt.leaf[0] = '\0';
86
+ tt_block(&tt);
87
+ }
88
+ tt.index = numbytes - (cur - &buf[1]);
89
+ tt.leaf = cur - 1;
90
+ tt.leaf[0] = '\0';
91
+ }
92
+
93
+ close(fd);
94
+
95
+ tt_digest(&tt, root);
96
+
97
+ tth = base32_encode(root, sizeof(root));
98
+
99
+ return tth;
100
+ }
data/ext/fargo/tth.h ADDED
@@ -0,0 +1,18 @@
1
+ #ifndef __TTH_H
2
+ #define __TTH_H
3
+
4
+ #include "tiger.h"
5
+
6
+ #if defined(__cplusplus)
7
+ extern "C" {
8
+ #endif
9
+
10
+ // user must call free() funtion on pointer returned from these functions
11
+
12
+ char* tth(const char* filename, char **tthl, size_t *tthl_len);
13
+
14
+ #if defined(__cplusplus)
15
+ }
16
+ #endif
17
+
18
+ #endif // ifndef __TTH_H