swarmfile.c (4011B)
1 #include <stddef.h> 2 #include <string.h> 3 4 #include "def.h" 5 #include "endian.h" 6 #include "swarmfile.h" 7 8 static inline void filehash_callback(filehash_t *fctx, const unsigned char *hash, const unsigned char *data, const size_t data_length, const bmt_spansize_t span_size) { 9 if (fctx->callback != NULL) { 10 if (span_size < 0) { 11 (*fctx->callback)(hash, data, data_length + SWARM_DATA_LENGTH_TYPESIZE, fctx->callback_static); 12 } else { 13 unsigned char out_data[SWARM_BLOCK_SIZE + SWARM_DATA_LENGTH_TYPESIZE]; 14 memcpy(out_data, &span_size, SWARM_DATA_LENGTH_TYPESIZE); 15 to_endian(CONVERT_LITTLEENDIAN, SWARM_DATA_LENGTH_TYPESIZE, (unsigned char*)out_data); 16 memcpy(out_data + SWARM_DATA_LENGTH_TYPESIZE, data, data_length); 17 (*fctx->callback)(hash, out_data, data_length + SWARM_DATA_LENGTH_TYPESIZE, fctx->callback_static); 18 } 19 } 20 } 21 22 23 void filehash_reset(filehash_t *fctx) { 24 int i; 25 for (i = 0; i < SWARM_LEVELS; i++) { 26 fctx->ptr[i] = fctx->buf; 27 fctx->writes[i] = 0; 28 } 29 fctx->length = 0; 30 } 31 32 33 static bmt_spansize_t filehash_finalize_level(filehash_t *fctx, int level) { 34 bmt_t *bctx; 35 int l; 36 int r; 37 int next_level; 38 int blocks; 39 int blocks_span_length; 40 int remainder; 41 42 bctx = &fctx->bmt_context; 43 44 next_level = level + 1; 45 46 if (fctx->ptr[level] == fctx->target) { 47 return fctx->length; 48 } 49 50 l = fctx->ptr[level] - fctx->ptr[next_level]; 51 blocks = (l / SWARM_WORD_SIZE); 52 53 remainder = fctx->length % fctx->spans[level]; 54 55 if (blocks == 1) { 56 fctx->ptr[next_level] = fctx->ptr[level]; 57 return filehash_finalize_level(fctx, next_level); 58 } else { 59 blocks_span_length = (blocks - 1) * fctx->spans[level]; 60 if (remainder > 0) { 61 blocks_span_length += remainder; 62 } else { 63 blocks_span_length += fctx->spans[level]; 64 } 65 bmt_init(bctx, fctx->ptr[next_level], l, (bmt_spansize_t)(blocks_span_length)); 66 r = bmt_sum(bctx); 67 if (r != 0) { 68 return -1; 69 } 70 filehash_callback(fctx, bctx->buf, fctx->ptr[next_level], l, (bmt_spansize_t)(blocks_span_length)); 71 memcpy(fctx->ptr[next_level], bctx->buf, SWARM_WORD_SIZE); 72 fctx->ptr[next_level] += SWARM_WORD_SIZE; 73 } 74 return filehash_finalize_level(fctx, next_level); 75 } 76 77 78 bmt_spansize_t filehash_sum(filehash_t *fctx) { 79 return filehash_finalize_level(fctx, 0); 80 } 81 82 83 void filehash_init_callback(filehash_t *fctx, void (*callback)(const unsigned char*, const unsigned char*, const size_t, void*), void *callback_static) { 84 int i; 85 int l; 86 87 l = SWARM_BLOCK_SIZE; 88 89 for (i = 0; i < SWARM_LEVELS; i++) { 90 fctx->spans[i] = l; 91 l *= SWARM_BATCH_SIZE; 92 } 93 fctx->target = fctx->buf + SWARM_WORD_SIZE; 94 fctx->callback = callback; 95 fctx->callback_static = callback_static; 96 97 filehash_reset(fctx); 98 } 99 100 void filehash_init(filehash_t *fctx) { 101 return filehash_init_callback(fctx, NULL, NULL); 102 } 103 104 105 static int filehash_write_hash(filehash_t *fctx, int level, const unsigned char *data) { 106 bmt_t *bctx; 107 int next_level; 108 int r; 109 110 fctx->writes[level] += 1; 111 memcpy(fctx->ptr[level], data, SWARM_WORD_SIZE); 112 if (fctx->writes[level] % SWARM_BATCH_SIZE == 0) { 113 bctx = &fctx->bmt_context; 114 next_level = level + 1; 115 bmt_init(bctx, fctx->ptr[next_level], SWARM_BLOCK_SIZE, (long long)fctx->spans[next_level]); 116 r = bmt_sum(bctx); 117 if (r != 0) { 118 return -1; 119 } 120 filehash_callback(fctx, bctx->buf, fctx->ptr[next_level], SWARM_BLOCK_SIZE, (bmt_spansize_t)fctx->spans[next_level]); 121 r = filehash_write_hash(fctx, level + 1, bctx->buf); 122 if (r != 0) { 123 return -1; 124 } 125 fctx->ptr[level] = fctx->ptr[next_level]; 126 } else { 127 fctx->ptr[level] += SWARM_WORD_SIZE; 128 } 129 return 0; 130 } 131 132 int filehash_write(filehash_t *fctx, const unsigned char *data, const size_t data_length) { 133 bmt_t *bctx; 134 int r; 135 136 bctx = &fctx->bmt_context; 137 138 bmt_init(bctx, data, data_length, (long long)data_length); 139 r = bmt_sum(bctx); 140 if (r != 0) { 141 return -1; 142 } 143 filehash_callback(fctx, bctx->buf, data, data_length, (bmt_spansize_t)data_length); 144 r = filehash_write_hash(fctx, 0, bctx->buf); 145 if (r != 0) { 146 return -1; 147 } 148 fctx->length += data_length; 149 150 return data_length; 151 } 152 153