#include<file.h>
+static int file_piece_layers(struct file *p, int piece_length);
+
void file_free(struct file *p) {
if(NULL==p) { return; }
uint8_t data[BLOCK_SIZE];
struct block *p, *next, *layer_p;
FILE *fp;
- size_t blocks;
- int ratio;
if(NULL==file_p) { return -1; }
return -1;
}
- blocks = 0;
- ratio = piece_length / BLOCK_SIZE;
-
- /* generate piece_layers
- * 1. grab all data and hash
- * 2. generate piece layer merkle trees (padding to piece layer boundary)
- * 3. generate merkle root from piece layer roots (balancing tree in process)
- */
p = NULL;
while(1) {
size_t len = fread(data,sizeof(uint8_t),BLOCK_SIZE,fp);
if(NULL==p) {
file_p->piece_layers = next;
p = next;
- layer_p = next;
} else {
p->next = next;
p = p->next;
}
+ }
- if(blocks%ratio==0) {
- layer_p = p;
- }
+ fclose(fp);
- blocks++;
+ // generate merkle root
+ if(block_duplicate(&p,file_p->piece_layers)<0) { return -1; }
+ if(block_length(p)>1) {
+ if(block_pad(p)<0) { goto clean; }
}
+ if(block_merkle_root(p)<0) { goto clean; }
+ memcpy(file_p->root,p->hash,crypto_hash_sha256_BYTES);
+ block_free(p);
+ if(file_piece_layers(file_p,piece_length)<0) { return -1; }
+
+ return 1;
+clean:
fclose(fp);
+ return -1;
+}
+
+static int file_piece_layers(struct file *p, int piece_length) {
+ int ratio;
- // pad to appropiate piece layer size
- // i.e. so each piece layer tree is balanced
- for(int i=1;i<=ratio;i<<=1) {
+ ratio = piece_length / BLOCK_SIZE;
+ return -1;
+ for(int i=1;i<ratio;i<<=1) {
if(block_pad(layer_p)<0) { return -1; }
}
ratio>>=1;
}
- if(block_duplicate(&p,file_p->piece_layers)<0) { return -1; }
- if(block_merkle_root(p)<0) { goto clean; }
-
- memcpy(file_p->root,p->hash,crypto_hash_sha256_BYTES);
- block_free(p);
-
return 1;
-clean:
- fclose(fp);
- return -1;
}
int file_init(struct file **p, const char *path) {
static void file_hash_large_file_test() {
struct file *p;
- unsigned char expected[crypto_hash_sha256_BYTES] = {100,239,196,122,239,43,229,105,216,75,220,175,222,60,41,21,90,14,137,169,54,216,172,179,234,56,139,100,139,66,216,238};
+ unsigned char expected[crypto_hash_sha256_BYTES] = {58,71,55,213,6,94,65,97,113,64,176,175,139,67,229,164,13,18,213,164,166,129,202,162,224,45,9,227,191,155,144,144};
extend_file(TEST_FILE_1);
static void file_hash_large_piece_test() {
struct file *p;
- unsigned char expected[crypto_hash_sha256_BYTES] = {84,58,164,117,149,227,209,117,101,168,163,50,36,135,253,15,112,185,149,168,191,58,216,233,94,59,199,17,199,48,28,68};
+ unsigned char expected[crypto_hash_sha256_BYTES] = {64,131,223,19,91,131,72,167,201,254,157,1,126,178,241,29,88,45,61,12,145,82,50,224,112,145,234,174,166,97,124,147};
- extend_file(TEST_FILE_2);
+ size_t blocks = 10001;
+ for(int i=16384;i<131073;i<<=1) {
+ extend_file(TEST_FILE_2);
- assert(1==file_init(&p,TEST_FILE_2));
- assert(file_hash(p,32768)==1);
- assert(memcmp(p->root,expected,crypto_hash_sha256_BYTES)==0);
- assert(5001==block_length(p->piece_layers));
- assert((10000*16384+26)==p->size);
-
- file_free(p);
-
- reset_env();
-
- extend_file(TEST_FILE_2);
-
- assert(1==file_init(&p,TEST_FILE_2));
- assert(file_hash(p,65536)==1);
- assert(memcmp(p->root,expected,crypto_hash_sha256_BYTES)==0);
- assert(2501==block_length(p->piece_layers));
- assert((10000*16384+26)==p->size);
-
- file_free(p);
+ assert(1==file_init(&p,TEST_FILE_2));
+ assert(file_hash(p,i)==1);
+ assert(memcmp(p->root,expected,crypto_hash_sha256_BYTES)==0);
+ assert(blocks==block_length(p->piece_layers));
+ assert((10000*16384+26)==p->size);
- reset_env();
-
- extend_file(TEST_FILE_2);
-
- assert(1==file_init(&p,TEST_FILE_2));
- assert(file_hash(p,131072)==1);
- assert(memcmp(p->root,expected,crypto_hash_sha256_BYTES)==0);
- assert(1251==block_length(p->piece_layers));
- assert((10000*16384+26)==p->size);
-
- file_free(p);
-
- reset_env();
+ file_free(p);
+ reset_env();
+ blocks >>= 1;
+ }
}
static void file_hash_random_file_test() {