From: alex Date: Sat, 30 Oct 2021 00:08:46 +0000 (-0700) Subject: ... X-Git-Url: http://git.infiniteadaptability.org/?a=commitdiff_plain;h=dd5a57e0d93d9d231577c02c8d843003fce89122;p=seeder ... --- diff --git a/Makefile.am b/Makefile.am index 90c8c4e..16073d3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,6 +15,7 @@ seederd_SOURCES = \ src/add.c \ src/bencode/decode.c \ src/bencode/encode.c \ + src/block.c \ src/default.c \ src/file.c \ src/hash.c \ @@ -47,6 +48,7 @@ seederd_SOURCES = \ seederd_SOURCES += \ inc/add.h \ inc/bencode.h \ + inc/block.h \ inc/default.h \ inc/file.h \ inc/hash.h \ diff --git a/inc/block.h b/inc/block.h new file mode 100644 index 0000000..9bde2bf --- /dev/null +++ b/inc/block.h @@ -0,0 +1,21 @@ +#ifndef __BLOCK_H_ +#define __BLOCK_H_ + +#include + +#define BLOCK_SIZE 16384 + +struct block { + uint8_t *data; + unsigned char hash[crypto_hash_sha256_BYTES]; + struct block *next; +}; + +int block_append_blank(struct block*); +int block_duplicate(struct block**,struct block*); +void block_free(struct block*); +int block_init(struct block**); +size_t block_length(struct block*); +int block_merkle_root(struct block*); + +#endif diff --git a/inc/file.h b/inc/file.h index ac254b0..28501ee 100644 --- a/inc/file.h +++ b/inc/file.h @@ -8,10 +8,14 @@ #include +#define FILE_MESSAGE_FREAD_FAILED "failed to read file: %s\n" + struct file { char *name; char *path; unsigned char root[crypto_hash_sha256_BYTES]; + struct block *blocks; + size_t size; }; void file_free(struct file*); diff --git a/src/block.c b/src/block.c new file mode 100644 index 0000000..5a3b51b --- /dev/null +++ b/src/block.c @@ -0,0 +1,98 @@ +#include + +int block_append_block(struct block *p) { + if(NULL==p) { return -1; } + + while(p->next!=NULL) { + p = p->next; + } + + if(block_init(&(p->next))<0) { return -1; } + memset(p->next->hash,0,crypto_hash_sha256_BYTES); + + return 1; +} + +int block_duplicate(struct block **p, struct block *to_dup) { + struct block *next; + + if(NULL==p) { return -1; } + if(NULL==to_dup) { return -1; } + + while(to_dup!=NULL) { + if(block_init(p)<0) { return -1; } + + memcpy((*p)->hash,to_dup->hash,crypto_hash_sha256_BYTES); + + (*p) = (*p)->next; + to_dup = to_dup->next; + } + + return 1; +} + +void block_free(struct block *p) { + struct block *next; + + while(p!=NULL) { + if(p->data!=NULL) { + free(p->data); + } + + next = p->next; + free(p); + p = next; + } +} + +int block_init(struct block **p) { + if(NULL==p) { return -1; } + + *p = malloc(sizeof(struct block)); + if(NULL==(*p)) { + perror("malloc"); + return -1; + } + + (*p)->data = NULL; + (*p)->next = NULL; + + return 1; +} + +size_t block_length(struct block *p) { + size_t i = 0; + while(p!=NULL) { + i++; + p = p->next; + } + + return i; +} + +int block_merkle_root(struct block *root) { + struct block *p, *to_free; + crypto_hash_sha256_state state; + + if(NULL==root) { return -1; } + + while(p!=NULL) { + if(NULL==p->next) { return -1; } + if(hash_init(&state)<0) { return -1; } + + if(hash_update(&state,p->hash,crypto_hash_sha256_BYTES)<0) { return -1; } + if(hash_update(&state,p->next->hash,crypto_hash_sha256_BYTES)<0) { return -1; } + + if(hash_final(&state,p->hash,crypto_hash_sha256_BYTES)<0) { return -1; } + + to_free = p->next; + p = p->next->next; + block_free(to_free); + + if((NULL==p)&&(p!=root)) { + p = root; + } + } + + return 1; +} diff --git a/src/file.c b/src/file.c index 009d11b..13c191f 100644 --- a/src/file.c +++ b/src/file.c @@ -14,8 +14,75 @@ void file_free(struct file *p) { free(p); } -int file_hash(struct file *p) { +int file_hash(struct file *file_p) { + uint8_t data[BLOCK_SIZE]; + struct block *start, *p, *next, *end; + FILE *fp; + int blocks_per_piece; + + blocks_per_piece = global_opts.piece_length / BLOCK_SIZE; + + fp = fopen(file_p->path,"rb"); + if(NULL==fp) { return -1; } + + while(1) { + if(block_init(&start)<0) { goto clean; } + p = start; + for(size_t i=0;ipath); + goto clean; + } + + if(len==0) { break; } + + file_p->size += len; + + if(block_init(&next)<0) { goto clean; } + if(hash(data,len,next->hash,crypto_hash_sha256_BYTES)<0) { goto clean; } + + p->next = next; + p = p->next; + } + + ssize_t blocks = block_length(start); + if(blocks<=0) { goto clean; } + + if(blocks!=blocks_per_piece) { + // if the file is smaller than one piece then the block hashes + // should be padded to the next power of two instead of the next + // piece boundary + size_t leaves_required = next_power_2(blocks); + while(leaves_required>0) { + if(block_append_blank(start)<0) { goto clean; } + leaves_required--; + } + } + + if(block_merkle_root(start)<0) { goto clean; } + + if(NULL==file_p->blocks) { + file_p->blocks = start; + end = start; + } + + end->next = start; + end = end->next; + } + + fclose(fp); + + if(block_duplicate(&start,file_p->blocks)<0) { return -1; } + if(block_merkle_root(start)<0) { return -1; } + memcpy(file_p->root,start->hash,crypto_hash_sha256_BYTES); + block_free(start); + return 1; +clean: + block_free(start); + fclose(fp); } int file_init(struct file **p, const char *path) { @@ -36,6 +103,8 @@ int file_init(struct file **p, const char *path) { (*p)->name = strdup(b); memset((*p)->root,0,crypto_hash_sha256_BYTES); + (*p)->blocks = NULL; + (*p)->size = 0; return 1; }