diff --git a/importer/exporter.c b/importer/exporter.c index 77a1a6e..bf0c73f 100644 --- a/importer/exporter.c +++ b/importer/exporter.c @@ -38,31 +38,43 @@ int ipfs_exporter_to_file(const unsigned char* hash, const char* file_name, cons ipfs_node_free(read_node); return 0; } - size_t bytes_written = fwrite(read_node->data, 1, read_node->data_size, file); - if (bytes_written != read_node->data_size) { - fclose(file); - ipfs_node_free(read_node); - return 0; - } - struct NodeLink* link = read_node->head_link; - struct Node* link_node = NULL; - while (link != NULL) { - if ( ipfs_merkledag_get(link->hash, link->hash_size, &link_node, fs_repo) == 0) { - fclose(file); - ipfs_node_free(read_node); - return 0; - } - bytes_written = fwrite(link_node->data, 1, link_node->data_size, file); - if (bytes_written != link_node->data_size) { - ipfs_node_free(link_node); - fclose(file); - ipfs_node_free(read_node); - return 0; - } - ipfs_node_free(link_node); - link = link->next; - } + if (read_node->head_link == NULL) { + // convert the node's data into a UnixFS data block + struct UnixFS* unix_fs; + ipfs_unixfs_protobuf_decode(read_node->data, read_node->data_size, &unix_fs); + size_t bytes_written = fwrite(unix_fs->bytes, 1, unix_fs->bytes_size, file); + if (bytes_written != unix_fs->bytes_size) { + fclose(file); + ipfs_node_free(read_node); + ipfs_unixfs_free(unix_fs); + return 0; + } + ipfs_unixfs_free(unix_fs); + } else { + struct NodeLink* link = read_node->head_link; + struct Node* link_node = NULL; + while (link != NULL) { + if ( ipfs_merkledag_get(link->hash, link->hash_size, &link_node, fs_repo) == 0) { + fclose(file); + ipfs_node_free(read_node); + return 0; + } + struct UnixFS* unix_fs; + ipfs_unixfs_protobuf_decode(link_node->data, link_node->data_size, &unix_fs); + size_t bytes_written = fwrite(unix_fs->bytes, 1, unix_fs->bytes_size, file); + if (bytes_written != unix_fs->bytes_size) { + ipfs_node_free(link_node); + fclose(file); + ipfs_node_free(read_node); + ipfs_unixfs_free(unix_fs); + return 0; + } + ipfs_node_free(link_node); + ipfs_unixfs_free(unix_fs); + link = link->next; + } + } fclose(file); if (read_node != NULL) diff --git a/importer/importer.c b/importer/importer.c index 02daf4f..04ea505 100644 --- a/importer/importer.c +++ b/importer/importer.c @@ -178,11 +178,15 @@ int ipfs_import_print_node_results(const struct Node* node, const char* file_nam /** * Creates a node based on an incoming file or directory * NOTE: this can be called recursively for directories + * @param root_dir the directory for where to look for the file * @param file_name the file (or directory) to import * @param parent_node the root node (has links to others in case this is a large file and is split) + * @param fs_repo the ipfs repository + * @param bytes_written number of bytes written to disk + * @param recursive true if we should navigate directories * @returns true(1) on success */ -int ipfs_import_file(const char* root_dir, const char* fileName, struct Node** parent_node, struct FSRepo* fs_repo, size_t* bytes_written) { +int ipfs_import_file(const char* root_dir, const char* fileName, struct Node** parent_node, struct FSRepo* fs_repo, size_t* bytes_written, int recursive) { /** * NOTE: When this function completes, parent_node will be either: * 1) the complete file, in the case of a small file (<256k-ish) @@ -194,44 +198,76 @@ int ipfs_import_file(const char* root_dir, const char* fileName, struct Node** p size_t total_size = 0; if (os_utils_is_directory(fileName)) { + // calculate the new root_dir + char* new_root_dir = (char*)root_dir; + char* path = NULL; + char* file = NULL; + os_utils_split_filename(fileName, &path, &file); + if (root_dir == NULL) { + new_root_dir = file; + } else { + free(path); + path = malloc(strlen(root_dir) + strlen(file) + 2); + os_utils_filepath_join(root_dir, file, path, strlen(root_dir) + strlen(file) + 2); + new_root_dir = path; + } // initialize parent_node as a directory - if (ipfs_node_create_directory(parent_node) == 0) + if (ipfs_node_create_directory(parent_node) == 0) { + if (path != NULL) + free(path); + if (file != NULL) + free(file); return 0; + } // get list of files struct FileList* first = os_utils_list_directory(fileName); struct FileList* next = first; - while (next != NULL) { - // process each file. NOTE: could be an embedded directory - *bytes_written = 0; - struct Node* file_node; - size_t filename_len = strlen(fileName) + strlen(next->file_name) + 2; - char full_file_name[filename_len]; - os_utils_filepath_join(fileName, next->file_name, full_file_name, filename_len); - if (ipfs_import_file(root_dir, full_file_name, &file_node, fs_repo, bytes_written) == 0) { - ipfs_node_free(*parent_node); - os_utils_free_file_list(first); - return 0; - } - // TODO: probably need to display what was imported - int len = strlen(next->file_name) + strlen(root_dir) + 2; - char full_path[len]; - os_utils_filepath_join(root_dir, next->file_name, full_path, len); - ipfs_import_print_node_results(file_node, full_path); - // TODO: Determine what needs to be done if this file_node is a file, a split file, or a directory - // Create link from file_node - struct NodeLink* file_node_link; - ipfs_node_link_create(next->file_name, file_node->hash, file_node->hash_size, &file_node_link); - file_node_link->t_size = *bytes_written; - // add file_node as link to parent_node - ipfs_node_add_link(*parent_node, file_node_link); - // clean up file_node - ipfs_node_free(file_node); - // move to next file in list - next = next->next; - } // while going through files + if (recursive) { + while (next != NULL) { + // process each file. NOTE: could be an embedded directory + *bytes_written = 0; + struct Node* file_node; + // put the filename together from fileName, which is the directory, and next->file_name + // which is a file (or a directory) within the directory we just found. + size_t filename_len = strlen(fileName) + strlen(next->file_name) + 2; + char full_file_name[filename_len]; + os_utils_filepath_join(fileName, next->file_name, full_file_name, filename_len); + // adjust root directory + + if (ipfs_import_file(new_root_dir, full_file_name, &file_node, fs_repo, bytes_written, recursive) == 0) { + ipfs_node_free(*parent_node); + os_utils_free_file_list(first); + if (file != NULL) + free(file); + if (path != NULL) + free (path); + return 0; + } + // TODO: probably need to display what was imported + int len = strlen(next->file_name) + strlen(new_root_dir) + 2; + char full_path[len]; + os_utils_filepath_join(new_root_dir, next->file_name, full_path, len); + ipfs_import_print_node_results(file_node, full_path); + // TODO: Determine what needs to be done if this file_node is a file, a split file, or a directory + // Create link from file_node + struct NodeLink* file_node_link; + ipfs_node_link_create(next->file_name, file_node->hash, file_node->hash_size, &file_node_link); + file_node_link->t_size = *bytes_written; + // add file_node as link to parent_node + ipfs_node_add_link(*parent_node, file_node_link); + // clean up file_node + ipfs_node_free(file_node); + // move to next file in list + next = next->next; + } // while going through files + } // save the parent_node (the directory) size_t bytes_written; ipfs_merkledag_add(*parent_node, fs_repo, &bytes_written); + if (file != NULL) + free(file); + if (path != NULL) + free (path); } else { // process this file FILE* file = fopen(fileName, "rb"); @@ -304,7 +340,7 @@ int ipfs_import_files(int argc, char** argv) { char* filename; os_utils_split_filename(current->file_name, &path, &filename); size_t bytes_written = 0; - retVal = ipfs_import_file(filename, current->file_name, &directory_entry, fs_repo, &bytes_written); + retVal = ipfs_import_file(NULL, current->file_name, &directory_entry, fs_repo, &bytes_written, recursive); ipfs_import_print_node_results(directory_entry, filename); // cleanup diff --git a/include/ipfs/importer/importer.h b/include/ipfs/importer/importer.h index 3b4b0e9..dd1f2a3 100644 --- a/include/ipfs/importer/importer.h +++ b/include/ipfs/importer/importer.h @@ -6,11 +6,15 @@ /** * Creates a node based on an incoming file - * @param file_name the file to import + * @param root the root directory + * @param file_name the file to import (could contain a directory) * @param node the root node (could have links to others) + * @param fs_repo the repo to use + * @param bytes_written the number of bytes written to disk + * @param recursive true(1) if you want to include files and directories * @returns true(1) on success */ -int ipfs_import_file(const char* root, const char* fileName, struct Node** node, struct FSRepo* fs_repo, size_t* bytes_written); +int ipfs_import_file(const char* root, const char* fileName, struct Node** node, struct FSRepo* fs_repo, size_t* bytes_written, int recursive); /** * called from the command line diff --git a/include/ipfs/os/utils.h b/include/ipfs/os/utils.h index 2753ced..214a741 100644 --- a/include/ipfs/os/utils.h +++ b/include/ipfs/os/utils.h @@ -46,7 +46,7 @@ int os_utils_split_filename(const char* in, char** path, char** filename); * @returns the results */ char* os_utils_getenv(const char* variable); - +int os_utils_setenv(const char* variable, const char* value, int overwrite); /** * get the user's home directory * @returns the user's home directory diff --git a/merkledag/merkledag.c b/merkledag/merkledag.c index cf3db22..fd2fdec 100644 --- a/merkledag/merkledag.c +++ b/merkledag/merkledag.c @@ -76,6 +76,9 @@ int ipfs_merkledag_get(const unsigned char* hash, size_t hash_size, struct Node* return 0; } + // set the hash + ipfs_node_set_hash(*node, hash, hash_size); + return 1; } diff --git a/os/utils.c b/os/utils.c index 93c5f80..a65d2e7 100644 --- a/os/utils.c +++ b/os/utils.c @@ -17,6 +17,17 @@ char* os_utils_getenv(const char* variable) { return getenv(variable); } +/** + * set an environment variable in the os + * @param variable the variable to set + * @param value the value to assign to the variable + * @param overwrite passing a non-zero will allow an existing value to be overwritten + * @returns true(1) on success + */ +int os_utils_setenv(const char* variable, const char* value, int overwrite) { + return setenv(variable, value, overwrite); +} + /** * returns the user's home directory * @returns the home directory diff --git a/repo/fsrepo/fs_repo.c b/repo/fsrepo/fs_repo.c index c615104..57f901a 100644 --- a/repo/fsrepo/fs_repo.c +++ b/repo/fsrepo/fs_repo.c @@ -116,15 +116,27 @@ int ipfs_repo_fsrepo_new(const char* repo_path, struct RepoConfig* config, struc if (repo_path == NULL) { // get the user's home directory - char* home_dir = os_utils_get_homedir(); + char* ipfs_path = os_utils_getenv("IPFS_PATH"); + if (ipfs_path == NULL) + ipfs_path = os_utils_get_homedir(); char* default_subdir = "/.ipfs"; - unsigned long newPathLen = strlen(home_dir) + strlen(default_subdir) + 2; // 1 for slash and 1 for end + unsigned long newPathLen = 0; + if (strstr(ipfs_path, default_subdir) != NULL) { + newPathLen = strlen(ipfs_path) + 1; + } else { + // add /.ipfs to the string + newPathLen = strlen(ipfs_path) + strlen(default_subdir) + 2; // 1 for slash and 1 for end + } (*repo)->path = malloc(sizeof(char) * newPathLen); if ((*repo)->path == NULL) { free( (*repo)); return 0; } - os_utils_filepath_join(os_utils_get_homedir(), default_subdir, (*repo)->path, newPathLen); + if (strstr(ipfs_path, default_subdir) != NULL) { + strcpy((*repo)->path, ipfs_path); + } else { + os_utils_filepath_join(os_utils_get_homedir(), default_subdir, (*repo)->path, newPathLen); + } } else { int len = strlen(repo_path) + 1; (*repo)->path = (char*)malloc(len); diff --git a/repo/init.c b/repo/init.c index dce7587..a3c4b34 100644 --- a/repo/init.c +++ b/repo/init.c @@ -52,10 +52,16 @@ int make_ipfs_repository(const char* path) { * Initialize a repository */ int ipfs_repo_init(int argc, char** argv) { + // the default is the user's home directory char* home_directory = os_utils_get_homedir(); //allow user to pass directory on command line if (argc > 2) { home_directory = argv[2]; + } else { + // check the IPFS_PATH + char* temp = os_utils_getenv("IPFS_PATH"); + if (temp != NULL) + home_directory = temp; } // get the full path int dir_len = strlen(home_directory) + 7; diff --git a/test/node/test_importer.h b/test/node/test_importer.h index 5a5f3f2..35b34ea 100644 --- a/test/node/test_importer.h +++ b/test/node/test_importer.h @@ -46,13 +46,13 @@ int test_import_large_file() { // write to ipfs struct Node* write_node; size_t bytes_written; - if (ipfs_import_file("/tmp", fileName, &write_node, fs_repo, &bytes_written) == 0) { + if (ipfs_import_file("/tmp", fileName, &write_node, fs_repo, &bytes_written, 1) == 0) { ipfs_repo_fsrepo_free(fs_repo); return 0; } // cid should be the same each time - unsigned char cid_test[10] = { 0x2c ,0x8e ,0x20 ,0x1b, 0xc7, 0xcc, 0x4d, 0x8f, 0x7e, 0x77 }; + unsigned char cid_test[10] = { 0xc1 ,0x69 ,0x68 ,0x22, 0xfa, 0x47, 0x16, 0xe2, 0x41, 0xa1 }; /* for (int i = 0; i < 10; i++) { @@ -195,13 +195,13 @@ int test_import_small_file() { // write to ipfs struct Node* write_node; size_t bytes_written; - if (ipfs_import_file("/tmp", fileName, &write_node, fs_repo, &bytes_written) == 0) { + if (ipfs_import_file("/tmp", fileName, &write_node, fs_repo, &bytes_written, 1) == 0) { ipfs_repo_fsrepo_free(fs_repo); return 0; } // cid should be the same each time - unsigned char cid_test[10] = { 0x94, 0x4f, 0x39, 0xa0, 0x33, 0x5d, 0x7f, 0xf2, 0xcd, 0x66 }; + unsigned char cid_test[10] = { 0x1e, 0xcf, 0x04, 0xce, 0x6a, 0xe8, 0xbf, 0xc0, 0xeb, 0xe4 }; /* for (int i = 0; i < 10; i++) { @@ -227,7 +227,7 @@ int test_import_small_file() { } // compare data - if (write_node->data_size != bytes_size || write_node->data_size != read_node->data_size) { + if (write_node->data_size != bytes_size + 8 || write_node->data_size != read_node->data_size) { printf("Data size of nodes are not equal or are incorrect. Should be %lu but are %lu\n", write_node->data_size, read_node->data_size); ipfs_repo_fsrepo_free(fs_repo); ipfs_node_free(write_node); diff --git a/test/node/test_resolver.h b/test/node/test_resolver.h index f9fcd90..787a64d 100644 --- a/test/node/test_resolver.h +++ b/test/node/test_resolver.h @@ -1,19 +1,24 @@ #include "ipfs/importer/resolver.h" +#include "ipfs/os/utils.h" int test_resolver_get() { // clean out repository - drop_and_build_repository("/Users/JohnJones/.ipfs"); + const char* ipfs_path = "/tmp/.ipfs"; + os_utils_setenv("IPFS_PATH", ipfs_path, 1); - int argc = 3; + drop_and_build_repository(ipfs_path); + + int argc = 4; char* argv[argc]; argv[0] = "ipfs"; argv[1] = "add"; - argv[2] = "/Users/JohnJones/ipfstest"; + argv[2] = "-r"; + argv[3] = "/Users/JohnJones/ipfstest"; ipfs_import_files(argc, (char**)argv); struct FSRepo* fs_repo; - ipfs_repo_fsrepo_new("/Users/JohnJones/.ipfs", NULL, &fs_repo); + ipfs_repo_fsrepo_new(ipfs_path, NULL, &fs_repo); ipfs_repo_fsrepo_open(fs_repo); // find something that is already in the repository @@ -25,7 +30,7 @@ int test_resolver_get() { ipfs_node_free(result); // find something by path - result = ipfs_resolver_get("/ipfs/QmWKtXwRg4oL2KaXhvJ3KyGjFE2PVKREwu7qb65V7ficui/hello_world.txt", NULL, fs_repo); + result = ipfs_resolver_get("/ipfs/QmZBvycPAYScBoPEzm35zXHt6gYYV5t9PyWmr4sksLPNFS/hello_world.txt", NULL, fs_repo); if (result == NULL) { return 0; } diff --git a/test/repo/test_repo_config.h b/test/repo/test_repo_config.h index 52ead48..98f4a36 100644 --- a/test/repo/test_repo_config.h +++ b/test/repo/test_repo_config.h @@ -1,6 +1,6 @@ #ifndef test_repo_config_h #define test_repo_config_h - +#include #include "ipfs/repo/config/config.h" #include "ipfs/repo/fsrepo/fs_repo.h" #include "ipfs/os/utils.h" @@ -63,6 +63,10 @@ int test_repo_config_init() { * test the writing of the config file */ int test_repo_config_write() { + // make sure the directory is there + if (!os_utils_file_exists("/tmp/.ipfs")) { + mkdir("/tmp/.ipfs", S_IRWXU); + } // first delete the existing one unlink("/tmp/.ipfs/config"); diff --git a/test/storage/test_unixfs.h b/test/storage/test_unixfs.h index 1ea4357..89ca69b 100644 --- a/test/storage/test_unixfs.h +++ b/test/storage/test_unixfs.h @@ -65,8 +65,7 @@ int test_unixfs_encode_smallfile() { 0x74, 0x68, 0x69, 0x6e, 0x20, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x57, 0x65, 0x72, 0x6c, 0x64, - 0x2e, 0x74, 0x78, 0x74, 0x0a, - 0x18, 0x23 + 0x2e, 0x74, 0x78, 0x74, 0x0a }; unixfs->bytes = (unsigned char*)malloc(35); @@ -81,7 +80,7 @@ int test_unixfs_encode_smallfile() { int retVal = 1; - if (bytes_written != 41) { + if (bytes_written != 39) { printf("Length should be %lu, but is %lu\n", 41LU, bytes_written); retVal = 0; }