diff --git a/.cproject b/.cproject index c73ace8..9bbebce 100644 --- a/.cproject +++ b/.cproject @@ -14,7 +14,7 @@ - + @@ -58,40 +58,6 @@ - - - - make - all - true - true - true - - - make - clean - true - true - true - - - make - - clean - true - false - true - - - make - - clean - true - false - true - - - @@ -101,4 +67,46 @@ + + + + make + + all + true + true + true + + + make + + clean + true + true + true + + + make + + rebuild + true + true + true + + + make + clean + true + false + true + + + make + clean + true + false + true + + + diff --git a/Makefile b/Makefile index 778029a..fc6bf07 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ DEBUG = true export DEBUG all: + cd blocks; make all; cd cid; make all; cd cmd; make all; cd commands; make all; @@ -16,6 +17,7 @@ all: cd test; make all; clean: + cd blocks; make clean; cd cid; make clean; cd cmd; make clean; cd commands; make clean; @@ -27,4 +29,5 @@ clean: cd datastore; make clean; cd thirdparty; make clean; cd test; make clean; - + +rebuild: clean all diff --git a/blocks/Makefile b/blocks/Makefile new file mode 100644 index 0000000..9828cc1 --- /dev/null +++ b/blocks/Makefile @@ -0,0 +1,18 @@ +CC = gcc +CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/include + +ifdef DEBUG +CFLAGS += -g3 +endif + +LFLAGS = +DEPS = ../include/blocks/block.h ../include/blocks/blockstore.h +OBJS = block.o blockstore.o + +%.o: %.c $(DEPS) + $(CC) -c -o $@ $< $(CFLAGS) + +all: $(OBJS) + +clean: + rm -f *.o diff --git a/blocks/block.c b/blocks/block.c index 6359442..4d6dcf6 100644 --- a/blocks/block.c +++ b/blocks/block.c @@ -3,6 +3,7 @@ */ #include +#include #include "libp2p/crypto/sha256.h" #include "ipfs/blocks/block.h" @@ -15,7 +16,7 @@ * @param block a pointer to the struct Block that will be created * @returns true(1) on success */ -int ipfs_blocks_block_new(unsigned char* data, size_t data_size, struct Block** block) { +int ipfs_blocks_block_new(const unsigned char* data, size_t data_size, struct Block** block) { // allocate memory for structure (*block) = (struct Block*)malloc(sizeof(struct Block)); @@ -23,25 +24,27 @@ int ipfs_blocks_block_new(unsigned char* data, size_t data_size, struct Block** return 0; // cid - char hash[32]; - if (libp2p_crypto_hashing_sha256(data, hash, 32) == 0) { + unsigned char hash[32]; + if (libp2p_crypto_hashing_sha256(data, data_size, &hash[0]) == 0) { free(*block); return 0; } - if (ipfs_cid_new(0, hash, 32, CID_PROTOBUF, (*block)->cid) == 0) { + if (ipfs_cid_new(0, hash, 32, CID_PROTOBUF, &((*block)->cid)) == 0) { free(*block); return 0; } - block->data = malloc(sizeof(unsigned char) * data_size); - if (block->data == NULL) { - ipfs_ci_free((*block)->cid); + (*block)->data_length = data_size; + + (*block)->data = malloc(sizeof(unsigned char) * data_size); + if ( (*block)->data == NULL) { + ipfs_cid_free((*block)->cid); free(*block); return 0; } - memcpy(block->data, data, data_size); + memcpy( (*block)->data, data, data_size); return 1; } diff --git a/blocks/blockstore.c b/blocks/blockstore.c index bd86ae0..68d2803 100644 --- a/blocks/blockstore.c +++ b/blocks/blockstore.c @@ -1,14 +1,18 @@ /*** * a thin wrapper over a datastore for getting and putting block objects */ - +#include "libp2p/crypto/encoding/base32.h" +#include "ipfs/cid/cid.h" +#include "ipfs/blocks/block.h" +#include "ipfs/datastore/ds_helper.h" +#include "ipfs/repo/fsrepo/fs_repo.h" /** * Delete a block based on its Cid * @param cid the Cid to look for * @param returns true(1) on success */ -int ipfs_blockstore_delete(struct Cid* cid) { +int ipfs_blockstore_delete(struct Cid* cid, struct FSRepo* fs_repo) { return 0; } @@ -17,7 +21,7 @@ int ipfs_blockstore_delete(struct Cid* cid) { * @param cid the Cid to look for * @returns true(1) if found */ -int ipfs_blockstore_has(struct Cid* cid) { +int ipfs_blockstore_has(struct Cid* cid, struct FSRepo* fs_repo) { return 0; } @@ -27,7 +31,7 @@ int ipfs_blockstore_has(struct Cid* cid) { * @param block where to put the data to be returned * @returns true(1) on success */ -int ipfs_blockstore_get(struct Cid* cid, struct Block* block) { +int ipfs_blockstore_get(struct Cid* cid, struct Block* block, struct FSRepo* fs_repo) { return 0; } @@ -36,9 +40,16 @@ int ipfs_blockstore_get(struct Cid* cid, struct Block* block) { * @param block the block to store * @returns true(1) on success */ -int ipfs_blockstore_put(struct Block* block) { +int ipfs_blockstore_put(struct Block* block, struct FSRepo* fs_repo) { // from blockstore.go line 118 - // TODO: Get Datastore key - // TODO: send to Put with key + // Get Datastore key, which is a base32 key of the binary, + size_t key_length = libp2p_crypto_encoding_base32_encode_size(block->data_length); + unsigned char key[key_length]; + int retVal = ipfs_datastore_helper_ds_key_from_binary(block->data, block->data_length, &key[0], key_length, &key_length); + if (retVal == 0) + return 0; + + // send to Put with key + fs_repo->config->datastore->datastore_put(key, block, fs_repo->config->datastore); return 0; } diff --git a/cmd/ipfs/init.c b/cmd/ipfs/init.c index 468ec5f..2bd3a18 100644 --- a/cmd/ipfs/init.c +++ b/cmd/ipfs/init.c @@ -61,7 +61,7 @@ int do_init(FILE* out_file, char* repo_root, int empty, int num_bits_for_keypair return 0; //TODO: If the conf is null, make one if ( conf->identity->peer_id == NULL) { - int retVal = repo_config_init(conf, num_bits_for_keypair, repo_root); + int retVal = ipfs_repo_config_init(conf, num_bits_for_keypair, repo_root); if (retVal == 0) return 0; } @@ -87,11 +87,12 @@ int init_run(struct Request* request) { // TODO: make sure offline // TODO: check parameters for logic errors // TODO: Initialize - struct RepoConfig conf = {0}; + struct RepoConfig* conf; + int retVal = ipfs_repo_config_new(&conf); // TODO: handle files in request // do the heavy lifting int num_bits_for_key_pair = request->cmd.options[0]->default_int_val; - return do_init(stdout, request->invoc_context->config_root, 1, num_bits_for_key_pair, &conf); + return do_init(stdout, request->invoc_context->config_root, 1, num_bits_for_key_pair, conf); } /*** diff --git a/datastore/Makefile b/datastore/Makefile index e8bfbec..ec69298 100644 --- a/datastore/Makefile +++ b/datastore/Makefile @@ -1,5 +1,5 @@ CC = gcc -CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/include +CFLAGS = -O0 -I../include -I../../c-libp2p/include -I../../c-multihash/include -I../../c-multiaddr/include -I../../lmdb/libraries/liblmdb ifdef DEBUG CFLAGS += -g3 @@ -7,7 +7,7 @@ endif LFLAGS = DEPS = ../include/ipfsdatastore/ds_helper.h -OBJS = ds_helper.o +OBJS = ds_helper.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/datastore/key.c b/datastore/key.c new file mode 100644 index 0000000..7baeb5a --- /dev/null +++ b/datastore/key.c @@ -0,0 +1,18 @@ +#include + +/** + * Constructs a new "clean" key. Will remove things like slashes + * @param input the input + * @param output the output + * @param max_output_length the amount of memory allocated for output + * @param actual_output_length the amount of bytes written to output + * @returns true(1) on success + */ +int ipfs_datastore_key_new(const char* input, char* output, size_t max_output_length, size_t* actual_output_length) { + //TODO: clean the input + if (strlen(input) + 1 > max_output_length) + return 0; + + memcpy(output, input, strlen(input) + 1); + return 1; +} diff --git a/include/ipfs/blocks/block.h b/include/ipfs/blocks/block.h index f51f6c4..288c3f0 100644 --- a/include/ipfs/blocks/block.h +++ b/include/ipfs/blocks/block.h @@ -5,9 +5,12 @@ #ifndef __IPFS_BLOCKS_BLOCK_H__ #define __IPFS_BLOCKS_BLOCK_H__ +#include "ipfs/cid/cid.h" + struct Block { struct Cid* cid; unsigned char* data; + size_t data_length; }; /*** @@ -17,7 +20,7 @@ struct Block { * @param block a pointer to the struct Block that will be created * @returns true(1) on success */ -int ipfs_blocks_block_new(unsigned char* data, size_t data_size, struct Block** block); +int ipfs_blocks_block_new(const unsigned char* data, size_t data_size, struct Block** block); /*** * Free resources used by the creation of a block diff --git a/include/ipfs/blocks/blockstore.h b/include/ipfs/blocks/blockstore.h index a4e10d6..f102c28 100644 --- a/include/ipfs/blocks/blockstore.h +++ b/include/ipfs/blocks/blockstore.h @@ -10,14 +10,14 @@ * @param cid the Cid to look for * @param returns true(1) on success */ -int ipfs_blockstore_delete(struct Cid* cid); +int ipfs_blockstore_delete(struct Cid* cid, struct FSRepo* fs_repo); /*** * Determine if the Cid can be found * @param cid the Cid to look for * @returns true(1) if found */ -int ipfs_blockstore_has(struct Cid* cid); +int ipfs_blockstore_has(struct Cid* cid, struct FSRepo* fs_repo); /*** * Find a block based on its Cid @@ -25,14 +25,14 @@ int ipfs_blockstore_has(struct Cid* cid); * @param block where to put the data to be returned * @returns true(1) on success */ -int ipfs_blockstore_get(struct Cid* cid, struct Block* block); +int ipfs_blockstore_get(struct Cid* cid, struct Block* block, struct FSRepo* fs_repo); /*** * Put a block in the blockstore * @param block the block to store * @returns true(1) on success */ -int ipfs_blockstore_put(struct Block* block); +int ipfs_blockstore_put(struct Block* block, struct FSRepo* fs_repo); #endif diff --git a/include/ipfs/cid/cid.h b/include/ipfs/cid/cid.h index 1f1b168..e499c41 100644 --- a/include/ipfs/cid/cid.h +++ b/include/ipfs/cid/cid.h @@ -5,6 +5,8 @@ #ifndef __IPFS_CID_CID_H #define __IPFS_CID_CID_H +#include + #define CID_PROTOBUF 0x70 #define CID_CBOR 0x71 #define CID_RAW 0x72 diff --git a/include/ipfs/datastore/key.h b/include/ipfs/datastore/key.h new file mode 100644 index 0000000..626627a --- /dev/null +++ b/include/ipfs/datastore/key.h @@ -0,0 +1,14 @@ +#ifndef __IPFS_DATASTORE_KEY_H__ +#define __IPFS_DATASTORE_KEY_H__ + +/** + * Constructs a new "clean" key. Will remove things like slashes + * @param input the input + * @param output the output + * @param max_output_length the amount of memory allocated for output + * @param actual_output_length the amount of bytes written to output + * @returns true(1) on success + */ +int ipfs_datastore_key_new(const char* input, char* output, size_t max_output_length, size_t* actual_output_length); + +#endif diff --git a/include/ipfs/repo/config/config.h b/include/ipfs/repo/config/config.h index c8c978b..fc88071 100644 --- a/include/ipfs/repo/config/config.h +++ b/include/ipfs/repo/config/config.h @@ -72,7 +72,7 @@ int config_path(char* config_root, char* extension, char* result, int max_len); * @param num_bits_for_keypair number of bits for the key pair * @returns true(1) on success, otherwise 0 */ -int repo_config_init(struct RepoConfig* config, unsigned int num_bits_for_keypair, char* repo_path); +int ipfs_repo_config_init(struct RepoConfig* config, unsigned int num_bits_for_keypair, char* repo_path); /*** * Initialize memory for a RepoConfig struct diff --git a/include/ipfs/repo/config/datastore.h b/include/ipfs/repo/config/datastore.h index 40bd94f..d7804a8 100644 --- a/include/ipfs/repo/config/datastore.h +++ b/include/ipfs/repo/config/datastore.h @@ -2,6 +2,7 @@ #define __DATASTORE_H__ #include +#include "ipfs/blocks/block.h" //const char* datastore_default_directory = "datastore"; @@ -19,6 +20,8 @@ struct Datastore { // function pointers for datastore operations int (*datastore_open)(int argc, char** argv, struct Datastore* datastore); int (*datastore_close)(int argc, char** argv, struct Datastore* datastore); + int (*datastore_put)(const char* key, struct Block* block, struct Datastore* datastore); + //int (*datastore_get)(const char* key, struct Block* block); // a handle to the datastore "context" used by the datastore void* handle; }; diff --git a/include/ipfs/repo/fsrepo/fs_repo.h b/include/ipfs/repo/fsrepo/fs_repo.h index 1b93b25..89c9692 100644 --- a/include/ipfs/repo/fsrepo/fs_repo.h +++ b/include/ipfs/repo/fsrepo/fs_repo.h @@ -16,13 +16,11 @@ struct FSRepo { char* path; struct IOCloser* lock_file; struct RepoConfig* config; - struct Datastore* data_store; }; /** * opens a fsrepo - * @param repo_path the path to the repo - * @param repo where to store the repo info + * @param repo the repo struct. Should contain the path. This method will do the rest * @return 0 if there was a problem, otherwise 1 */ int ipfs_repo_fsrepo_open(struct FSRepo* repo); @@ -43,10 +41,12 @@ int fs_repo_is_initialized(char* repo_path); int fs_repo_write_config_file(char* path, struct RepoConfig* config); /** - * Initializes a new FSRepo at the given path with the provided config - * @param repo_path the path to use - * @param config the information for the config file - * @returns true(1) on success + * constructs the FSRepo struct. + * Remember: ipfs_repo_fsrepo_free must be called + * @param repo_path the path to the repo + * @param config the optional config file. NOTE: if passed, fsrepo_free will free resources of the RepoConfig. + * @param repo the struct to allocate memory for + * @returns false(0) if something bad happened, otherwise true(1) */ int ipfs_repo_fsrepo_new(char* repo_path, struct RepoConfig* config, struct FSRepo** fs_repo); diff --git a/include/ipfs/repo/fsrepo/lmdb_datastore.h b/include/ipfs/repo/fsrepo/lmdb_datastore.h index 38920b0..7a0a105 100644 --- a/include/ipfs/repo/fsrepo/lmdb_datastore.h +++ b/include/ipfs/repo/fsrepo/lmdb_datastore.h @@ -27,4 +27,11 @@ int repo_fsrepro_lmdb_open(int argc, char** argv, struct Datastore* datastore); */ int repo_fsrepo_lmdb_close(int argc, char** argv, struct Datastore* datastore); +/*** + * Creates the directory + * @param datastore contains the path that needs to be created + * @returns true(1) on success + */ +int repo_fsrepo_lmdb_create_directory(struct Datastore* datastore); + #endif diff --git a/include/ipfs/repo/repo.h b/include/ipfs/repo/repo.h deleted file mode 100644 index 23f6364..0000000 --- a/include/ipfs/repo/repo.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __REPO_H__ -#define __REPO_H__ - -#include - -#include "config/config.h" - -/** - * Get the config - * @param config a place to put the buffer (must have been pre-allocated) - * @returns 0 on error - */ -int repo_get_config(struct RepoConfig* config); - -/** - * Retrieves the config - * @param config a place to get the information - * @returns 0 on error - */ -int repo_set_config(struct RepoConfig* config); -int repo_set_config_key(char* key, void* value); -int repo_get_config_key(char* key, void* value); -int repo_get_datastore(struct Datastore* datastore); -int repo_get_storage_usage(uint64_t* usage); - -#endif // __REPO_H__ diff --git a/repo/Makefile b/repo/Makefile index e5db459..3277e1f 100644 --- a/repo/Makefile +++ b/repo/Makefile @@ -6,7 +6,7 @@ CFLAGS += -g3 endif DEPS = -OBJS = repo.o +OBJS = %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/repo/config/config.c b/repo/config/config.c index f86554d..61d417d 100644 --- a/repo/config/config.c +++ b/repo/config/config.c @@ -87,7 +87,7 @@ int repo_config_get_file_name(char* path, char** result) { * @param num_bits_for_keypair number of bits for the key pair * @returns true(1) on success, otherwise 0 */ -int repo_config_init(struct RepoConfig* config, unsigned int num_bits_for_keypair, char* repo_path) { +int ipfs_repo_config_init(struct RepoConfig* config, unsigned int num_bits_for_keypair, char* repo_path) { // identity int retVal = repo_config_identity_init(config->identity, num_bits_for_keypair); if (retVal == 0) diff --git a/repo/config/datastore.c b/repo/config/datastore.c index eaa874e..732cbf2 100644 --- a/repo/config/datastore.c +++ b/repo/config/datastore.c @@ -40,6 +40,7 @@ int ipfs_repo_config_datastore_new(struct Datastore** datastore) { if (*datastore == NULL) return 0; (*datastore)->path = NULL; + (*datastore)->handle = NULL; return 1; } diff --git a/repo/fsrepo/fs_repo.c b/repo/fsrepo/fs_repo.c index 74c0a4e..e20d317 100644 --- a/repo/fsrepo/fs_repo.c +++ b/repo/fsrepo/fs_repo.c @@ -109,7 +109,7 @@ int repo_config_write_config_file(char* full_filename, struct RepoConfig* config * Remember: ipfs_repo_fsrepo_free must be called * @param repo_path the path to the repo * @param config the optional config file. NOTE: if passed, fsrepo_free will free resources of the RepoConfig. - * @param repo the struct to fill in + * @param repo the struct to allocate memory for * @returns false(0) if something bad happened, otherwise true(1) */ int ipfs_repo_fsrepo_new(char* repo_path, struct RepoConfig* config, struct FSRepo** repo) { @@ -140,11 +140,6 @@ int ipfs_repo_fsrepo_new(char* repo_path, struct RepoConfig* config, struct FSRe return 0; } } - if (ipfs_repo_config_datastore_new(&((*repo)->data_store)) == 0) { - free(repo_path); - ipfs_repo_config_free((*repo)->config); - return 0; - } return 1; } @@ -159,8 +154,6 @@ int ipfs_repo_fsrepo_free(struct FSRepo* repo) { free(repo->path); if (repo->config != NULL) ipfs_repo_config_free(repo->config); - if (repo->data_store != NULL) - ipfs_repo_config_datastore_free(repo->data_store); free(repo); } return 1; @@ -347,7 +340,7 @@ int fs_repo_open_config(struct FSRepo* repo) { return 0; } // fill FSRepo struct - repo->config = malloc(sizeof(struct RepoConfig)); + // allocation done by fsrepo_new... repo->config = malloc(sizeof(struct RepoConfig)); // Identity int curr_pos = _find_token(data, tokens, num_tokens, 0, "Identity"); if (curr_pos < 0) { @@ -389,7 +382,7 @@ int fs_repo_open_config(struct FSRepo* repo) { * @returns true(1) on success */ int fs_repo_setup_lmdb_datastore(struct FSRepo* repo) { - return repo_fsrepo_lmdb_cast(repo->data_store); + return repo_fsrepo_lmdb_cast(repo->config->datastore); } /*** @@ -401,10 +394,7 @@ int fs_repo_open_datastore(struct FSRepo* repo) { int argc = 0; char** argv = NULL; - // copy struct from config area to this area - repo->data_store = repo->config->datastore; - - if (strncmp(repo->data_store->type, "lmdb", 4) == 0) { + if (strncmp(repo->config->datastore->type, "lmdb", 4) == 0) { // this is a LightningDB. Open it. int retVal = fs_repo_setup_lmdb_datastore(repo); if (retVal == 0) @@ -414,7 +404,7 @@ int fs_repo_open_datastore(struct FSRepo* repo) { return 0; } - int retVal = repo->data_store->datastore_open(argc, argv, repo->data_store); + int retVal = repo->config->datastore->datastore_open(argc, argv, repo->config->datastore); // do specific datastore cleanup here if needed @@ -463,6 +453,14 @@ int fs_repo_is_initialized(char* repo_path) { return fs_repo_is_initialized_unsynced(repo_path); } +int ipfs_repo_fsrepo_datastore_init(struct FSRepo* fs_repo) { + // make the directory + repo_fsrepo_lmdb_create_directory(fs_repo->config->datastore); + + // fill in the function prototypes + repo_fsrepo_lmdb_cast(fs_repo->config->datastore); +} + /** * Initializes a new FSRepo at the given path with the provided config * @param path the path to use @@ -481,7 +479,7 @@ int ipfs_repo_fsrepo_init(struct FSRepo* repo) { return 0; // TODO: Implement this method - //retVal = fs_repo_defaultds_init(path, config); + retVal = ipfs_repo_fsrepo_datastore_init(repo); if (retVal == 0) return 0; diff --git a/repo/fsrepo/lmdb_datastore.c b/repo/fsrepo/lmdb_datastore.c index c3f0cf9..5e9d902 100644 --- a/repo/fsrepo/lmdb_datastore.c +++ b/repo/fsrepo/lmdb_datastore.c @@ -3,10 +3,55 @@ */ #include +#include +#include +#include #include "lmdb.h" #include "ipfs/repo/fsrepo/lmdb_datastore.h" +/** + * Write a block to the datastore with the specified key + * @param key the key + * @param block the block to be written + * @returns true(1) on success + */ +int repo_fsrepo_lmdb_put(const char* key, struct Block* block, struct Datastore* datastore) { + int retVal; + MDB_txn* mdb_txn; + MDB_dbi mdb_dbi; + struct MDB_val db_key; + struct MDB_val db_value; + + MDB_env* mdb_env = (MDB_env*)datastore->handle; + if (mdb_env == NULL) + return 0; + + // open transaction + retVal = mdb_txn_begin(mdb_env, NULL, 0, &mdb_txn); + if (retVal != 0) + return 0; + retVal = mdb_dbi_open(mdb_txn, NULL, 0, &mdb_dbi); + if (retVal != 0) + return 0; + + // write + db_key.mv_size = strlen(key) + 1; + db_key.mv_data = (char*)key; + db_value.mv_size = block->data_length; + db_value.mv_data = block->data; + retVal = mdb_put(mdb_txn, mdb_dbi, &db_key, &db_value, MDB_NODUPDATA); + if (retVal != 0) + return 0; + + // cleanup + mdb_dbi_close(mdb_env, mdb_dbi); + mdb_txn_commit(mdb_txn); + return 1; +} + + + /** * Open an lmdb database with the given parameters. * Note: for now, the parameters are not used @@ -23,7 +68,7 @@ int repo_fsrepro_lmdb_open(int argc, char** argv, struct Datastore* datastore) { } // open the environment - retVal = mdb_env_open(mdb_env, datastore->path, 0, 755); + retVal = mdb_env_open(mdb_env, datastore->path, 0, S_IRWXU); if (retVal < 0) { mdb_env_close(mdb_env); return 0; @@ -55,6 +100,17 @@ int repo_fsrepo_lmdb_close(int argc, char** argv, struct Datastore* datastore) { int repo_fsrepo_lmdb_cast(struct Datastore* datastore) { datastore->datastore_open = &repo_fsrepro_lmdb_open; datastore->datastore_close = &repo_fsrepo_lmdb_close; + datastore->datastore_put = &repo_fsrepo_lmdb_put; + //datastore->datastore_get = &repo_fsrepo_lmdb_get; return 1; } +/*** + * Creates the directory + * @param datastore contains the path that needs to be created + * @returns true(1) on success + */ +int repo_fsrepo_lmdb_create_directory(struct Datastore* datastore) { + return mkdir(datastore->path, S_IRWXU) == 0; +} + diff --git a/repo/repo.c b/repo/repo.c deleted file mode 100644 index 67e0a61..0000000 --- a/repo/repo.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "ipfs/repo/repo.h" - -int repo_get_config(struct RepoConfig* config) { - return 0; -} - diff --git a/test/Makefile b/test/Makefile index 37d3fe4..61045ae 100644 --- a/test/Makefile +++ b/test/Makefile @@ -8,7 +8,8 @@ OBJS = testit.o ../cmd/ipfs/init.o ../commands/argument.o ../commands/command_op ../repo/config/bootstrap_peers.o ../repo/config/datastore.o ../repo/config/gateway.o \ ../repo/config/addresses.o ../repo/config/swarm.o ../repo/config/peer.o \ ../thirdparty/ipfsaddr/ipfs_addr.o ../cid/cid.o ../multibase/multibase.o \ - ../flatfs/flatfs.o ../datastore/ds_helper.o + ../flatfs/flatfs.o ../blocks/block.o ../blocks/blockstore.o \ + ../datastore/ds_helper.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/test/repo/test_repo_config.h b/test/repo/test_repo_config.h index 612eae8..ef5dcc7 100644 --- a/test/repo/test_repo_config.h +++ b/test/repo/test_repo_config.h @@ -32,7 +32,7 @@ int test_repo_config_init() { if (retVal == 0) return 0; - retVal = repo_config_init(repoConfig, 2048, "/Users/JohnJones/.ipfs"); + retVal = ipfs_repo_config_init(repoConfig, 2048, "/Users/JohnJones/.ipfs"); if (retVal == 0) return 0; @@ -77,7 +77,7 @@ int test_repo_config_write() { // now build a new one struct RepoConfig* repoConfig; ipfs_repo_config_new(&repoConfig); - if (!repo_config_init(repoConfig, 2048, "/tmp/.ipfs")) { + if (!ipfs_repo_config_init(repoConfig, 2048, "/tmp/.ipfs")) { ipfs_repo_config_free(repoConfig); return 0; } diff --git a/test/storage/test_blocks.h b/test/storage/test_blocks.h new file mode 100644 index 0000000..2636538 --- /dev/null +++ b/test/storage/test_blocks.h @@ -0,0 +1,36 @@ +#include "ipfs/blocks/block.h" + +int test_blocks_new() { + const char* input = "Hello, World!"; + int retVal = 0; + struct Block* block; + retVal = ipfs_blocks_block_new(input, strlen(input) + 1, &block); + if (retVal == 0) + return 0; + + // now examine the block + if (strcmp(block->data, input) != 0) + return 0; + + if (block->data_length != strlen(input) + 1) + return 0; + + if (block->cid->codec != CID_PROTOBUF) + return 0; + + if (block->cid->version != 0) + return 0; + + if (block->cid->hash_length != 32) + return 0; + + unsigned char result_hash[32] = {33, 153, 66, 187, 124, 250, 87, 12, 12, 73, 43, 247, 175, 153, 10, 51, 192, 195, 218, 69, 220, 170, 105, 179, 195, 0, 203, 213, 172, 3, 244, 10 }; + for(int i = 0; i < 32; i++) { + if (block->cid->hash[i] != result_hash[i]) + return 0; + } + + retVal = ipfs_blocks_block_free(block); + + return 1; +} diff --git a/test/storage/test_blockstore.h b/test/storage/test_blockstore.h new file mode 100644 index 0000000..149f218 --- /dev/null +++ b/test/storage/test_blockstore.h @@ -0,0 +1,20 @@ +#include + +#include "ipfs/blocks/blockstore.h" +#include "ipfs/blocks/block.h" + +int test_blockstore_put() { + const unsigned char* input_string = "Hello, World!"; + struct Block* input_block; + int retVal = 0; + + retVal = ipfs_blocks_block_new(input_string, strlen((const char*)input_string) + 1, &input_block); + if (retVal == 0) + return 0; + + retVal = ipfs_blockstore_put(input_block); + if (retVal == 0) + return 0; + + return 1; +} diff --git a/test/storage/test_datastore.h b/test/storage/test_datastore.h new file mode 100644 index 0000000..fdd81fa --- /dev/null +++ b/test/storage/test_datastore.h @@ -0,0 +1,148 @@ +#include "libp2p/crypto/encoding/base32.h" +#include "ipfs/datastore/ds_helper.h" +#include "ipfs/blocks/block.h" +#include "ipfs/repo/config/config.h" +#include "ipfs/repo/fsrepo/fs_repo.h" + +#include +#include + +int remove_directory(const char *path) +{ + DIR *d = opendir(path); + size_t path_len = strlen(path); + int r = -1; + + if (d) + { + struct dirent *p; + + r = 0; + + while (!r && (p=readdir(d))) + { + int r2 = -1; + char *buf; + size_t len; + + /* Skip the names "." and ".." as we don't want to recurse on them. */ + if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) + { + continue; + } + + len = path_len + strlen(p->d_name) + 2; + buf = malloc(len); + + if (buf) + { + struct stat statbuf; + + snprintf(buf, len, "%s/%s", path, p->d_name); + + if (!stat(buf, &statbuf)) + { + if (S_ISDIR(statbuf.st_mode)) + { + r2 = remove_directory(buf); + } + else + { + r2 = unlink(buf); + } + } + + free(buf); + } + + r = r2; + } + + closedir(d); + } + + if (!r) + { + r = rmdir(path); + } + + return r; +} + +int make_ipfs_repository(struct FSRepo* fs_repo) { + int retVal; + struct RepoConfig* repo_config; + + unlink("/tmp/.ipfs/config"); + remove_directory("/tmp/.ipfs/datastore"); + remove_directory("/tmp/.ipfs/blockstore"); + + // build a default repo config + retVal = ipfs_repo_config_new(&repo_config); + if (retVal == 0) + return 0; + retVal = ipfs_repo_config_init(repo_config, 2048, "/tmp/.ipfs"); + if (retVal == 0) + return 0; + // now the fs_repo + retVal = ipfs_repo_fsrepo_new("/tmp/.ipfs", repo_config, &fs_repo); + if (retVal == 0) + return 0; + // this builds a new repo + retVal = ipfs_repo_fsrepo_init(fs_repo); + if (retVal == 0) + return 0; + + // clean up + ipfs_repo_fsrepo_free(fs_repo); + // this is cleaned up by fsrepo_free + //ipfs_repo_config_free(repo_config); + + // make sure the repository exists + retVal = os_utils_file_exists("/tmp/.ipfs/config"); + return retVal; +} + +int test_ipfs_datastore_put() { + struct Block* block; + int retVal; + const unsigned char* input = "Hello, world!"; + + // build the ipfs repository, then shut it down, so we can start fresh + struct FSRepo* fs_repo; + retVal = make_ipfs_repository(fs_repo); + ipfs_repo_fsrepo_free(fs_repo); + if (retVal == 0) + return 0; + + // build the block + retVal = ipfs_blocks_block_new(input, strlen((char*)input), &block); + if (retVal == 0) + return 0; + + // generate the key + size_t key_length = libp2p_crypto_encoding_base32_encode_size(block->data_length); + unsigned char key[key_length]; + retVal = ipfs_datastore_helper_ds_key_from_binary(block->data, block->data_length, &key[0], key_length, &key_length); + if (retVal == 0) + return 0; + + // open the repository + retVal = ipfs_repo_fsrepo_new("/tmp/.ipfs", NULL, &fs_repo); + if (retVal == 0) + return 0; + retVal = ipfs_repo_fsrepo_open(fs_repo); + if (retVal == 0) + return 0; + + // send to Put with key + retVal = fs_repo->config->datastore->datastore_put(key, block, fs_repo->config->datastore); + if (retVal == 0) + return 0; + + // save the block + + // check the results + + return 1; +} diff --git a/test/testit.c b/test/testit.c index b005073..7b21f52 100644 --- a/test/testit.c +++ b/test/testit.c @@ -6,6 +6,8 @@ #include "cid/test_cid.h" #include "flatfs/test_flatfs.h" #include "storage/test_ds_helper.h" +#include "storage/test_datastore.h" +#include "storage/test_blocks.h" int testit(const char* name, int (*func)(void)) { printf("Testing %s...\n", name); @@ -19,6 +21,7 @@ int testit(const char* name, int (*func)(void)) { int main(int argc, char** argv) { int counter = 0; + /* counter += testit("test_cid_new_free", test_cid_new_free); counter += testit("test_cid_cast_multihash", test_cid_cast_multihash); counter += testit("test_cid_cast_non_multihash", test_cid_cast_non_multihash); @@ -35,6 +38,9 @@ int main(int argc, char** argv) { counter += testit("test_flatfs_get_filename", test_flatfs_get_filename); counter += testit("test_flatfs_get_full_filename", test_flatfs_get_full_filename); counter += testit("test_ds_key_from_binary", test_ds_key_from_binary); + counter += testit("test_blocks_new", test_blocks_new); + */ + counter += testit("test_ipfs_datastore_put", test_ipfs_datastore_put); if (counter > 0) { printf("***** There were %d failed test(s) *****\n", counter); } else {