...
authoralex <[email protected]>
Fri, 3 Dec 2021 00:01:45 +0000 (16:01 -0800)
committeralex <[email protected]>
Fri, 3 Dec 2021 00:01:45 +0000 (16:01 -0800)
inc/torrent.h
src/opt/watch.c
src/torrent.c
src/tree.c
test/unit/Makefile.am
test/unit/torrent.tests.c
test/unit/tree.tests.c

index 65e354cec52ebe6bea9de0ddfe37c61dad3928f6..f67ed386d616968b843415fd0d719a9724d2c2f9 100644 (file)
@@ -7,6 +7,7 @@
 
 #include<bencode.h>
 #include<file.h>
+#include<fs.h>
 #include<hashmap.h>
 #include<opt.h>
 #include<tree.h>
 struct torrent {
        char *root;
        char *name;
+       
+       unsigned long long piece_length;
+
        struct tree *tree;
        struct hash_map *files;
+
        int watch_fd;
 };
 
@@ -23,7 +28,7 @@ int torrent_add(struct torrent*,struct file*);
 int torrent_file(struct torrent*);
 ssize_t torrent_file_info(struct torrent*,uint8_t**);
 void torrent_free(struct torrent*);
-int torrent_init(struct torrent**,const char*,const char*);
+int torrent_init(struct torrent**,const char*,const char*,unsigned long long);
 char *torrent_magnet(struct torrent*);
 
 #endif
