src/torrent/info.c \
src/torrent/init.c \
src/torrent/magnet.c \
+ src/torrent/path.c \
src/torrent/piece.c \
src/tree.c \
src/usage.c \
};
int torrent_add(struct torrent*,struct file*);
-int torrent_file(struct torrent*);
+int torrent_file(const char*,struct torrent*);
ssize_t torrent_file_info(struct torrent*,uint8_t**);
-char *torrent_file_path(unsigned char*,size_t);
+char *torrent_file_path(const char*,unsigned char*,size_t);
int torrent_file_piece_layers(FILE*,struct torrent*);
void torrent_free(struct torrent*);
int torrent_init(struct torrent**,const char*,const char*,unsigned long long);
static int torrent_file_write_piece_layers(FILE*,struct torrent*);
static int torrent_file_write_start(FILE*);
-int torrent_file(struct torrent *torrent_p) {
+int torrent_file(const char *datadir, struct torrent *torrent_p) {
uint8_t *info;
FILE *fp;
unsigned char infohash[crypto_hash_sha256_BYTES];
fp = NULL;
path = NULL;
+ if(NULL==datadir) { goto clean; }
+ if(is_directory(datadir)<0) { goto clean; }
+
if((i = torrent_file_info(torrent_p,&info))<0) { goto clean; }
if(hash(info,i,infohash,crypto_hash_sha256_BYTES)<0) { goto clean; }
- path = torrent_file_path(infohash,crypto_hash_sha256_BYTES);
+ path = torrent_file_path(datadir,infohash,crypto_hash_sha256_BYTES);
if(NULL==path) { goto clean; }
fp = fopen(path,"w");
info = NULL;
if(torrent_file_write_piece_layers(fp,torrent_p)<0) { goto clean; }
+
if(torrent_file_write_end(fp)<0) { goto clean; }
fclose(fp);
+
+ // must be done last because of remove() in cleanup
free(path);
return 1;
return -1;
}
+#define ANNOUNCE_SAMPLE_SIZE 50
+
static int torrent_file_announce(FILE *fp, struct torrent *p) {
- uint8_t buf[28];
+ uint8_t buf[ANNOUNCE_SAMPLE_SIZE];
ssize_t i;
uint8_t announce_string[] = "announce";
- if((i = bencode_string(announce_string,sizeof(announce_string),buf,28))<0) { return -1; }
+ if((i = bencode_string(announce_string,sizeof(announce_string)-1,buf,ANNOUNCE_SAMPLE_SIZE))<0) { return -1; }
if(i!=fwrite(buf,sizeof(uint8_t),i,fp)) { return -1; }
uint8_t announce_sample_string[] = "http://example.com/announce";
- if((i = bencode_string(announce_sample_string,sizeof(announce_sample_string),buf,28))<0) { return -1; }
+ if((i = bencode_string(announce_sample_string,sizeof(announce_sample_string)-1,buf,ANNOUNCE_SAMPLE_SIZE))<0) { return -1; }
if(i!=fwrite(buf,sizeof(uint8_t),i,fp)) { return -1; }
return 1;
}
-#define TORRENT_FILE_DIRECTORY "/torrents"
-#define TORRENT_FILE_EXTENSION ".torrent"
-
-char *torrent_file_path(unsigned char *infohash, size_t len) {
- char *path, *p;
- char hex[(crypto_hash_sha256_BYTES<<1)+1];
-
- if(len!=crypto_hash_sha256_BYTES) { return NULL; }
-
- // this always returns hex, unnecessary to return
- sodium_bin2hex(hex,(crypto_hash_sha256_BYTES<<1)+1,infohash,crypto_hash_sha256_BYTES);
-
- p = concat(TORRENT_FILE_DIRECTORY,hex);
- if(NULL==p) { return NULL; }
-
- path = malloc(strlen(p)+strlen(".torrent")+1);
- if(NULL==path) {
- free(p);
- return NULL;
- }
-
- if(sprintf(path,"%s" TORRENT_FILE_EXTENSION,p)<0) {
- free(p);
- free(path);
- return NULL;
- }
-
- free(p);
-
- return path;
-}
-
static int torrent_file_write_end(FILE *fp) {
uint8_t c;
ssize_t i;
uint8_t buf[6];
ssize_t i;
- if((i = bencode_string(info_string,sizeof(info_string),buf,6))<0) { return -1; }
+ if((i = bencode_string(info_string,sizeof(info_string)-1,buf,6))<0) { return -1; }
if(i!=fwrite(buf,sizeof(uint8_t),i,fp)) { return -1; }
if(info_len!=fwrite(info,sizeof(uint8_t),info_len,fp)) { return -1; }
uint8_t buf[15];
ssize_t i;
- if((i = bencode_string(piece_layers_string,sizeof(piece_layers_string),buf,15))<0) { return -1; }
+ if((i = bencode_string(piece_layers_string,sizeof(piece_layers_string)-1,buf,15))<0) { return -1; }
if(i!=fwrite(buf,sizeof(uint8_t),i,fp)) { return -1; }
+ if(torrent_file_write_start(fp)<0) { return -1; }
if(torrent_file_piece_layers(fp,p)<0) { return -1; }
+ if(torrent_file_write_end(fp)<0) { return -1; }
return 1;
}
--- /dev/null
+#include<torrent.h>
+
+#define TORRENT_FILE_DIRECTORY "/torrents"
+#define TORRENT_FILE_EXTENSION ".torrent"
+
+char *torrent_file_path(const char *prefix, unsigned char *infohash, size_t len) {
+ char *path, *p;
+ char hex[(crypto_hash_sha256_BYTES<<1)+1];
+
+ if(len!=crypto_hash_sha256_BYTES) { return NULL; }
+
+ // this always returns hex, unnecessary to return
+ sodium_bin2hex(hex,(crypto_hash_sha256_BYTES<<1)+1,infohash,crypto_hash_sha256_BYTES);
+
+ path = concat(prefix,TORRENT_FILE_DIRECTORY);
+ if(NULL==path) { return NULL; }
+
+ p = concat(path,hex);
+ free(path);
+ if(NULL==p) { return NULL; }
+
+ path = malloc(strlen(p)+strlen(".torrent")+1);
+ if(NULL==path) {
+ free(p);
+ return NULL;
+ }
+
+ if(sprintf(path,"%s" TORRENT_FILE_EXTENSION,p)<0) {
+ free(p);
+ free(path);
+ return NULL;
+ }
+
+ free(p);
+
+ return path;
+}
+
+
pieces = 0;
for(size_t i=0;i<p->files.roots->size;i++) {
file_p = (struct file*)p->files.roots->map[i];
- if(file_p!=NULL) { pieces++; }
+ if(file_p!=NULL) {
+ if(file_p->size>p->piece_length) { pieces++; }
+ }
}
hashes = malloc(sizeof(const unsigned char*)*pieces);
for(size_t i=0;i<p->files.roots->size;i++) {
file_p = (struct file*)p->files.roots->map[i];
if(file_p!=NULL) {
- hashes[index] = file_p->root;
- index++;
+ if(file_p->size>p->piece_length) {
+ hashes[index] = file_p->root;
+ index++;
+ }
}
}
$(top_srcdir)/src/block.c \
$(top_srcdir)/src/file.c \
$(top_srcdir)/src/fs/concat.c \
+ $(top_srcdir)/src/fs/dir.c \
$(top_srcdir)/src/hash.c \
$(top_srcdir)/src/hashmap.c \
$(top_srcdir)/src/torrent/add.c \
$(top_srcdir)/src/torrent/info.c \
$(top_srcdir)/src/torrent/init.c \
$(top_srcdir)/src/torrent/magnet.c \
+ $(top_srcdir)/src/torrent/path.c \
$(top_srcdir)/src/torrent/piece.c \
$(top_srcdir)/src/tree.c
srand(time(NULL));
create_test_directory(TEST_DIRECTORY);
+ create_test_directory(TEST_DIRECTORY "/torrents");
create_test_file(TEST_FILE_1,TEST_FILE_1_CONTENTS);
create_test_file(TEST_FILE_2,TEST_FILE_2_CONTENTS);
create_test_file(TEST_FILE_3,TEST_FILE_3_CONTENTS);
}
static void torrent_file_basic_test() {
- assert(1);
+ struct torrent *torrent;
+
+ torrent_setup_example(&torrent);
+
+ assert(1==torrent_file(TEST_DIRECTORY,torrent));
+
+ torrent_free(torrent);
}
static void torrent_file_info_basic_test() {
assert(memcmp(out,expected,crypto_hash_sha256_BYTES)==0);
- assert(torrent_file(torrent_p)==1);
+ assert(torrent_file(TEST_DIRECTORY,torrent_p)==1);
assert(sodium_hex2bin(expected,crypto_hash_sha256_BYTES,torrent_file_hash_expected,strlen(torrent_file_hash_expected),NULL,&i,NULL)==0);
assert(i==32);
char *p;
memset(infohash,0,crypto_hash_sha256_BYTES);
-
- p = torrent_file_path(NULL,0);
+ p = torrent_file_path(NULL,NULL,0);
assert(NULL==p);
- p = torrent_file_path(infohash,0);
+ p = torrent_file_path(TEST_DIRECTORY,infohash,0);
assert(NULL==p);
- p = torrent_file_path(infohash,23);
+ p = torrent_file_path(TEST_DIRECTORY,infohash,23);
assert(NULL==p);
- p = torrent_file_path(infohash,crypto_hash_sha256_BYTES);
- assert(strcmp(p,"/torrents/0000000000000000000000000000000000000000000000000000000000000000.torrent")==0);
+ p = torrent_file_path(TEST_DIRECTORY,infohash,crypto_hash_sha256_BYTES);
+ assert(strcmp(p,TEST_DIRECTORY "/torrents/0000000000000000000000000000000000000000000000000000000000000000.torrent")==0);
free(p);
}
struct torrent *torrent;
FILE *fp;
unsigned char hash[crypto_hash_sha256_BYTES];
- unsigned char expected[crypto_hash_sha256_BYTES] = {32,188,23,84,39,38,213,235,27,41,120,194,91,119,181,244,243,49,193,113,138,136,121,232,42,97,20,207,246,225,132,236};
+ unsigned char expected[crypto_hash_sha256_BYTES] = {227,176,196,66,152,252,28,20,154,251,244,200,153,111,185,36,39,174,65,228,100,155,147,76,164,149,153,27,120,82,184,85};
fp = fopen(TEST_FILE_6,"w");
assert(fp!=NULL);