diff --git a/include/libaktualizr-c.h b/include/libaktualizr-c.h index e321ef4073..e614873f83 100644 --- a/include/libaktualizr-c.h +++ b/include/libaktualizr-c.h @@ -1,6 +1,8 @@ #ifndef AKTUALIZR_LIBAKTUALIZRC_H #define AKTUALIZR_LIBAKTUALIZRC_H +#include // for uint8_t + #ifdef __cplusplus #include "primary/aktualizr.h" @@ -38,6 +40,13 @@ int Aktualizr_download_target(Aktualizr *a, Target *t); int Aktualizr_install_target(Aktualizr *a, Target *t); +int Aktualizr_send_manifest(Aktualizr *a, const char *manifest); +int Aktualizr_send_device_data(Aktualizr *a); + +void *Aktualizr_open_stored_target(Aktualizr *a, const char *filename, const char *content); +size_t Aktualizr_read_stored_target(void *handle, uint8_t* buf, size_t size); +int Aktualizr_close_stored_target(void *handle); + #ifdef __cplusplus } #endif diff --git a/src/libaktualizr-c/libaktualizr-c.cc b/src/libaktualizr-c/libaktualizr-c.cc index a4369f1bd4..f2c702d511 100644 --- a/src/libaktualizr-c/libaktualizr-c.cc +++ b/src/libaktualizr-c/libaktualizr-c.cc @@ -47,6 +47,7 @@ Campaign *Aktualizr_campaigns_check(Aktualizr *a) { } return nullptr; } + int Aktualizr_campaign_accept(Aktualizr *a, Campaign *c) { try { a->CampaignControl(c->id, campaign::Cmd::Accept).get(); @@ -56,6 +57,7 @@ int Aktualizr_campaign_accept(Aktualizr *a, Campaign *c) { } return 0; } + int Aktualizr_campaign_postpone(Aktualizr *a, Campaign *c) { try { a->CampaignControl(c->id, campaign::Cmd::Postpone).get(); @@ -65,6 +67,7 @@ int Aktualizr_campaign_postpone(Aktualizr *a, Campaign *c) { } return 0; } + int Aktualizr_campaign_decline(Aktualizr *a, Campaign *c) { try { a->CampaignControl(c->id, campaign::Cmd::Decline).get(); @@ -105,7 +108,7 @@ Target *Aktualizr_get_nth_target(Updates *u, size_t n) { } // TODO: leaks memory. Would it be nicer if t->filename returned const ref? -const char *Aktualizr_get_target_name(Target *t) { +const char *Aktualizr_get_target_name(Target *t) { if (t) { auto name = new std::string(std::move(t->filename())); return name->c_str(); @@ -114,7 +117,6 @@ const char *Aktualizr_get_target_name(Target *t) { } } - int Aktualizr_download_target(Aktualizr *a, Target *t) { try { a->Download(std::vector({*t})).get(); @@ -135,3 +137,70 @@ int Aktualizr_install_target(Aktualizr *a, Target *t) { return 0; } +int Aktualizr_send_manifest(Aktualizr *a, const char *manifest) { + try { + Json::Value custom = Utils::parseJSON(manifest); + bool r = a->SendManifest(custom).get(); + return r ? 0 : -1; + } catch (const std::exception &e) { + std::cerr << "Aktualizr_send_manifest exception: " << e.what() << std::endl; + return -1; + } +} + +int Aktualizr_send_device_data(Aktualizr *a) { + try { + a->SendDeviceData(); + return 0; + } catch (const std::exception &e) { + std::cerr << "Aktualizr_send_device_data exception: " << e.what() << std::endl; + return -1; + } +} + +void *Aktualizr_open_stored_target(Aktualizr *a, const char *filename, const char *content) { + if (filename == nullptr || content == nullptr) { + std::cerr << "Aktualizr_open_stored_target failed: invalid input " + << (filename ? "content" : "filename") << std::endl; + return nullptr; + } + + Json::Value value; + Json::Reader reader; + if (!reader.parse(content, value)) { + std::cerr << "Aktualizr_open_stored_target content parsing failed" << std::endl; + return nullptr; + } + + Uptane::Target target(filename, value); + try { + auto handle = a->OpenStoredTarget(target); + return reinterpret_cast(handle.release()); + } catch (const std::exception &e) { + std::cerr << "Aktualizr_open_stored_target exception: " << e.what() << std::endl; + return nullptr; + } +} + +size_t Aktualizr_read_stored_target(void *handle, uint8_t *buf, size_t size) { + if (handle && buf) { + StorageTargetRHandle *target_handle = reinterpret_cast(handle); + return target_handle->rread(buf, size); + } else { + std::cerr << "Aktualizr_read_stored_target failed: invalid input " + << (handle ? "buffer" : "handle") << std::endl; + return 0; + } +} + +int Aktualizr_close_stored_target(void *handle) { + if (handle) { + StorageTargetRHandle *target_handle = reinterpret_cast(handle); + target_handle->rclose(); + delete target_handle; + return 0; + } else { + std::cerr << "Aktualizr_close_stored_target failed: no input handle" << std::endl; + return -1; + } +} diff --git a/src/libaktualizr-c/test/api-test.c b/src/libaktualizr-c/test/api-test.c index 66af2031e6..d40f3d20a7 100644 --- a/src/libaktualizr-c/test/api-test.c +++ b/src/libaktualizr-c/test/api-test.c @@ -27,7 +27,7 @@ int main(int argc, char **argv) { c = Aktualizr_campaigns_check(a); if (c) { - printf("Accepting running campaign\n"); + fprintf(stdout, "Accepting running campaign\n"); err = Aktualizr_campaign_accept(a, c); Aktualizr_campaign_free(c); if (err) { @@ -38,14 +38,14 @@ int main(int argc, char **argv) { u = Aktualizr_updates_check(a); if (u) { size_t n = Aktualizr_get_targets_num(u); - printf("Found new updates for %zu target(s)\n", n); + fprintf(stdout, "Found new updates for %zu target(s)\n", n); for (size_t i = 0; i < n; i++) { t = Aktualizr_get_nth_target(u, i); - printf("Downloading target %s\n", Aktualizr_get_target_name(t)); + fprintf(stdout, "Downloading target %s\n", Aktualizr_get_target_name(t)); Aktualizr_download_target(a, t); - printf("Installing...\n"); + fprintf(stdout, "Installing...\n"); Aktualizr_install_target(a, t); - printf("Installation completed\n"); + fprintf(stdout, "Installation completed\n"); } } #if 0 @@ -54,6 +54,46 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } #endif + + err = Aktualizr_send_manifest(a, R"({"test_field":"test_value"})"); + if (err) { + return EXIT_FAILURE; + } + + err = Aktualizr_send_device_data(a); + if (err) { + return EXIT_FAILURE; + } + + // TODO: Remove hardcoded filename and content + const char *const filename = "Software2_Version2"; + const char *const content = + "{\"hashes\" : {" + "\"sha256\" : \"6F0CF24ADE13FFF76E943C003413D85C3E497C984C95C1ECEA1C9731CA86F13C\"," + "\"sha512\" : \"\"}," + "\"length\" : 2}"; + + void *handle = Aktualizr_open_stored_target(a, filename, content); + if (!handle) { + return EXIT_FAILURE; + } + + const size_t bufSize = 1024; + uint8_t *buf = malloc(bufSize); + size_t size = Aktualizr_read_stored_target(handle, buf, bufSize); + fprintf(stdout, "Downloading target %s: extracted %li bytes, content: ", filename, (long int)size); + for (size_t i = 0; i < bufSize; ++i) + fprintf(stdout, "%c", buf[i]); + free(buf); + if (size == 0) { + return EXIT_FAILURE; + } + + err = Aktualizr_close_stored_target(handle); + if (err) { + return EXIT_FAILURE; + } + Aktualizr_destroy(a); return EXIT_SUCCESS;