index b057f6551897e0147eb6d006324bb4f900f146f3..e4842b15b4ddefb984dcf76579dc534c125f4e65 100644 (file)
@@ -12,7 +12,7 @@ int opt_add_watch(const char *directory) {
        name = strdup(directory);
        name = basename(name);
 
-       if(torrent_init(&p,directory,name)<0) { return -1; }
+       if(torrent_init(&p,directory,name,global_options.piece_length)<0) { return -1; }
        if(session_torrent_add(p)<0) { return -1; }
 
        log_msg(OPT_MESSAGE_WATCH_ADD_SUCCESS,p->root,p->name);
index 3c452a97994b0572ff1d78da2c426dbbbcf36e2e..e23aa1fd899be10dad405ede3f689169a50cb27c 100644 (file)
@@ -128,7 +128,7 @@ ssize_t torrent_file_info(struct torrent *torrent_p, uint8_t **buf) {
        uint8_t piece_length_string[] = "piece length";
        if((i = bencode_string(piece_length_string,sizeof(piece_length_string),&(p[len]),buf_len-len))<0) { goto clean; }
        len += i;
-       if((i = bencode_int(global_options.piece_length,&(p[len]),buf_len-len))<0) { goto clean; }
+       if((i = bencode_int(torrent_p->piece_length,&(p[len]),buf_len-len))<0) { goto clean; }
        len += i;
 
        *buf = malloc(len);
@@ -143,6 +143,7 @@ clean:
        return -1;
 }
 
+#define TORRENT_FILE_DIRECTORY "/torrents"
 #define TORRENT_FILE_EXTENSION ".torrent"
 
 static char *torrent_file_path(unsigned char *infohash, size_t len) {
@@ -154,7 +155,7 @@ static char *torrent_file_path(unsigned char *infohash, size_t len) {
        // this always returns hex, unnecessary to return
        sodium_bin2hex(hex,(crypto_hash_sha256_BYTES<<1)+1,infohash,crypto_hash_sha256_BYTES);
 
-       p = concat(PREFIX,hex);
+       p = concat(PREFIX TORRENT_FILE_DIRECTORY,hex);
        if(NULL==p) { return NULL; }
 
        path = malloc(strlen(p)+strlen(".torrent")+1);
@@ -244,11 +245,13 @@ void torrent_free(struct torrent *p) {
 
 #define TORRENT_FILES_HASHMAP_INITIAL_SIZE 8
 
-int torrent_init(struct torrent **torrent_p, const char *root, const char *name) {
+int torrent_init(struct torrent **torrent_p, const char *root, const char *name, unsigned long long piece_length) {
        if(NULL==torrent_p) { return -1; }
        if(NULL==root) { return -1; }
        if(NULL==name) { return -1; }
 
+       if((piece_length<16384)||(!(piece_length&&!(piece_length&(piece_length-1))))) { return -1; }
+
        *(torrent_p) = malloc(sizeof(struct torrent));
        if(NULL==(*torrent_p)) {
                perror("malloc");
@@ -261,6 +264,8 @@ int torrent_init(struct torrent **torrent_p, const char *root, const char *name)
        (*torrent_p)->name = strdup(name);
        if(NULL==(*torrent_p)->name) { goto clean; }
 
+       (*torrent_p)->piece_length = piece_length;
+
        if(tree_init(&((*torrent_p)->tree))<0) { goto clean; }
 
        if(hashmap_init(&((*torrent_p)->files),TORRENT_FILES_HASHMAP_INITIAL_SIZE)<0) { goto clean; }
index 4f2065a41e5fe983dc3d2a8ecc2c378f28b5f406..23bcaace9f130bdc838f4b76291b341efcda1e98 100644 (file)
@@ -146,7 +146,7 @@ int tree_entry_init(struct tree_entry **p, struct file *file) {
 
        (*p)->name = strdup(file->name);
        if(NULL==(*p)->name) {
-               free(p);
+               free(*p);
                return -1;
        }
 
@@ -158,6 +158,24 @@ int tree_entry_init(struct tree_entry **p, struct file *file) {
 };
 
 static int tree_entry_init_directory(struct tree_entry **p, const char *dirname) {
+       if(NULL==p) { return -1; }
+       if((NULL==dirname)||(0==strlen(dirname))) { return -1; }
+
+       (*p) = malloc(sizeof(struct tree_entry));
+       if(NULL==(*p)) { return -1; }
+
+       (*p)->name = NULL;
+       (*p)->file = NULL;
+       (*p)->next = NULL;
+
+       (*p)->name = strdup(dirname);
+       if(NULL==(*p)->name) { goto clean; }
+
+       if(tree_init(&((*p)->children))<0) { goto clean; }
+
+       return 1;
+clean:
+       if((*p)->name!=NULL) { free((*p)->name); }
        return -1;
 }
 
index 7fbe09ab00685c42758085f4407fc1b69c398ca5..17e239c7b66afd2e865ad5fd772ee9757fa8a6ed 100644 (file)
@@ -64,8 +64,10 @@ hashmap_tests_SOURCES = \
 torrent_tests_SOURCES = \
        $(common_SOURCES) \
        torrent.tests.c \
+       $(top_srcdir)/src/bencode/encode.c \
        $(top_srcdir)/src/block.c \
        $(top_srcdir)/src/file.c \
+       $(top_srcdir)/src/fs/concat.c \
        $(top_srcdir)/src/hash.c \
        $(top_srcdir)/src/hashmap.c \
        $(top_srcdir)/src/torrent.c \
index a81cfeca7a0a540f57f05ae0f325e9edc0d42230..38389c73bfaf27064dc89541248486cdc13555ab 100644 (file)
@@ -26,18 +26,17 @@ static void torrent_add_basic_test() {
        assert(file_init(&file3,TEST_FILE_3)==1);
        assert(file_init(&file4,TEST_FILE_4)==1);
 
-       assert(torrent_init(&torrent,TEST_DIRECTORY,TEST_DIRECTORY)==1);
+       assert(torrent_init(&torrent,TEST_DIRECTORY,TEST_DIRECTORY,16384)==1);
 
        assert(torrent_add(torrent,file1)==1);
        assert(torrent_add(torrent,file2)==1);
        assert(torrent_add(torrent,file3)==1);
        assert(torrent_add(torrent,file4)==1);
 
-       assert(NULL==torrent->tree->directories);
-       assert(torrent->tree->files->file==file3);
-       assert(torrent->tree->files->next->file==file4);
-       assert(torrent->tree->files->next->next->file==file1);
-       assert(torrent->tree->files->next->next->next->file==file2);
+       assert(torrent->tree->entries->file==file3);
+       assert(torrent->tree->entries->next->file==file4);
+       assert(torrent->tree->entries->next->next->file==file1);
+       assert(torrent->tree->entries->next->next->next->file==file2);
 
        torrent_free(torrent);
 
@@ -47,9 +46,10 @@ static void torrent_add_basic_test() {
 static void torrent_init_basic_test() {
        struct torrent *torrent;
 
-       assert(torrent_init(&torrent,NULL,NULL)<0);
-       assert(torrent_init(&torrent,"src",NULL)<0);
+       assert(torrent_init(&torrent,NULL,NULL,0)<0);
+       assert(torrent_init(&torrent,"src",NULL,0)<0);
+       assert(torrent_init(&torrent,"src","src",1000)<0);
 
-       assert(torrent_init(&torrent,"src","src")==1);
+       assert(torrent_init(&torrent,"src","src",16384)==1);
        torrent_free(torrent);
 }
index 9346c422b4fe5dd24bea3a80f3a1835f0b4c3fb0..6034844588d88effcba75b7ff12afa6ca70d4100 100644 (file)
@@ -4,7 +4,8 @@
 
 int main();
 static char *create_random_path();
-static int tree_deep_equals(struct tree *a, struct tree *b);
+static int tree_deep_equals(struct tree*,struct tree*);
+static int tree_entry_equals(struct tree_entry*,struct tree_entry*);
 static void tree_add_basic_test();
 static void tree_add_extended_test();
 static void tree_bencode_basic_test();
@@ -24,29 +25,17 @@ int main() {
 }
 
 static void tree_add_basic_test() {
-       struct tree *tree, *root, *test, *test2, *hello, *nope, *helloo;
-       struct tree_entry *entry1, *entry2, *entry3, *entry4;
+       struct tree *tree;
+       struct tree_entry *p;
        struct file *file1, *file2, *file3, *file4;
 
-       assert(1==tree_init(&tree,NULL));
-
-       assert(1==tree_init(&root,NULL));
-       assert(1==tree_init(&test,"test"));
-       assert(1==tree_init(&test2,"test2"));
-       assert(1==tree_init(&hello,"hello"));
-       assert(1==tree_init(&nope,"nope"));
-       assert(1==tree_init(&helloo,"helloo"));
+       assert(1==tree_init(&tree));
 
        assert(1==file_init(&file1,"test/file1"));
        assert(1==file_init(&file2,"test/hello/file2"));
        assert(1==file_init(&file3,"test2/nope/helloo/file3"));
        assert(1==file_init(&file4,"test/file4"));
 
-       assert(1==tree_entry_init(&entry1,file1));
-       assert(1==tree_entry_init(&entry2,file2));
-       assert(1==tree_entry_init(&entry3,file3));
-       assert(1==tree_entry_init(&entry4,file4));
-
        /*
         * Tree:
         * test(d)
@@ -60,16 +49,6 @@ static void tree_add_basic_test() {
         *                      file3(f)
         */
 
-       root->directories = test;
-       test->next = test2;
-       test->files = entry1;
-       entry1->next = entry4;
-       test->directories = hello;
-       hello->files = entry2;
-       test2->directories = nope;
-       nope->directories = helloo;
-       helloo->files = entry3;
-
        assert(-1==tree_add(NULL,NULL,NULL));
        assert(-1==tree_add(tree,NULL,NULL));
        assert(-1==tree_add(tree,"test path",NULL));
@@ -80,51 +59,105 @@ static void tree_add_basic_test() {
        assert(1==tree_add(tree,file3->path,file3));
        assert(1==tree_add(tree,file4->path,file4));
 
-       assert(NULL==tree->name);
-       assert(NULL==tree->files);
-
-       assert(tree_deep_equals(tree,root)==1);
-       assert(tree_deep_equals(tree->directories,test)==1);
-       assert(tree_deep_equals(tree->directories->next,test2)==1);
-       assert(tree_deep_equals(tree->directories->directories,hello)==1);
-       assert(tree_deep_equals(tree->directories->next->directories,nope)==1);
-       assert(tree_deep_equals(tree->directories->next->directories->directories,helloo)==1);
+       // test/
+       p = tree->entries;
+       assert(strcmp(p->name,"test")==0);
+       assert(p->children!=NULL);
+       assert(p->file==NULL);
+       assert(p->next!=NULL);
+
+       // test/file1
+       p = tree->entries->children->entries;
+       assert(strcmp(p->name,"file1")==0);
+       assert(p->children==NULL);
+       assert(p->file==file1);
+       assert(p->next!=NULL);
+
+       // test/file4
+       p = tree->entries->children->entries->next;
+       assert(strcmp(p->name,"file4")==0);
+       assert(p->children==NULL);
+       assert(p->file==file4);
+       assert(p->next!=NULL);
+
+       // test/hello/
+       p = tree->entries->children->entries->next->next;
+       assert(strcmp(p->name,"hello")==0);
+       assert(p->children!=NULL);
+       assert(p->file==NULL);
+       assert(p->next==NULL);
+
+       // test/hello/file2
+       p = tree->entries->children->entries->next->next->children->entries;
+       assert(strcmp(p->name,"file2")==0);
+       assert(p->children==NULL);
+       assert(p->file==file2);
+       assert(p->next==NULL);
+
+       // test2/
+       p = tree->entries->next;
+       assert(strcmp(p->name,"test2")==0);
+       assert(p->children!=NULL);
+       assert(p->file==NULL);
+       assert(p->next==NULL);
+       
+       // test2/nope/
+       p = tree->entries->next->children->entries;
+       assert(strcmp(p->name,"nope")==0);
+       assert(p->children!=NULL);
+       assert(p->file==NULL);
+       assert(p->next==NULL);
+
+       // test2/nope/helloo/
+       p = tree->entries->next->children->entries->children->entries;
+       assert(strcmp(p->name,"helloo")==0);
+       assert(p->children!=NULL);
+       assert(p->file==NULL);
+       assert(p->next==NULL);
+
+       // test2/nope/helloo/file3
+       p = tree->entries->next->children->entries->children->entries->children->entries;
+       assert(strcmp(p->name,"file3")==0);
+       assert(p->children==NULL);
+       assert(p->file==file3);
+       assert(p->next==NULL);
 
        tree_free(tree);
-
-       // remove pointers to already free'd entries
-       entry1->file = NULL;
-       entry2->file = NULL;
-       entry3->file = NULL;
-       entry4->file = NULL;
-
-       tree_free(root);
 }
 
 static int tree_deep_equals(struct tree *a, struct tree *b) {
        if(a==NULL&&b==NULL) { return 1; }
        if((a!=NULL&&b==NULL)||(a==NULL&&b!=NULL)) { return -1; }
-       if((a->name!=NULL&&b->name==NULL)||(a->name==NULL&&b->name!=NULL)) { return -1; }
-       if(a->name!=NULL) {
-               if(strcmp(a->name,b->name)!=0) { return -1; }
-       }
 
        {
                struct tree_entry *p1, *p2;
-               p1 = a->files;
-               p2 = b->files;
+               p1 = a->entries;
+               p2 = b->entries;
                while(p1!=NULL) {
                        if(p2==NULL) { return -1; }
-                       if(strcmp(p1->file->name,p2->file->name)!=0) { return -1; }
-                       if(strcmp(p1->file->path,p2->file->path)!=0) { return -1; }
+                       if(tree_entry_equals(p1,p2)<0) { return -1; }
 
                        p1 = p1->next;
                        p2 = p2->next;
                }
        }
 
-       if(tree_deep_equals(a->directories,b->directories)<0) { return -1; }
-       if(tree_deep_equals(a->next,b->next)<0) { return -1; }
+       return 1;
+}
+
+static int tree_entry_equals(struct tree_entry *a, struct tree_entry *b) {
+       if((a->name!=NULL&&b->name==NULL)||(a->name==NULL&&b->name!=NULL)) { return -1; }
+       if(a->name!=NULL) {
+               if(strcmp(a->name,b->name)!=0) { return -1; }
+       }
+
+       if(tree_deep_equals(a->children,b->children)<0) { return -1; }
+
+       if((a->file!=NULL&&b->file==NULL)||(a->file==NULL&&b->file!=NULL)) { return -1; }
+       if(a->file!=NULL) {
+               if(strcmp(a->file->name,b->file->name)!=0) { return -1; }
+               if(strcmp(a->file->path,b->file->path)!=0) { return -1; }
+       }
 
        return 1;
 }
@@ -158,7 +191,7 @@ static void tree_add_extended_test() {
        struct tree *tree;
        struct file *file;
 
-       assert(1==tree_init(&tree,NULL));
+       assert(1==tree_init(&tree));
        
        for(int i=0;i<100;i++) {
                char *path = create_random_path();
@@ -177,7 +210,7 @@ static void tree_bencode_basic_test() {
        char fileA_path[] = "dir1/dir2/fileA.txt";
        uint8_t expected[] = "d4:dir1d4:dir2d9:fileA.txtd0:d5:lengthi102411:pieces root32:00000000000000000000000000000000eeeee";
 
-       assert(1==tree_init(&root,NULL));
+       assert(1==tree_init(&root));
 
        assert(1==file_init(&file,fileA_path));
        memset(file->root,48,crypto_hash_sha256_BYTES);
@@ -190,24 +223,11 @@ static void tree_bencode_basic_test() {
 static void tree_init_basic_test() {
        struct tree *p;
 
-       char str[] = "this is a test string";
-
-       assert(-1==tree_init(NULL,NULL));
-       assert(1==tree_init(&p,NULL));
-
-       assert(NULL==p->name);
-       assert(NULL==p->files);
-       assert(NULL==p->directories);
-       assert(NULL==p->next);
+       assert(-1==tree_init(NULL));
+       assert(1==tree_init(&p));
 
-       tree_free(p);
-
-       assert(1==tree_init(&p,str));
+       assert(NULL==p->entries);
+       assert(-1==p->watch_fd);
 
-       assert(strcmp(p->name,str)==0);
-       assert(NULL==p->files);
-       assert(NULL==p->directories);
-       assert(NULL==p->next);
-       
        tree_free(p);
 }