diff --git a/include/ipfs/repo/config/config.h b/include/ipfs/repo/config/config.h index 45c690d..3d959e7 100644 --- a/include/ipfs/repo/config/config.h +++ b/include/ipfs/repo/config/config.h @@ -52,7 +52,7 @@ struct RepoConfig { * @param result the full filename including the path * @returns true(1) on success, false(0) otherwise */ -int config_get_file_name(char* path, char* result); +int repo_config_get_file_name(char* path, char** result); /*** * Returns the path "extension" relative to the configuration root. diff --git a/include/ipfs/repo/fsrepo/fs_repo.h b/include/ipfs/repo/fsrepo/fs_repo.h index b02ba3e..490aec8 100644 --- a/include/ipfs/repo/fsrepo/fs_repo.h +++ b/include/ipfs/repo/fsrepo/fs_repo.h @@ -5,6 +5,8 @@ #define fs_repo_h #include +#include "ipfs/repo/config/config.h" + /** * a structure to hold the repo info @@ -32,4 +34,13 @@ int fs_repo_open(char* repo_path, struct FSRepo* repo); */ int fs_repo_is_initialized(char* repo_path); +/** + * write the config file to disk + * @param path the path to the file + * @param config the config structure + * @returns true(1) on success + */ +int fs_repo_write_config_file(char* path, struct RepoConfig* config); + + #endif /* fs_repo_h */ diff --git a/repo/config/config.c b/repo/config/config.c index 1daac05..8afde8c 100644 --- a/repo/config/config.c +++ b/repo/config/config.c @@ -72,8 +72,13 @@ int config_path(char* config_root, char* extension, char* result, int max_len) { * @param result the full filename including the path * @returns true(1) on success, false(0) otherwise */ -int config_get_file_name(char* path, char* result) { - return 0; +int repo_config_get_file_name(char* path, char** result) { + unsigned long max_len = strlen(path) + 8; + *result = malloc(sizeof(char) * max_len); + if (result == NULL) + return 0; + + return os_utils_filepath_join(path, "/config", *result, max_len); } /*** diff --git a/repo/config/swarm.c b/repo/config/swarm.c index a42ef09..80b9288 100644 --- a/repo/config/swarm.c +++ b/repo/config/swarm.c @@ -28,6 +28,8 @@ int repo_config_swarm_address_init(struct SwarmAddresses* swarm_addresses, char* swarm_addresses->addresses[i] = newString; } + swarm_addresses->num_addresses = array_length; + return 1; } diff --git a/repo/fsrepo/fs_repo.c b/repo/fsrepo/fs_repo.c index 69044c3..0111090 100644 --- a/repo/fsrepo/fs_repo.c +++ b/repo/fsrepo/fs_repo.c @@ -7,12 +7,90 @@ // #include "fs_repo.h" -#include "ipfs/repo/config/config.h" #include "ipfs/os/utils.h" /** * private methods */ +/** + * writes the config file + * @param full_filename the full filename of the config file in the OS + * @param config the details to put into the file + * @returns true(1) on success, else false(0) + */ +int repo_config_write_config_file(char* full_filename, struct RepoConfig* config) { + FILE* out_file = fopen(full_filename, "w"); + if (out_file == NULL) + return 0; + + fprintf(out_file, "{\n"); + fprintf(out_file, " \"Identity\": {\n"); + fprintf(out_file, " \"PeerID\": \"%s\",\n", config->identity.peer_id); + // TODO: print correct format of private key + //fprintf(out_file, " \"PrivKey\": \"%s\"\n", config->identity.private_key.base64); + fprintf(out_file, " },\n"); + fprintf(out_file, " \"Datastore\": {\n"); + fprintf(out_file, " \"Type\": \"%s\",\n", config->datastore.type); + fprintf(out_file, " \"Path\": \"%s\",\n", config->datastore.path); + fprintf(out_file, " \"StorageMax\": \"%s\",\n", config->datastore.storage_max); + fprintf(out_file, " \"StorageGCWatermark\": %d,\n", config->datastore.storage_gc_watermark); + fprintf(out_file, " \"GCPeriod\": \"%s\",\n", config->datastore.gc_period); + fprintf(out_file, " \"Params\": null,\n"); + fprintf(out_file, " \"NoSync\": %s,\n", config->datastore.no_sync ? "true" : "false"); + fprintf(out_file, " \"HashOnRead\": %s,\n", config->datastore.hash_on_read ? "true" : "false"); + fprintf(out_file, " \"BloomFilterSize\": %d\n", config->datastore.bloom_filter_size); + fprintf(out_file, " },\n \"Addresses\": {\n"); + fprintf(out_file, " \"Swarm\": [\n"); + for(int i = 0; i < config->addresses.swarm.num_addresses; i++) { + fprintf(out_file, " \"%s\"", config->addresses.swarm.addresses[i]); + if (i != (config->addresses.swarm.num_addresses - 1)) + fprintf(out_file, ",\n"); + else + fprintf(out_file, "\n"); + } + fprintf(out_file, " ],\n"); + fprintf(out_file, " \"API\": \"%s\",\n", config->addresses.api); + fprintf(out_file, " \"Gateway\": \"%s\"\n", config->addresses.gateway); + fprintf(out_file, " }\n \"Mounts\": {\n"); + fprintf(out_file, " \"IPFS\": \"%s\",\n", config->mounts.ipfs); + fprintf(out_file, " \"IPNS\": \"%s\",\n", config->mounts.ipns); + fprintf(out_file, " \"FuseAllowOther\": %s\n", "false"); + fprintf(out_file, " },\n \"Discovery\": {\n \"MDNS\": {\n"); + fprintf(out_file, " \"Enabled\": %s,\n", config->discovery.mdns.enabled ? "true" : "false"); + fprintf(out_file, " \"Interval\": %d\n }\n },\n", config->discovery.mdns.interval); + fprintf(out_file, " \"Ipns\": {\n"); + fprintf(out_file, " \"RepublishedPeriod\": \"\",\n"); + fprintf(out_file, " \"RecordLifetime\": \"\",\n"); + fprintf(out_file, " \"ResolveCacheSize\": %d\n", config->ipns.resolve_cache_size); + fprintf(out_file, " },\n \"Bootstrap\": [\n"); + for(int i = 0; i < config->peer_addresses.num_peers; i++) { + fprintf(out_file, " \"%s\"", config->peer_addresses.peers[i]->entire_string); + if (i < config->peer_addresses.num_peers - 1) + fprintf(out_file, ",\n"); + else + fprintf(out_file, "\n"); + } + fprintf(out_file, " ],\n \"Tour\": {\n \"Last\": \"\"\n },\n"); + fprintf(out_file, " \"Gateway\": {\n"); + fprintf(out_file, " \"HTTPHeaders\": {\n"); + for (int i = 0; i < config->gateway.http_headers.num_elements; i++) { + fprintf(out_file, " \"%s\": [\n \"%s\"\n ]", config->gateway.http_headers.headers[i]->header, config->gateway.http_headers.headers[i]->value); + if (i < config->gateway.http_headers.num_elements - 1) + fprintf(out_file, ",\n"); + else + fprintf(out_file, "\n"); + } + fprintf(out_file, " \"RootRedirect\": \"%s\"\n", config->gateway.root_redirect); + fprintf(out_file, " \"Writable\": %s\n", config->gateway.writable ? "true" : "false"); + fprintf(out_file, " \"PathPrefixes\": []\n"); + fprintf(out_file, " },\n \"SupernodeRouting\": {\n"); + fprintf(out_file, " \"Servers\": null\n },"); + fprintf(out_file, " \"API\": {\n \"HTTPHeaders\": null\n },\n"); + fprintf(out_file, " \"Swarm\": {\n \"AddrFilters\": null\n }\n}"); + fclose(out_file); + return 1; +} + /** * constructs the FSRepo struct. Basically fills in the FSRepo.path * Remember: the path must be freed @@ -37,11 +115,16 @@ int repo_new_fs_repo(char* repo_path, struct FSRepo* repo) { */ int repo_config_is_initialized(char* full_path) { char* config_file_full_path; - int retVal = config_get_file_name(full_path, config_file_full_path); + int retVal = repo_config_get_file_name(full_path, &config_file_full_path); if (!retVal) return 0; + if (os_utils_file_exists(config_file_full_path)) retVal = 1; + else + retVal = 0; + + free(config_file_full_path); return retVal; } @@ -85,7 +168,6 @@ int fs_repo_open_datastore(struct FSRepo* repo) { return 0; } - /** * public methods */ @@ -128,3 +210,45 @@ int fs_repo_is_initialized(char* repo_path) { return fs_repo_is_initialized_unsynced(repo_path); } +int fs_repo_init(char* path, struct RepoConfig* config) { + // TODO: Do a lock so 2 don't do this at the same time + + // return error if this has already been done + if (fs_repo_is_initialized_unsynced(path)) + return 0; + + int retVal = fs_repo_write_config_file(path, config); + if (retVal == 0) + return 0; + + // TODO: Implement this method + retVal = fs_repo_defaultds_init(path, config); + if (retVal == 0) + return 0; + + // write the version to a file for migrations (see repo/fsrepo/migrations/mfsr.go) + //TODO: mfsr.RepoPath(repo_path).WriteVersion(RepoVersion) + return 1; +} + +/** + * write the config file to disk + * @param path the path to the file + * @param config the config structure + * @returns true(1) on success + */ +int fs_repo_write_config_file(char* path, struct RepoConfig* config) { + if (fs_repo_is_initialized(path)) + return 0; + + char* buff = NULL; + if (!repo_config_get_file_name(path, &buff)) + return 0; + + int retVal = repo_config_write_config_file(buff, config); + + free(buff); + + return retVal; +} + diff --git a/test/repo/test_repo_config.h b/test/repo/test_repo_config.h index fff3b5b..46cf385 100644 --- a/test/repo/test_repo_config.h +++ b/test/repo/test_repo_config.h @@ -10,6 +10,8 @@ #define test_repo_config_h #include "ipfs/repo/config/config.h" +#include "ipfs/repo/fsrepo/fs_repo.h" +#include "ipfs/os/utils.h" int test_repo_config_init() { struct RepoConfig repoConfig; @@ -27,6 +29,17 @@ int test_repo_config_init() { if (retVal != 0) return 0; + if (repoConfig.addresses.swarm.num_addresses != 2) + return 0; + + retVal = strncmp(repoConfig.addresses.swarm.addresses[0], "/ip4/0.0.0.0/tcp/4001", 21); + if (retVal != 0) + return 0; + + retVal = strncmp(repoConfig.addresses.swarm.addresses[1], "/ip6/::/tcp/4001", 16); + if (retVal != 0) + return 0; + // datastore retVal = strncmp(repoConfig.datastore.path, "/Users/JohnJones/.ipfs/datastore", 32); if (retVal != 0) @@ -37,4 +50,29 @@ int test_repo_config_init() { return 1; } +/*** + * test the writing of the config file + */ +int test_repo_config_write() { + // first delete the existing one + unlink("/tmp/config"); + + // now build a new one + struct RepoConfig repoConfig; + if (!repo_config_init(&repoConfig, 2048, "/tmp")) { + repo_config_free(&repoConfig); + return 0; + } + + if (!fs_repo_write_config_file("/tmp", &repoConfig)) { + repo_config_free(&repoConfig); + return 0; + } + + repo_config_free(&repoConfig); + + // check to see if the file exists + return os_utils_file_exists("/tmp/config"); +} + #endif /* test_repo_config_h */ diff --git a/test/testit.c b/test/testit.c index 8ae566b..08674df 100644 --- a/test/testit.c +++ b/test/testit.c @@ -16,6 +16,7 @@ int testit(const char* name, int (*func)(void)) { int main(int argc, char** argv) { testit("test_repo_config_init", test_repo_config_init); + testit("test_repo_config_write", test_repo_config_write); testit("test_repo_config_identity_new", test_repo_config_identity_new); testit("test_repo_config_identity_private_key", test_repo_config_identity_private_key); testit("test_reop_bootstrap_peers_init", test_repo_bootstrap_peers_init);