From fa3dd77e96544863c238096a23442ddc28dd4263 Mon Sep 17 00:00:00 2001 From: jmjatlanta Date: Wed, 28 Dec 2016 22:45:35 -0500 Subject: [PATCH] Saving directories --- importer/importer.c | 81 +++++++++++++++++++++++++---------- include/ipfs/merkledag/node.h | 13 +++++- include/ipfs/os/utils.h | 19 ++++++++ merkledag/node.c | 29 +++++++++++++ os/utils.c | 54 +++++++++++++++++++++++ 5 files changed, 171 insertions(+), 25 deletions(-) diff --git a/importer/importer.c b/importer/importer.c index cceccea..5861afd 100644 --- a/importer/importer.c +++ b/importer/importer.c @@ -4,6 +4,7 @@ #include "ipfs/importer/importer.h" #include "ipfs/merkledag/merkledag.h" +#include "ipfs/os/utils.h" #include "ipfs/repo/fsrepo/fs_repo.h" #include "ipfs/unixfs/unixfs.h" @@ -150,6 +151,26 @@ size_t ipfs_import_chunk(FILE* file, struct Node* parent_node, struct FSRepo* fs return bytes_read; } +/** + * Prints to the console the results of a node import + * @param node the node imported + * @param file_name the name of the file + * @returns true(1) if successful, false(0) if couldn't generate the MultiHash to be displayed + */ +int ipfs_import_print_node_results(const struct Node* node, const char* file_name) { + // give some results to the user + //TODO: if directory_entry is itself a directory, traverse and report files + int buffer_len = 100; + unsigned char buffer[buffer_len]; + if (ipfs_cid_hash_to_base58(node->hash, node->hash_size, buffer, buffer_len) == 0) { + printf("Unable to generate hash for file %s.\n", file_name); + return 0; + } + printf("added %s %s\n", buffer, file_name); + return 1; +} + + /** * Creates a node based on an incoming file or directory * NOTE: this can be called recursively for directories @@ -167,13 +188,42 @@ int ipfs_import_file(const char* fileName, struct Node** parent_node, struct FSR int retVal = 1; int bytes_read = MAX_DATA_SIZE; size_t total_size = 0; - unsigned int isDirectory = 0; - //TODO: determine if this file is actually a directory - if (isDirectory) { + if (os_utils_is_directory(fileName)) { + // initialize parent_node as a directory + if (ipfs_node_create_directory(parent_node) == 0) + return 0; // get list of files - // process each file - // add file as link to parent_node + struct FileList* first = os_utils_list_directory(fileName); + struct FileList* next = first; + while (next != NULL) { + // process each file. NOTE: could be an embedded directory + 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(full_file_name, &file_node, fs_repo) == 0) { + ipfs_node_free(*parent_node); + os_utils_free_file_list(first); + return 0; + } + // TODO: probably need to display what was imported + ipfs_import_print_node_results(file_node, next->file_name); + // 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 = file_node->data_size; + // 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); } else { // process this file FILE* file = fopen(fileName, "rb"); @@ -192,12 +242,6 @@ int ipfs_import_file(const char* fileName, struct Node** parent_node, struct FSR } -// a linked list to store filenames -struct FileList { - char* file_name; - struct FileList* next; -}; - /** * called from the command line to import multiple files or directories * @param argc the number of arguments @@ -248,18 +292,8 @@ int ipfs_import_files(int argc, char** argv) { struct Node* directory_entry = NULL; retVal = ipfs_import_file(current->file_name, &directory_entry, fs_repo); - // give some results to the user - int buffer_len = 100; - unsigned char buffer[buffer_len]; - retVal = ipfs_cid_hash_to_base58(directory_entry->hash, directory_entry->hash_size, buffer, buffer_len); - if (retVal == 0) { - printf("Unable to generate hash\n"); - ipfs_node_free(directory_entry); - ipfs_repo_fsrepo_free(fs_repo); - return 0; - } - printf("added %s %s\n", buffer, current->file_name); - //TODO: cleanup + ipfs_import_print_node_results(directory_entry, current->file_name); + // cleanup ipfs_node_free(directory_entry); current = current->next; } @@ -276,3 +310,4 @@ int ipfs_import_files(int argc, char** argv) { return retVal; } + diff --git a/include/ipfs/merkledag/node.h b/include/ipfs/merkledag/node.h index fe6469b..e7b2d94 100644 --- a/include/ipfs/merkledag/node.h +++ b/include/ipfs/merkledag/node.h @@ -127,12 +127,21 @@ int ipfs_node_protobuf_decode(unsigned char* buffer, size_t buffer_length, struc * Node Functions *===================================================================================*/ -/*ipfs_node_new +/**** * Creates an empty node, allocates the required memory - * Returns a fresh new node with no data set in it. + * @param node the pointer to the memory allocated + * @returns true(1) on success, otherwise false(0) */ int ipfs_node_new(struct Node** node); +/*** + * Allocates memory for a node, and sets the data section to indicate + * that this node is a directory + * @param node the node to initialize + * @returns true(1) on success, otherwise false(0) + */ +int ipfs_node_create_directory(struct Node** node); + /** * sets the Cid into the struct element titled cached * @param node the node to work with diff --git a/include/ipfs/os/utils.h b/include/ipfs/os/utils.h index 09b7cd8..a1b26d8 100644 --- a/include/ipfs/os/utils.h +++ b/include/ipfs/os/utils.h @@ -8,6 +8,18 @@ #include #include +/** + * a linked list to store filenames + */ +struct FileList { + char* file_name; + struct FileList* next; +}; + +struct FileList* os_utils_list_directory(const char* path); +// frees memory used by creating a FileList linked list +int os_utils_free_file_list(struct FileList* first); + /** * get an environment varible from the os * @param variable the variable to look for @@ -38,4 +50,11 @@ int os_utils_directory_writeable(const char* path); int os_utils_directory_exists(const char* path); +/** + * Determine if the path presented is actually a directory + * @param file_name the path to examine + * @returns true(1) if file_name is actually a directory + */ +int os_utils_is_directory(const char* file_name); + #endif /* utils_h */ diff --git a/merkledag/node.c b/merkledag/node.c index 6b336a8..ac4eeb8 100644 --- a/merkledag/node.c +++ b/merkledag/node.c @@ -356,6 +356,35 @@ int ipfs_node_new(struct Node** node) return 1; } +/*** + * Allocates memory for a node, and sets the data section to indicate + * that this node is a directory + * @param node the node to initialize + * @returns true(1) on success, otherwise false(0) + */ +int ipfs_node_create_directory(struct Node** node) { + // initialize parent_node + if (ipfs_node_new(node) == 0) + return 0; + // put a UnixFS protobuf in the data section + struct UnixFS* unix_fs; + if (ipfs_unixfs_new(&unix_fs) == 0) { + ipfs_node_free(*node); + return 0; + } + unix_fs->data_type = UNIXFS_DIRECTORY; + size_t protobuf_len = ipfs_unixfs_protobuf_encode_size(unix_fs); + unsigned char protobuf[protobuf_len]; + if (ipfs_unixfs_protobuf_encode(unix_fs, protobuf, protobuf_len, &protobuf_len) == 0) { + ipfs_node_free(*node); + ipfs_unixfs_free(unix_fs); + return 0; + } + ipfs_unixfs_free(unix_fs); + ipfs_node_set_data(*node, protobuf, protobuf_len); + return 1; +} + /** * Set the cached struct element * @param node the node to be modified diff --git a/os/utils.c b/os/utils.c index 41dc01c..5bae8fb 100644 --- a/os/utils.c +++ b/os/utils.c @@ -2,9 +2,11 @@ #include #include +#include #include #include #include +#include /** * get an environment varible from the os @@ -56,6 +58,58 @@ int os_utils_directory_exists(const char* directory_name) { return 0; } +int os_utils_is_directory(const char* file_name) { + struct stat path_stat; + stat(file_name, &path_stat); + return S_ISDIR(path_stat.st_mode) != 0; +} + +struct FileList* os_utils_list_directory(const char* path) { + DIR* dp; + struct dirent *ep; + struct FileList* first = NULL; + struct FileList* last = NULL; + struct FileList* next = NULL; + + dp = opendir(path); + if (dp != NULL) { + while ( (ep = readdir(dp)) ) { + if (strcmp(ep->d_name, ".") != 0 && strcmp(ep->d_name, "..") != 0) { + // grab the data + next = (struct FileList*)malloc(sizeof(struct FileList)); + next->file_name = malloc(strlen(ep->d_name) + 1); + strcpy(next->file_name, ep->d_name); + next->next = NULL; + // put it in the appropriate spot + if (first == NULL) { + first = next; + last = next; + } else { + last->next = next; + last = next; + } + } // not dealing with . or .. + } // while + closedir(dp); + } + return first; +} + +int os_utils_free_file_list(struct FileList* first) { + if (first != NULL) { + struct FileList* next = first; + struct FileList* last = NULL; + while (next != NULL) { + last = next->next; + free(next); + next = last; + } + } + return 1; +} + + + int os_utils_directory_writeable(const char* path) { int result = access(path, W_OK); return result == 0;