diff --git a/importer/exporter.c b/importer/exporter.c index 34fbfd7..a8e8941 100644 --- a/importer/exporter.c +++ b/importer/exporter.c @@ -70,3 +70,71 @@ int ipfs_exporter_to_file(const unsigned char* hash, const char* file_name, cons return 1; } + +/** + * get a file by its hash, and write the data to a file + * @param hash the base58 multihash of the cid + * @param file_name the file name to write to + * @returns true(1) on success + */ +int ipfs_exporter_to_console(const unsigned char* hash, const struct FSRepo* fs_repo) { + // convert hash to cid + struct Cid* cid = NULL; + if ( ipfs_cid_decode_hash_from_base58(hash, strlen((char*)hash), &cid) == 0) { + return 0; + } + + // find block + struct Node* read_node = NULL; + if (ipfs_merkledag_get(cid->hash, cid->hash_length, &read_node, fs_repo) == 0) { + ipfs_cid_free(cid); + return 0; + } + + // no longer need the cid + ipfs_cid_free(cid); + + // process blocks + struct NodeLink* link = read_node->head_link; + printf("Links:["); + while (link != NULL) { + unsigned char b58[100]; + ipfs_cid_hash_to_base58(link->hash, link->hash_size, b58, 100); + printf("{\"Name\":\"%s\",\"Hash\":\"%s\",\"Size\":%lu}", (link->name != NULL ? link->name : ""), (char*)b58, link->t_size); + link = link->next; + } + printf("],\"Data\":\""); + for(size_t i = 0LU; i < read_node->data_size; i++) { + printf("%02x", read_node->data[i]); + } + printf("\"}\n"); + + if (read_node != NULL) + ipfs_node_free(read_node); + + return 1; +} + + +/*** + * Called from the command line with ipfs object get [hash]. Retrieves the object pointed to by hash, and displays its block data (links and data elements) + * @param argc number of arguments + * @param argv arguments + * @returns true(1) on success + */ +int ipfs_exporter_object_get(int argc, char** argv) { + struct FSRepo* fs_repo = NULL; + + // open the repo + int retVal = ipfs_repo_fsrepo_new(NULL, NULL, &fs_repo); + if (retVal == 0) { + return 0; + } + retVal = ipfs_repo_fsrepo_open(fs_repo); + if (retVal == 0) { + return 0; + } + // find hash + retVal = ipfs_exporter_to_console((unsigned char*)argv[3], fs_repo); + return retVal; +} diff --git a/importer/importer.c b/importer/importer.c index 24fc431..d58cda0 100644 --- a/importer/importer.c +++ b/importer/importer.c @@ -1,8 +1,11 @@ #include +#include +#include #include "ipfs/importer/importer.h" #include "ipfs/merkledag/merkledag.h" #include "ipfs/repo/fsrepo/fs_repo.h" +#include "ipfs/unixfs/unixfs.h" #define MAX_DATA_SIZE 262144 // 1024 * 256; @@ -16,27 +19,48 @@ * @param node the node to add to * @returns number of bytes read */ -size_t ipfs_import_chunk(FILE* file, struct Node* node, struct FSRepo* fs_repo) { +size_t ipfs_import_chunk(FILE* file, struct Node* parent_node, struct FSRepo* fs_repo, size_t* total_size) { unsigned char buffer[MAX_DATA_SIZE]; size_t bytes_read = fread(buffer, 1, MAX_DATA_SIZE, file); - if (node->data_size == 0) { - ipfs_node_set_data(node, buffer, bytes_read); - } else { - // create a new node, and link to the parent - struct Node* new_node = NULL; - ipfs_node_new_from_data(buffer, bytes_read, &new_node); - // persist - ipfs_merkledag_add(new_node, fs_repo); - // put link in parent node - struct NodeLink* new_link = NULL; - ipfs_node_link_create("", new_node->hash, new_node->hash_size, &new_link); - ipfs_node_add_link(node, new_link); - ipfs_node_free(new_node); - } + // create a new node + struct Node* new_node = NULL; + ipfs_node_new_from_data(buffer, bytes_read, &new_node); + // persist + ipfs_merkledag_add(new_node, fs_repo); + // put link in parent node + struct NodeLink* new_link = NULL; + ipfs_node_link_create("", new_node->hash, new_node->hash_size, &new_link); + new_link->t_size = new_node->data_size; + *total_size += new_link->t_size; + ipfs_node_add_link(parent_node, new_link); + ipfs_node_free(new_node); + // save the parent_node if it is time... if (bytes_read != MAX_DATA_SIZE) { + // build UnixFS for file + struct UnixFS* unix_fs; + if (ipfs_unixfs_new(&unix_fs) == 0) { + return 0; + } + unix_fs->data_type = UNIXFS_FILE; + unix_fs->file_size = *total_size; + // now encode unixfs and put in parent_node->data + size_t temp_size = ipfs_unixfs_protobuf_encode_size(unix_fs); + unsigned char temp[temp_size]; + size_t bytes_written; + if (ipfs_unixfs_protobuf_encode(unix_fs, temp, temp_size, &bytes_written) == 0) { + ipfs_unixfs_free(unix_fs); + return 0; + } + parent_node->data_size = bytes_written; + parent_node->data = (unsigned char*)malloc(bytes_written); + if (parent_node->data == NULL) { + ipfs_unixfs_free(unix_fs); + return 0; + } + memcpy(parent_node->data, temp, bytes_written); // persist the main node - ipfs_merkledag_add(node, fs_repo); + ipfs_merkledag_add(parent_node, fs_repo); } return bytes_read; } @@ -44,21 +68,22 @@ size_t ipfs_import_chunk(FILE* file, struct Node* node, struct FSRepo* fs_repo) /** * Creates a node based on an incoming file * @param file_name the file to import - * @param node the root node (could have links to others) + * @param parent_node the root node (has links to others) * @returns true(1) on success */ -int ipfs_import_file(const char* fileName, struct Node** node, struct FSRepo* fs_repo) { +int ipfs_import_file(const char* fileName, struct Node** parent_node, struct FSRepo* fs_repo) { int retVal = 1; int bytes_read = MAX_DATA_SIZE; + size_t total_size = 0; FILE* file = fopen(fileName, "rb"); - retVal = ipfs_node_new(node); + retVal = ipfs_node_new(parent_node); if (retVal == 0) return 0; // add all nodes while ( bytes_read == MAX_DATA_SIZE) { - bytes_read = ipfs_import_chunk(file, *node, fs_repo); + bytes_read = ipfs_import_chunk(file, *parent_node, fs_repo, &total_size); } fclose(file); @@ -76,7 +101,7 @@ int ipfs_import(int argc, char** argv) { * param 1: add * param 2: filename */ - struct Node* node = NULL; + struct Node* directory_node = NULL; struct FSRepo* fs_repo = NULL; // open the repo @@ -87,20 +112,20 @@ int ipfs_import(int argc, char** argv) { retVal = ipfs_repo_fsrepo_open(fs_repo); // import the file(s) - retVal = ipfs_import_file(argv[2], &node, fs_repo); + retVal = ipfs_import_file(argv[2], &directory_node, fs_repo); // give some results to the user int buffer_len = 100; unsigned char buffer[buffer_len]; - retVal = ipfs_cid_hash_to_base58(node->hash, node->hash_size, buffer, buffer_len); + retVal = ipfs_cid_hash_to_base58(directory_node->hash, directory_node->hash_size, buffer, buffer_len); if (retVal == 0) { printf("Unable to generate hash\n"); return 0; } printf("added %s %s\n", buffer, argv[2]); - if (node != NULL) - ipfs_node_free(node); + if (directory_node != NULL) + ipfs_node_free(directory_node); if (fs_repo != NULL) ipfs_repo_fsrepo_free(fs_repo); diff --git a/include/ipfs/importer/exporter.h b/include/ipfs/importer/exporter.h index 58aad67..395199c 100644 --- a/include/ipfs/importer/exporter.h +++ b/include/ipfs/importer/exporter.h @@ -7,3 +7,6 @@ * @returns true(1) on success */ int ipfs_exporter_to_file(const unsigned char* hash, const char* file_name, const struct FSRepo* fs_repo); + +int ipfs_exporter_object_get(int argc, char** argv); + diff --git a/main/ipfs b/main/ipfs index 6fce399..388725d 100755 Binary files a/main/ipfs and b/main/ipfs differ diff --git a/main/main.c b/main/main.c index 525e679..2fdc626 100644 --- a/main/main.c +++ b/main/main.c @@ -3,6 +3,7 @@ #include "ipfs/repo/init.h" #include "ipfs/importer/importer.h" +#include "ipfs/importer/exporter.h" void stripit(int argc, char** argv) { char tmp[strlen(argv[argc])]; @@ -22,6 +23,7 @@ void strip_quotes(int argc, char** argv) { #define INIT 1 #define ADD 2 +#define OBJECT_GET 3 /*** * Basic parsing of command line arguments to figure out where the user wants to go @@ -37,6 +39,9 @@ int parse_arguments(int argc, char** argv) { if (strcmp("add", argv[1]) == 0) { return ADD; } + if (strcmp("object", argv[1]) == 0 && argc > 2 && strcmp("get", argv[2]) == 0) { + return OBJECT_GET; + } return -1; } @@ -53,5 +58,8 @@ int main(int argc, char** argv) { case (ADD): ipfs_import(argc, argv); break; + case (OBJECT_GET): + ipfs_exporter_object_get(argc, argv); + break; } } diff --git a/merkledag/merkledag.c b/merkledag/merkledag.c index 2f57aea..37bf4bc 100644 --- a/merkledag/merkledag.c +++ b/merkledag/merkledag.c @@ -42,8 +42,9 @@ int ipfs_merkledag_add(struct Node* node, struct FSRepo* fs_repo) { } /*** - * Retrieves a node from the datastore based on the cid - * @param cid the key to look for + * Retrieves a node from the datastore based on the hash + * @param hash the key to look for + * @param hash_size the length of the key * @param node the node to be created * @param fs_repo the repository * @returns true(1) on success