From 362045400a168268c2896936c4cd2813a1778113 Mon Sep 17 00:00:00 2001 From: Felicity Date: Mon, 7 Oct 2024 17:59:44 +0000 Subject: [PATCH 01/13] Added a new dependency -- libzip --- CMakeLists.txt | 1 + docs/INSTALL.md | 3 ++- ggl-file/CMakeLists.txt | 3 ++- nix/package.nix | 2 ++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 381fbd2ad..ab751a442 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -233,6 +233,7 @@ pkg_search_module(libsystemd REQUIRED IMPORTED_TARGET libsystemd) pkg_search_module(uuid REQUIRED IMPORTED_TARGET uuid) pkg_search_module(libevent REQUIRED IMPORTED_TARGET libevent) pkg_search_module(liburiparser REQUIRED IMPORTED_TARGET liburiparser) +pkg_search_module(libzip REQUIRED IMPORTED_TARGET libzip) include(CheckCSourceCompiles) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index c6f6aba2c..3e3faa8a0 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -17,12 +17,13 @@ This project uses the following third party library dependencies: - liburiparser - libuuid - libevent +- libzip On Ubuntu, these can be installed with: ```sh sudo apt install libssl-dev libcurl4-openssl-dev libsqlite3-dev libyaml-dev \ - libsystemd-dev liburiparser-dev uuid-dev libevent-dev + libsystemd-dev liburiparser-dev uuid-dev libevent-dev libzip-dev ``` ## Build tools diff --git a/ggl-file/CMakeLists.txt b/ggl-file/CMakeLists.txt index aea4b460b..825fe29f8 100644 --- a/ggl-file/CMakeLists.txt +++ b/ggl-file/CMakeLists.txt @@ -2,4 +2,5 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -ggl_init_module(ggl-file LIBS ggl-lib ggl-socket) + +ggl_init_module(ggl-file LIBS ggl-lib ggl-socket PkgConfig::libzip) diff --git a/nix/package.nix b/nix/package.nix index be34f47f4..101f98d5e 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -12,6 +12,7 @@ , argp-standalone , sqlite , libyaml +, libzip , dbus , systemdLibs , defaultMeta @@ -30,6 +31,7 @@ stdenv.mkDerivation { libyaml.dev dbus systemdLibs + libzip ] ++ lib.optional (!stdenv.hostPlatform.isGnu) argp-standalone; cmakeBuildType = "MinSizeRel"; cmakeFlags = gglUtil.fetchContentFlags ++ [ "-DENABLE_WERROR=1" ]; From 0b0e07383c11406afda992707254588f17ffcdf0 Mon Sep 17 00:00:00 2001 From: Felicity Date: Mon, 7 Oct 2024 18:00:25 +0000 Subject: [PATCH 02/13] Feature: Unarchive the zip file --- ggdeploymentd/src/deployment_handler.c | 125 ++++++++++++++++++++++--- ggl-file/CMakeLists.txt | 1 - ggl-file/include/ggl/file.h | 5 + ggl-file/src/file.c | 108 +++++++++++++++++++++ 4 files changed, 226 insertions(+), 13 deletions(-) diff --git a/ggdeploymentd/src/deployment_handler.c b/ggdeploymentd/src/deployment_handler.c index d834e8d23..aa3e79e38 100644 --- a/ggdeploymentd/src/deployment_handler.c +++ b/ggdeploymentd/src/deployment_handler.c @@ -37,6 +37,8 @@ #include #define MAX_RECIPE_BUF_SIZE 256000 +#define MAX_DECODE_BUF_LEN 4096 +#define MAX_PATH_LEN 512 static struct DeploymentConfiguration { char data_endpoint[128]; @@ -553,12 +555,62 @@ static GglError find_artifacts_list( return GGL_ERR_OK; } +// Get the unarchive type: NONE or ZIP +static GglError get_artifact_unarchive_type( + GglBuffer unarchive_buf, bool *needs_unarchive +) { + if (ggl_buffer_eq(unarchive_buf, GGL_STR("NONE"))) { + *needs_unarchive = false; + } else if (ggl_buffer_eq(unarchive_buf, GGL_STR("ZIP"))) { + *needs_unarchive = true; + } else { + GGL_LOGE("ggdeploymentd", "Unknown archive type"); + return GGL_ERR_UNSUPPORTED; + } + return GGL_ERR_OK; +} + +static GglError unarchive_artifact( + int component_store_fd, + GglBuffer zip_file, + mode_t mode, + int component_archive_store_fd +) { + GglBuffer destination_dir = zip_file; + if (ggl_buffer_has_suffix(zip_file, GGL_STR(".zip"))) { + destination_dir = ggl_buffer_substr( + zip_file, 0, zip_file.len - (sizeof(".zip") - 1U) + ); + } + + GGL_LOGD( + "ggdeploymentd", "Unarchive %.*s", (int) zip_file.len, zip_file.data + ); + + int output_dir_fd; + GglError err = ggl_dir_openat( + component_archive_store_fd, + destination_dir, + O_PATH | O_RDONLY, + true, + &output_dir_fd + ); + if (err != GGL_ERR_OK) { + return err; + } + + // Unarchive the zip + return ggl_unarchive_zip(component_store_fd, zip_file, output_dir_fd, mode); +} + +// NOLINTNEXTLINE(readability-function-cognitive-complexity) static GglError get_recipe_artifacts( GglBuffer component_arn, TesCredentials tes_creds, CertificateDetails iot_creds, GglMap recipe, - int component_store_fd + int component_store_fd, + int component_archive_store_fd ) { GglList artifacts = { 0 }; GglError error = find_artifacts_list(recipe, &artifacts); @@ -567,36 +619,56 @@ static GglError get_recipe_artifacts( } for (size_t i = 0; i < artifacts.len; ++i) { - static uint8_t decode_buffer[1024]; + uint8_t decode_buffer[MAX_DECODE_BUF_LEN]; if (artifacts.items[i].type != GGL_TYPE_MAP) { return GGL_ERR_PARSE; } GglObject *uri_obj = NULL; + GglObject *unarchive_obj = NULL; GglError err = ggl_map_validate( artifacts.items[i].map, - GGL_MAP_SCHEMA({ GGL_STR("Uri"), true, GGL_TYPE_BUF, &uri_obj }) + GGL_MAP_SCHEMA( + { GGL_STR("Uri"), true, GGL_TYPE_BUF, &uri_obj }, + { GGL_STR("Unarchive"), false, GGL_TYPE_BUF, &unarchive_obj } + ) ); if (err != GGL_ERR_OK) { return GGL_ERR_PARSE; } + GglUriInfo info = { 0 }; { GglBumpAlloc alloc = ggl_bump_alloc_init(GGL_BUF(decode_buffer)); err = gg_uri_parse(&alloc.alloc, uri_obj->buf, &info); + + if (err != GGL_ERR_OK) { + return err; + } + } + + bool needs_unarchive = false; + if (unarchive_obj != NULL) { + err = get_artifact_unarchive_type( + unarchive_obj->buf, &needs_unarchive + ); if (err != GGL_ERR_OK) { return err; } } + // TODO: set permissions from recipe + mode_t mode = 0777; int artifact_fd = -1; err = ggl_file_openat( component_store_fd, info.file, - O_CREAT | O_WRONLY, - 0644, + O_CREAT | O_WRONLY | O_TRUNC, + needs_unarchive ? 0644 : mode, &artifact_fd ); + GGL_DEFER(ggl_close, artifact_fd); + if (err != GGL_ERR_OK) { GGL_LOGE( "ggdeployment", "Failed to create artifact file for write." @@ -618,19 +690,27 @@ static GglError get_recipe_artifacts( ); } else { GGL_LOGE("ggdeploymentd", "Unknown artifact URI scheme"); - err = GGL_ERR_PARSE; + return GGL_ERR_PARSE; + } + if (err != GGL_ERR_OK) { + return err; } - GglError close_error = ggl_close(artifact_fd); + // Unarchive the ZIP file if needed + if (needs_unarchive) { + err = unarchive_artifact( + component_store_fd, info.file, mode, component_archive_store_fd + ); + if (err != GGL_ERR_OK) { + return err; + } + } + err = ggl_fsync(artifact_fd); if (err != GGL_ERR_OK) { return err; } - if (close_error != GGL_ERR_OK) { - return close_error; - } } - return GGL_ERR_OK; } @@ -1434,6 +1514,19 @@ static void handle_deployment( return; } + int artifact_archive_fd = -1; + ret = ggl_dir_openat( + root_path_fd, + GGL_STR("packages/artifacts-unarchived"), + O_PATH, + true, + &artifact_archive_fd + ); + if (ret != GGL_ERR_OK) { + GGL_LOGE("ggdeploymentd", "Failed to open archive store."); + return; + } + GGL_MAP_FOREACH(pair, resolved_components_kv_vec.map) { int component_artifacts_fd = -1; open_component_artifacts_dir( @@ -1442,6 +1535,13 @@ static void handle_deployment( pair->val.buf, &component_artifacts_fd ); + int component_archive_dir_fd = -1; + open_component_artifacts_dir( + artifact_archive_fd, + pair->key, + pair->val.buf, + &component_archive_dir_fd + ); GglObject recipe_obj; static uint8_t recipe_mem[8192] = { 0 }; static uint8_t component_arn_buffer[256]; @@ -1480,7 +1580,8 @@ static void handle_deployment( tes_credentials, iot_credentials, recipe_obj.map, - component_artifacts_fd + component_artifacts_fd, + component_archive_dir_fd ); if (ret != GGL_ERR_OK) { diff --git a/ggl-file/CMakeLists.txt b/ggl-file/CMakeLists.txt index 825fe29f8..552a071e5 100644 --- a/ggl-file/CMakeLists.txt +++ b/ggl-file/CMakeLists.txt @@ -2,5 +2,4 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 - ggl_init_module(ggl-file LIBS ggl-lib ggl-socket PkgConfig::libzip) diff --git a/ggl-file/include/ggl/file.h b/ggl-file/include/ggl/file.h index 79bd5a03a..318bd8096 100644 --- a/ggl-file/include/ggl/file.h +++ b/ggl-file/include/ggl/file.h @@ -53,4 +53,9 @@ GglError ggl_file_read_path_at(int dirfd, GglBuffer path, GglBuffer *content); /// Copy directory contents recursively GglError ggl_copy_dir(int source_fd, int dest_fd); +/// Unarchive the zip file from the source path to the destination path +GglError ggl_unarchive_zip( + int source_dest_dir_fd, GglBuffer zip_path, int dest_dir_fd, mode_t mode +); + #endif diff --git a/ggl-file/src/file.c b/ggl-file/src/file.c index 64bca5a14..e74d364c4 100644 --- a/ggl-file/src/file.c +++ b/ggl-file/src/file.c @@ -13,21 +13,40 @@ #include #include #include +#include #include #include #include #include #include #include +#include +#include #include #include #include +#define MAX_BUF_LEN 1024 + static char path_comp_buf[NAME_MAX + 1]; static pthread_mutex_t path_comp_buf_mtx = PTHREAD_MUTEX_INITIALIZER; GGL_DEFINE_DEFER(closedir, DIR *, dirp, if (*dirp != NULL) closedir(*dirp)) +GGL_DEFINE_DEFER( + zip_fclose, + zip_file_t *, + zip_entry, + if (*zip_entry != NULL) zip_fclose(*zip_entry) +) + +GGL_DEFINE_DEFER( + zip_close, + zip_t *, + zip_archive, + if (*zip_archive != NULL) zip_close(*zip_archive) +) + GglError ggl_close(int fd) { // Do not loop on EINTR // Posix states that after an interrupted close, the state of the file @@ -655,3 +674,92 @@ GglError ggl_copy_dir(int source_fd, int dest_fd) { return GGL_ERR_OK; } + +GglError ggl_unarchive_zip( + int source_dest_dir_fd, GglBuffer zip_path, int dest_dir_fd, mode_t mode +) { + zip_t *zip; + { + int zip_fd; + GglError ret = ggl_file_openat( + source_dest_dir_fd, zip_path, O_RDONLY, 0, &zip_fd + ); + if (ret != GGL_ERR_OK) { + return ret; + } + int err; + zip = zip_fdopen(zip_fd, ZIP_RDONLY, &err); + if (zip == NULL) { + GGL_LOGE("file", "Failed to open zip file with error %d.", err); + return GGL_ERR_FAILURE; + } + } + GGL_DEFER(zip_close, zip); + + zip_uint64_t num_entries = (zip_uint64_t) zip_get_num_entries(zip, 0); + for (zip_uint64_t i = 0; i < num_entries; i++) { + const char *name = zip_get_name(zip, i, 0); + if (name == NULL) { + int err = zip_error_code_zip(zip_get_error(zip)); + GGL_LOGE( + "file", + "Failed to get the name of entry %" PRIu64 " with error %d.", + (uint64_t) i, + err + ); + return GGL_ERR_FAILURE; + } + + zip_file_t *entry = zip_fopen_index(zip, i, 0); + if (entry == NULL) { + int err = zip_error_code_zip(zip_get_error(zip)); + GGL_LOGE( + "file", + "Failed to open file \"%s\" (index %" PRIu64 + ") from zip with error %d.", + name, + i, + err + ); + return GGL_ERR_FAILURE; + } + GGL_DEFER(zip_fclose, entry); + + int dest_file_fd; + GglError ret = ggl_file_openat( + dest_dir_fd, + // const cast: name will not be modified + ggl_buffer_from_null_term((char *) name), + O_WRONLY | O_CREAT | O_TRUNC, + mode, + &dest_file_fd + ); + if (ret != GGL_ERR_OK) { + return ret; + } + GGL_DEFER(ggl_close, dest_file_fd); + + GGL_LOGD("file", "Inflating %s.", name); + uint8_t read_buffer[32]; + for (;;) { + zip_int64_t bytes_read + = zip_fread(entry, read_buffer, sizeof(read_buffer)); + // end of file + if (bytes_read == 0) { + break; + } + if (bytes_read < 0) { + GGL_LOGE("file", "Failed to read from zip file."); + return GGL_ERR_FAILURE; + } + GglBuffer bytes = (GglBuffer) { .data = read_buffer, + .len = (size_t) bytes_read }; + ret = ggl_write_exact(dest_file_fd, bytes); + if (ret != GGL_ERR_OK) { + return GGL_ERR_FAILURE; + } + } + } + + return GGL_ERR_OK; +} From 6eebe7f577ead2468f092fb568ec51c12a327915 Mon Sep 17 00:00:00 2001 From: Patrick Cook Date: Wed, 9 Oct 2024 13:08:51 -0700 Subject: [PATCH 03/13] Add new library ggl-zip. Moved from ggl-file. --- CMakeLists.txt | 1 + ggdeploymentd/CMakeLists.txt | 1 + ggdeploymentd/src/deployment_handler.c | 8 +- ggl-file/include/ggl/file.h | 5 - ggl-file/src/file.c | 108 --------------------- ggl-zip/CMakeLists.txt | 5 + ggl-zip/include/ggl/zip.h | 20 ++++ ggl-zip/src/zip.c | 127 +++++++++++++++++++++++++ 8 files changed, 158 insertions(+), 117 deletions(-) create mode 100644 ggl-zip/CMakeLists.txt create mode 100644 ggl-zip/include/ggl/zip.h create mode 100644 ggl-zip/src/zip.c diff --git a/CMakeLists.txt b/CMakeLists.txt index ab751a442..68ce586a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -302,6 +302,7 @@ add_subdirectory(ggl-json) add_subdirectory(ggl-yaml) add_subdirectory(ggl-recipe) add_subdirectory(ggl-cli) +add_subdirectory(ggl-zip) add_subdirectory(core-bus) add_subdirectory(core-bus-gg-config) add_subdirectory(core-bus-aws-iot-mqtt) diff --git a/ggdeploymentd/CMakeLists.txt b/ggdeploymentd/CMakeLists.txt index 955631ab0..f564c3940 100644 --- a/ggdeploymentd/CMakeLists.txt +++ b/ggdeploymentd/CMakeLists.txt @@ -13,6 +13,7 @@ ggl_init_module( ggl-semver ggl-socket ggl-yaml + ggl-zip core-bus-gg-config core-bus-aws-iot-mqtt recipe2unit diff --git a/ggdeploymentd/src/deployment_handler.c b/ggdeploymentd/src/deployment_handler.c index aa3e79e38..6616258a7 100644 --- a/ggdeploymentd/src/deployment_handler.c +++ b/ggdeploymentd/src/deployment_handler.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,6 @@ #define MAX_RECIPE_BUF_SIZE 256000 #define MAX_DECODE_BUF_LEN 4096 -#define MAX_PATH_LEN 512 static struct DeploymentConfiguration { char data_endpoint[128]; @@ -591,7 +591,7 @@ static GglError unarchive_artifact( GglError err = ggl_dir_openat( component_archive_store_fd, destination_dir, - O_PATH | O_RDONLY, + O_PATH, true, &output_dir_fd ); @@ -600,7 +600,7 @@ static GglError unarchive_artifact( } // Unarchive the zip - return ggl_unarchive_zip(component_store_fd, zip_file, output_dir_fd, mode); + return ggl_zip_unarchive(component_store_fd, zip_file, output_dir_fd, mode); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) @@ -658,7 +658,7 @@ static GglError get_recipe_artifacts( } // TODO: set permissions from recipe - mode_t mode = 0777; + mode_t mode = 0755; int artifact_fd = -1; err = ggl_file_openat( component_store_fd, diff --git a/ggl-file/include/ggl/file.h b/ggl-file/include/ggl/file.h index 318bd8096..79bd5a03a 100644 --- a/ggl-file/include/ggl/file.h +++ b/ggl-file/include/ggl/file.h @@ -53,9 +53,4 @@ GglError ggl_file_read_path_at(int dirfd, GglBuffer path, GglBuffer *content); /// Copy directory contents recursively GglError ggl_copy_dir(int source_fd, int dest_fd); -/// Unarchive the zip file from the source path to the destination path -GglError ggl_unarchive_zip( - int source_dest_dir_fd, GglBuffer zip_path, int dest_dir_fd, mode_t mode -); - #endif diff --git a/ggl-file/src/file.c b/ggl-file/src/file.c index e74d364c4..64bca5a14 100644 --- a/ggl-file/src/file.c +++ b/ggl-file/src/file.c @@ -13,40 +13,21 @@ #include #include #include -#include #include #include #include #include #include #include -#include -#include #include #include #include -#define MAX_BUF_LEN 1024 - static char path_comp_buf[NAME_MAX + 1]; static pthread_mutex_t path_comp_buf_mtx = PTHREAD_MUTEX_INITIALIZER; GGL_DEFINE_DEFER(closedir, DIR *, dirp, if (*dirp != NULL) closedir(*dirp)) -GGL_DEFINE_DEFER( - zip_fclose, - zip_file_t *, - zip_entry, - if (*zip_entry != NULL) zip_fclose(*zip_entry) -) - -GGL_DEFINE_DEFER( - zip_close, - zip_t *, - zip_archive, - if (*zip_archive != NULL) zip_close(*zip_archive) -) - GglError ggl_close(int fd) { // Do not loop on EINTR // Posix states that after an interrupted close, the state of the file @@ -674,92 +655,3 @@ GglError ggl_copy_dir(int source_fd, int dest_fd) { return GGL_ERR_OK; } - -GglError ggl_unarchive_zip( - int source_dest_dir_fd, GglBuffer zip_path, int dest_dir_fd, mode_t mode -) { - zip_t *zip; - { - int zip_fd; - GglError ret = ggl_file_openat( - source_dest_dir_fd, zip_path, O_RDONLY, 0, &zip_fd - ); - if (ret != GGL_ERR_OK) { - return ret; - } - int err; - zip = zip_fdopen(zip_fd, ZIP_RDONLY, &err); - if (zip == NULL) { - GGL_LOGE("file", "Failed to open zip file with error %d.", err); - return GGL_ERR_FAILURE; - } - } - GGL_DEFER(zip_close, zip); - - zip_uint64_t num_entries = (zip_uint64_t) zip_get_num_entries(zip, 0); - for (zip_uint64_t i = 0; i < num_entries; i++) { - const char *name = zip_get_name(zip, i, 0); - if (name == NULL) { - int err = zip_error_code_zip(zip_get_error(zip)); - GGL_LOGE( - "file", - "Failed to get the name of entry %" PRIu64 " with error %d.", - (uint64_t) i, - err - ); - return GGL_ERR_FAILURE; - } - - zip_file_t *entry = zip_fopen_index(zip, i, 0); - if (entry == NULL) { - int err = zip_error_code_zip(zip_get_error(zip)); - GGL_LOGE( - "file", - "Failed to open file \"%s\" (index %" PRIu64 - ") from zip with error %d.", - name, - i, - err - ); - return GGL_ERR_FAILURE; - } - GGL_DEFER(zip_fclose, entry); - - int dest_file_fd; - GglError ret = ggl_file_openat( - dest_dir_fd, - // const cast: name will not be modified - ggl_buffer_from_null_term((char *) name), - O_WRONLY | O_CREAT | O_TRUNC, - mode, - &dest_file_fd - ); - if (ret != GGL_ERR_OK) { - return ret; - } - GGL_DEFER(ggl_close, dest_file_fd); - - GGL_LOGD("file", "Inflating %s.", name); - uint8_t read_buffer[32]; - for (;;) { - zip_int64_t bytes_read - = zip_fread(entry, read_buffer, sizeof(read_buffer)); - // end of file - if (bytes_read == 0) { - break; - } - if (bytes_read < 0) { - GGL_LOGE("file", "Failed to read from zip file."); - return GGL_ERR_FAILURE; - } - GglBuffer bytes = (GglBuffer) { .data = read_buffer, - .len = (size_t) bytes_read }; - ret = ggl_write_exact(dest_file_fd, bytes); - if (ret != GGL_ERR_OK) { - return GGL_ERR_FAILURE; - } - } - } - - return GGL_ERR_OK; -} diff --git a/ggl-zip/CMakeLists.txt b/ggl-zip/CMakeLists.txt new file mode 100644 index 000000000..2127e37f6 --- /dev/null +++ b/ggl-zip/CMakeLists.txt @@ -0,0 +1,5 @@ +# aws-greengrass-lite - AWS IoT Greengrass runtime for constrained devices +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +ggl_init_module(ggl-zip LIBS ggl-lib ggl-socket ggl-file PkgConfig::libzip) diff --git a/ggl-zip/include/ggl/zip.h b/ggl-zip/include/ggl/zip.h new file mode 100644 index 000000000..85f5278d9 --- /dev/null +++ b/ggl-zip/include/ggl/zip.h @@ -0,0 +1,20 @@ +// aws-greengrass-lite - AWS IoT Greengrass runtime for constrained devices +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef GGL_ZIP_H +#define GGL_ZIP_H + +//! Zip file functionality + +#include +#include +#include + +/// Unarchive all entries from the zip file in a directory to the destination +/// directory. All created, uncompressed files use the given mode. +GglError ggl_zip_unarchive( + int source_dest_dir_fd, GglBuffer zip_path, int dest_dir_fd, mode_t mode +); + +#endif diff --git a/ggl-zip/src/zip.c b/ggl-zip/src/zip.c new file mode 100644 index 000000000..faea618ba --- /dev/null +++ b/ggl-zip/src/zip.c @@ -0,0 +1,127 @@ +// aws-greengrass-lite - AWS IoT Greengrass runtime for constrained devices +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#include "ggl/zip.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GGL_DEFINE_DEFER( + zip_fclose, + zip_file_t *, + zip_entry, + if (*zip_entry != NULL) zip_fclose(*zip_entry) +) + +GGL_DEFINE_DEFER( + zip_close, + zip_t *, + zip_archive, + if (*zip_archive != NULL) zip_close(*zip_archive) +) + +static GglError write_entry_to_fd(zip_file_t *entry, int fd) { + uint8_t read_buffer[32]; + for (;;) { + zip_int64_t bytes_read + = zip_fread(entry, read_buffer, sizeof(read_buffer)); + // end of file + if (bytes_read == 0) { + return GGL_ERR_OK; + } + if (bytes_read < 0) { + int err = zip_error_code_zip(zip_file_get_error(entry)); + GGL_LOGE("zip", "Failed to read from zip file with error %d.", err); + return GGL_ERR_FAILURE; + } + GglBuffer bytes + = (GglBuffer) { .data = read_buffer, .len = (size_t) bytes_read }; + GglError ret = ggl_write_exact(fd, bytes); + if (ret != GGL_ERR_OK) { + return GGL_ERR_FAILURE; + } + } +} + +GglError ggl_zip_unarchive( + int source_dest_dir_fd, GglBuffer zip_path, int dest_dir_fd, mode_t mode +) { + zip_t *zip; + { + int zip_fd; + GglError ret = ggl_file_openat( + source_dest_dir_fd, zip_path, O_RDONLY, 0, &zip_fd + ); + if (ret != GGL_ERR_OK) { + return ret; + } + int err; + zip = zip_fdopen(zip_fd, ZIP_RDONLY, &err); + if (zip == NULL) { + GGL_LOGE("zip", "Failed to open zip file with error %d.", err); + return GGL_ERR_FAILURE; + } + } + GGL_DEFER(zip_close, zip); + + zip_uint64_t num_entries = (zip_uint64_t) zip_get_num_entries(zip, 0); + for (zip_uint64_t i = 0; i < num_entries; i++) { + const char *name = zip_get_name(zip, i, 0); + if (name == NULL) { + int err = zip_error_code_zip(zip_get_error(zip)); + GGL_LOGE( + "zip", + "Failed to get the name of entry %" PRIu64 " with error %d.", + (uint64_t) i, + err + ); + return GGL_ERR_FAILURE; + } + + zip_file_t *entry = zip_fopen_index(zip, i, 0); + if (entry == NULL) { + int err = zip_error_code_zip(zip_get_error(zip)); + GGL_LOGE( + "zip", + "Failed to open file \"%s\" (index %" PRIu64 + ") from zip with error %d.", + name, + i, + err + ); + return GGL_ERR_FAILURE; + } + GGL_DEFER(zip_fclose, entry); + + int dest_file_fd; + GglError ret = ggl_file_openat( + dest_dir_fd, + // const cast: name will not be modified + ggl_buffer_from_null_term((char *) name), + O_WRONLY | O_CREAT | O_TRUNC, + mode, + &dest_file_fd + ); + if (ret != GGL_ERR_OK) { + return ret; + } + GGL_DEFER(ggl_close, dest_file_fd); + + GGL_LOGD("zip", "Inflating %s.", name); + ret = write_entry_to_fd(entry, dest_file_fd); + if (ret != GGL_ERR_OK) { + return ret; + } + } + + return GGL_ERR_OK; +} From 9a271021fce13b9a15fd72a8c4bf55b5c56a86cb Mon Sep 17 00:00:00 2001 From: Patrick Cook Date: Wed, 9 Oct 2024 13:10:57 -0700 Subject: [PATCH 04/13] Add libzip to Containerfile --- misc/container/Containerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/container/Containerfile b/misc/container/Containerfile index afe21a95e..512df2201 100644 --- a/misc/container/Containerfile +++ b/misc/container/Containerfile @@ -8,7 +8,7 @@ RUN apt-get -y install --no-install-recommends \ && apt-get clean RUN apt-get -y install --no-install-recommends \ libssl-dev libcurl4-openssl-dev libsqlite3-dev libyaml-dev \ - libsystemd-dev liburiparser-dev uuid-dev libevent-dev \ + libsystemd-dev liburiparser-dev uuid-dev libevent-dev libzip-dev \ && apt-get clean COPY ./getty-override.conf \ From 1ba282f2b9b19d1fd78ede16569831ac33305c78 Mon Sep 17 00:00:00 2001 From: Felicity Date: Thu, 10 Oct 2024 16:56:41 +0000 Subject: [PATCH 05/13] Bug fix: avoid creating dup zip file name --- ggl-zip/src/zip.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/ggl-zip/src/zip.c b/ggl-zip/src/zip.c index faea618ba..d251125a8 100644 --- a/ggl-zip/src/zip.c +++ b/ggl-zip/src/zip.c @@ -73,6 +73,7 @@ GglError ggl_zip_unarchive( } GGL_DEFER(zip_close, zip); + GglBuffer init_name; zip_uint64_t num_entries = (zip_uint64_t) zip_get_num_entries(zip, 0); for (zip_uint64_t i = 0; i < num_entries; i++) { const char *name = zip_get_name(zip, i, 0); @@ -87,6 +88,20 @@ GglError ggl_zip_unarchive( return GGL_ERR_FAILURE; } + // Avoid creating duplicate zip file name + if (i == 0) { + init_name = ggl_buffer_from_null_term((char *) name); + continue; + } + + // Remove the first segment from the path + GglBuffer name_buf = ggl_buffer_from_null_term((char *) name); + GglBuffer trunc_name = name_buf; + if (ggl_buffer_has_prefix(name_buf, init_name)) { + trunc_name + = ggl_buffer_substr(name_buf, init_name.len, name_buf.len); + }; + zip_file_t *entry = zip_fopen_index(zip, i, 0); if (entry == NULL) { int err = zip_error_code_zip(zip_get_error(zip)); @@ -94,7 +109,7 @@ GglError ggl_zip_unarchive( "zip", "Failed to open file \"%s\" (index %" PRIu64 ") from zip with error %d.", - name, + trunc_name.data, i, err ); @@ -102,21 +117,26 @@ GglError ggl_zip_unarchive( } GGL_DEFER(zip_fclose, entry); + GglError ret; int dest_file_fd; - GglError ret = ggl_file_openat( - dest_dir_fd, - // const cast: name will not be modified - ggl_buffer_from_null_term((char *) name), - O_WRONLY | O_CREAT | O_TRUNC, - mode, - &dest_file_fd - ); + if (ggl_buffer_has_suffix(trunc_name, GGL_STR("/"))) { + ret = ggl_dir_openat( + dest_dir_fd, trunc_name, O_PATH, mode, &dest_file_fd + ); + } else { + ret = ggl_file_openat( + dest_dir_fd, + trunc_name, + O_WRONLY | O_CREAT | O_TRUNC, + mode, + &dest_file_fd + ); + } if (ret != GGL_ERR_OK) { return ret; } GGL_DEFER(ggl_close, dest_file_fd); - GGL_LOGD("zip", "Inflating %s.", name); ret = write_entry_to_fd(entry, dest_file_fd); if (ret != GGL_ERR_OK) { return ret; From 350ef88d34f12e31ed1649d57d35e202ec07ae72 Mon Sep 17 00:00:00 2001 From: Felicity Date: Thu, 10 Oct 2024 17:41:40 +0000 Subject: [PATCH 06/13] Fix CI: too many args for format --- ggdeploymentd/src/deployment_handler.c | 17 ++++++++++++----- ggl-zip/src/zip.c | 6 ++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/ggdeploymentd/src/deployment_handler.c b/ggdeploymentd/src/deployment_handler.c index ab41b2186..ad9c506e7 100644 --- a/ggdeploymentd/src/deployment_handler.c +++ b/ggdeploymentd/src/deployment_handler.c @@ -549,7 +549,7 @@ static GglError get_artifact_unarchive_type( } else if (ggl_buffer_eq(unarchive_buf, GGL_STR("ZIP"))) { *needs_unarchive = true; } else { - GGL_LOGE("ggdeploymentd", "Unknown archive type"); + GGL_LOGE("Unknown archive type"); return GGL_ERR_UNSUPPORTED; } return GGL_ERR_OK; @@ -568,9 +568,7 @@ static GglError unarchive_artifact( ); } - GGL_LOGD( - "ggdeploymentd", "Unarchive %.*s", (int) zip_file.len, zip_file.data - ); + GGL_LOGD("Unarchive %.*s", (int) zip_file.len, zip_file.data); int output_dir_fd; GglError err = ggl_dir_openat( @@ -676,6 +674,10 @@ static GglError get_recipe_artifacts( err = GGL_ERR_PARSE; } + if (err != GGL_ERR_OK) { + return err; + } + // Unarchive the ZIP file if needed if (needs_unarchive) { err = unarchive_artifact( @@ -690,6 +692,11 @@ static GglError get_recipe_artifacts( if (err != GGL_ERR_OK) { return err; } + + GglError close_error = ggl_close(artifact_fd); + if (close_error != GGL_ERR_OK) { + return close_error; + } } return GGL_ERR_OK; } @@ -1481,7 +1488,7 @@ static void handle_deployment( &artifact_archive_fd ); if (ret != GGL_ERR_OK) { - GGL_LOGE("ggdeploymentd", "Failed to open archive store."); + GGL_LOGE("Failed to open archive store."); return; } diff --git a/ggl-zip/src/zip.c b/ggl-zip/src/zip.c index d251125a8..f490c0c53 100644 --- a/ggl-zip/src/zip.c +++ b/ggl-zip/src/zip.c @@ -40,7 +40,7 @@ static GglError write_entry_to_fd(zip_file_t *entry, int fd) { } if (bytes_read < 0) { int err = zip_error_code_zip(zip_file_get_error(entry)); - GGL_LOGE("zip", "Failed to read from zip file with error %d.", err); + GGL_LOGE("Failed to read from zip file with error %d.", err); return GGL_ERR_FAILURE; } GglBuffer bytes @@ -67,7 +67,7 @@ GglError ggl_zip_unarchive( int err; zip = zip_fdopen(zip_fd, ZIP_RDONLY, &err); if (zip == NULL) { - GGL_LOGE("zip", "Failed to open zip file with error %d.", err); + GGL_LOGE("Failed to open zip file with error %d.", err); return GGL_ERR_FAILURE; } } @@ -80,7 +80,6 @@ GglError ggl_zip_unarchive( if (name == NULL) { int err = zip_error_code_zip(zip_get_error(zip)); GGL_LOGE( - "zip", "Failed to get the name of entry %" PRIu64 " with error %d.", (uint64_t) i, err @@ -106,7 +105,6 @@ GglError ggl_zip_unarchive( if (entry == NULL) { int err = zip_error_code_zip(zip_get_error(zip)); GGL_LOGE( - "zip", "Failed to open file \"%s\" (index %" PRIu64 ") from zip with error %d.", trunc_name.data, From 4c38b8e50de769953201522884dbf18073310598 Mon Sep 17 00:00:00 2001 From: Felicity Date: Wed, 30 Oct 2024 16:32:55 +0000 Subject: [PATCH 07/13] Add fd to recipe2unit testing --- recipe2unit-test/CMakeLists.txt | 2 +- recipe2unit-test/src/entry.c | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/recipe2unit-test/CMakeLists.txt b/recipe2unit-test/CMakeLists.txt index b1a297f17..5172e06f0 100644 --- a/recipe2unit-test/CMakeLists.txt +++ b/recipe2unit-test/CMakeLists.txt @@ -2,4 +2,4 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -ggl_init_module(recipe2unit-test LIBS ggl-lib recipe2unit) +ggl_init_module(recipe2unit-test LIBS ggl-file ggl-lib recipe2unit) diff --git a/recipe2unit-test/src/entry.c b/recipe2unit-test/src/entry.c index 7245dfa14..b75546e7e 100644 --- a/recipe2unit-test/src/entry.c +++ b/recipe2unit-test/src/entry.c @@ -4,20 +4,34 @@ #include "ggl/recipe2unit.h" #include "recipe2unit-test.h" -#include +#include #include #include +#include +#include #include #include #include +// For the testing purpose, move the sample recipe.yml to /run/packages/recipes +// and rename it to recipe-1.0.0.yml + GglError run_recipe2unit_test(void) { static Recipe2UnitArgs args = { 0 }; - char component_name[] = "recipe.yml"; + char component_name[] = "recipe"; char version[] = "1.0.0"; char root_dir[] = "."; char recipe_runner_path[] = "/home/reciperunner"; + int root_path_fd; + GglError ret + = ggl_dir_open(GGL_STR(root_dir), O_PATH, false, &root_path_fd); + if (ret != GGL_ERR_OK) { + GGL_LOGE("Failed to open root dir."); + return ret; + } + args.root_path_fd = root_path_fd; + GglBuffer component_name_buff = (GglBuffer) { (uint8_t *) component_name, strlen(component_name) }; GglBuffer version_buff From f6b2acfbcf887d705127d6cf4cda49dbe5338a63 Mon Sep 17 00:00:00 2001 From: Felicity Date: Wed, 30 Oct 2024 18:28:36 +0000 Subject: [PATCH 08/13] create unit files for install and run_startup --- recipe2unit/src/parser.c | 106 ++++++++++++++++++++++++++++----------- 1 file changed, 77 insertions(+), 29 deletions(-) diff --git a/recipe2unit/src/parser.c b/recipe2unit/src/parser.c index 08401558c..a2cbe0169 100644 --- a/recipe2unit/src/parser.c +++ b/recipe2unit/src/parser.c @@ -19,6 +19,41 @@ #define MAX_UNIT_FILE_BUF_SIZE 2048 #define MAX_COMPONENT_FILE_NAME 1024 +static GglError create_unit_file( + Recipe2UnitArgs *args, + GglObject **component_name, + GglBuffer *response_buffer, + bool is_install +) { + static uint8_t file_name_array[MAX_COMPONENT_FILE_NAME]; + GglBuffer file_name_buffer = (GglBuffer + ) { .data = (uint8_t *) file_name_array, .len = MAX_COMPONENT_FILE_NAME }; + + GglByteVec file_name_vector + = { .buf = { .data = file_name_buffer.data, .len = 0 }, + .capacity = file_name_buffer.len }; + + GglBuffer root_dir_buffer = (GglBuffer + ) { .data = (uint8_t *) args->root_dir, .len = strlen(args->root_dir) }; + + GglError ret = ggl_byte_vec_append(&file_name_vector, root_dir_buffer); + ggl_byte_vec_chain_append(&ret, &file_name_vector, GGL_STR("/")); + ggl_byte_vec_chain_append(&ret, &file_name_vector, GGL_STR("ggl.")); + ggl_byte_vec_chain_append(&ret, &file_name_vector, (*component_name)->buf); + if (is_install) { + ggl_byte_vec_chain_append(&ret, &file_name_vector, GGL_STR(".install")); + } + ggl_byte_vec_chain_append(&ret, &file_name_vector, GGL_STR(".service\0")); + if (ret != GGL_ERR_OK) { + return ret; + } + + FILE *f = fopen((const char *) file_name_vector.buf.data, "wb"); + fwrite(response_buffer->data, sizeof(char), response_buffer->len, f); + fclose(f); + return GGL_ERR_OK; +} + GglError convert_to_unit( Recipe2UnitArgs *args, GglAlloc *alloc, @@ -27,6 +62,7 @@ GglError convert_to_unit( ) { GglError ret; *component_name = NULL; + bool is_install = false; ret = validate_args(args); if (ret != GGL_ERR_OK) { @@ -41,48 +77,60 @@ GglError convert_to_unit( recipe_obj ); if (ret != GGL_ERR_OK) { + GGL_LOGI("No recipe found"); return ret; } - static uint8_t unit_file_buffer[MAX_UNIT_FILE_BUF_SIZE]; - GglBuffer response_buffer = (GglBuffer - ) { .data = (uint8_t *) unit_file_buffer, .len = MAX_UNIT_FILE_BUF_SIZE }; + // Note: currently, if we have both run and startup phases, + // we will only select startup for the script and service file + static uint8_t install_unit_file_buffer[MAX_UNIT_FILE_BUF_SIZE]; + static uint8_t run_startup_unit_file_buffer[MAX_UNIT_FILE_BUF_SIZE]; + GglBuffer install_response_buffer + = (GglBuffer) { .data = (uint8_t *) install_unit_file_buffer, + .len = MAX_UNIT_FILE_BUF_SIZE }; + GglBuffer run_startup_response_buffer + = (GglBuffer) { .data = (uint8_t *) run_startup_unit_file_buffer, + .len = MAX_UNIT_FILE_BUF_SIZE }; ret = generate_systemd_unit( - &recipe_obj->map, &response_buffer, args, component_name + &recipe_obj->map, + &install_response_buffer, + args, + component_name, + INSTALL ); - if (ret != GGL_ERR_OK) { - return ret; - } - if (*component_name == NULL) { GGL_LOGE("Component name was NULL"); return GGL_ERR_FAILURE; } - - static uint8_t file_name_array[MAX_COMPONENT_FILE_NAME]; - GglBuffer file_name_buffer = (GglBuffer - ) { .data = (uint8_t *) file_name_array, .len = MAX_COMPONENT_FILE_NAME }; - - GglByteVec file_name_vector - = { .buf = { .data = file_name_buffer.data, .len = 0 }, - .capacity = file_name_buffer.len }; - - GglBuffer root_dir_buffer = (GglBuffer - ) { .data = (uint8_t *) args->root_dir, .len = strlen(args->root_dir) }; - - ret = ggl_byte_vec_append(&file_name_vector, root_dir_buffer); - ggl_byte_vec_chain_append(&ret, &file_name_vector, GGL_STR("/")); - ggl_byte_vec_chain_append(&ret, &file_name_vector, GGL_STR("ggl.")); - ggl_byte_vec_chain_append(&ret, &file_name_vector, (*component_name)->buf); - ggl_byte_vec_chain_append(&ret, &file_name_vector, GGL_STR(".service\0")); - if (ret != GGL_ERR_OK) { + if (ret == GGL_ERR_NOENTRY) { + GGL_LOGW("No Install phase present"); + } else if (ret != GGL_ERR_OK) { return ret; + } else { + is_install = true; + ret = create_unit_file( + args, component_name, &install_response_buffer, is_install + ); } - FILE *f = fopen((const char *) file_name_vector.buf.data, "wb"); - fwrite(response_buffer.data, sizeof(char), response_buffer.len, f); - fclose(f); + ret = generate_systemd_unit( + &recipe_obj->map, + &run_startup_response_buffer, + args, + component_name, + RUN_STARTUP + ); + if (ret == GGL_ERR_NOENTRY) { + GGL_LOGW("No run or phase present"); + } else if (ret != GGL_ERR_OK) { + return ret; + } else { + is_install = false; + ret = create_unit_file( + args, component_name, &run_startup_response_buffer, is_install + ); + } return GGL_ERR_OK; } From a2d9cf8ba1c8919e6e4cf035bf8b081f5b52cb8b Mon Sep 17 00:00:00 2001 From: Felicity Date: Wed, 30 Oct 2024 23:55:17 +0000 Subject: [PATCH 09/13] Update handle_deployment for install and startup-run --- ggdeploymentd/src/component_manager.c | 3 +- ggdeploymentd/src/deployment_handler.c | 200 +++++++++++--- recipe2unit/src/unit_file_generator.c | 363 +++++++++++-------------- recipe2unit/src/unit_file_generator.h | 8 +- 4 files changed, 324 insertions(+), 250 deletions(-) diff --git a/ggdeploymentd/src/component_manager.c b/ggdeploymentd/src/component_manager.c index 54520a877..1b91e8e31 100644 --- a/ggdeploymentd/src/component_manager.c +++ b/ggdeploymentd/src/component_manager.c @@ -95,10 +95,11 @@ bool resolve_component_version( // TODO: also check that the component region matches the expected region // (component store functionality) GGL_LOGI( - "Found local candidate for %s that satisfies version requirements. " + "Found local candidate for %.*s that satisfies version requirements. " "Using " "the local candidate as the resolved version " "without negotiating with the cloud.", + (int) component_name.len, (char *) component_name.data ); diff --git a/ggdeploymentd/src/deployment_handler.c b/ggdeploymentd/src/deployment_handler.c index 37060c221..c47114785 100644 --- a/ggdeploymentd/src/deployment_handler.c +++ b/ggdeploymentd/src/deployment_handler.c @@ -46,6 +46,7 @@ #define MAX_RECIPE_BUF_SIZE 256000 #define MAX_DECODE_BUF_LEN 4096 +#define MAX_COMP_NAME_BUF_SIZE 10000 static struct DeploymentConfiguration { char data_endpoint[128]; @@ -1973,6 +1974,9 @@ static void handle_deployment( } GGL_CLEANUP(ggl_free_digest, digest_context); + static GglBuffer comp_name_buf[MAX_COMP_NAME_BUF_SIZE]; + GglBufVec comp_name_vec = GGL_BUF_VEC(comp_name_buf); + GGL_MAP_FOREACH(pair, resolved_components_kv_vec.map) { int component_artifacts_fd = -1; open_component_artifacts_dir( @@ -2234,32 +2238,147 @@ static void handle_deployment( // TODO: add install file processing logic here. if (component_updated) { - static uint8_t service_file_path_buf[PATH_MAX]; - GglByteVec service_file_path_vec - = GGL_BYTE_VEC(service_file_path_buf); - ret = ggl_byte_vec_append( - &service_file_path_vec, GGL_STR("ggl.") - ); - ggl_byte_vec_chain_append( - &ret, &service_file_path_vec, pair->key - ); - ggl_byte_vec_chain_append( - &ret, &service_file_path_vec, GGL_STR(".service") - ); + ret = ggl_buf_vec_push(&comp_name_vec, pair->key); if (ret != GGL_ERR_OK) { - GGL_LOGE("Failed to create service file path."); + GGL_LOGE("Failed to add the component name into vector"); return; } + } + } + if (comp_name_vec.buf_list.len == 0) { + GGL_LOGE("Failed to retrieve any component name"); + return; + } + + for (size_t i = 0; i < comp_name_vec.buf_list.len; i++) { + // install + static uint8_t install_service_file_path_buf[PATH_MAX]; + GglByteVec install_service_file_path_vec + = GGL_BYTE_VEC(install_service_file_path_buf); + ret = ggl_byte_vec_append( + &install_service_file_path_vec, args->root_path + ); + ggl_byte_vec_append(&install_service_file_path_vec, GGL_STR("/")); + ggl_byte_vec_append( + &install_service_file_path_vec, GGL_STR("ggl.") + ); + ggl_byte_vec_chain_append( + &ret, + &install_service_file_path_vec, + comp_name_vec.buf_list.bufs[i] + ); + ggl_byte_vec_chain_append( + &ret, + &install_service_file_path_vec, + GGL_STR(".install.service") + ); + if (ret == GGL_ERR_OK) { + // check if the current component name has relevant install + // service file created + int fd = -1; + ret = ggl_file_open( + install_service_file_path_vec.buf, O_RDONLY, 0, &fd + ); + if (ret != GGL_ERR_OK) { + GGL_LOGW( + "Component %.*s does not have the relevant install " + "service file", + (int) comp_name_vec.buf_list.bufs[i].len, + comp_name_vec.buf_list.bufs[i].data + ); + } else { // relevant install service file exists + + // run link command + static uint8_t link_command_buf[PATH_MAX]; + GglByteVec link_command_vec + = GGL_BYTE_VEC(link_command_buf); + ret = ggl_byte_vec_append( + &link_command_vec, GGL_STR("sudo systemctl link ") + ); + ggl_byte_vec_chain_append( + &ret, + &link_command_vec, + install_service_file_path_vec.buf + ); + ggl_byte_vec_chain_push(&ret, &link_command_vec, '\0'); + if (ret != GGL_ERR_OK) { + GGL_LOGE("Failed to create systemctl link command."); + return; + } + + // NOLINTNEXTLINE(concurrency-mt-unsafe) + int system_ret = system((char *) link_command_vec.buf.data); + if (WIFEXITED(system_ret)) { + if (WEXITSTATUS(system_ret) != 0) { + GGL_LOGE("systemctl link failed"); + return; + } + GGL_LOGI( + "systemctl link exited with child status %d\n", + WEXITSTATUS(system_ret) + ); + } else { + GGL_LOGE("systemctl link did not exit normally"); + return; + } + + // run start command + static uint8_t start_command_buf[PATH_MAX]; + GglByteVec start_command_vec + = GGL_BYTE_VEC(start_command_buf); + ret = ggl_byte_vec_append( + &start_command_vec, GGL_STR("sudo systemctl start ") + ); + ggl_byte_vec_chain_append( + &ret, + &start_command_vec, + install_service_file_path_vec.buf + ); + ggl_byte_vec_chain_push(&ret, &start_command_vec, '\0'); + if (ret != GGL_ERR_OK) { + GGL_LOGE("Failed to create systemctl start command."); + return; + } + + // NOLINTNEXTLINE(concurrency-mt-unsafe) + system_ret = system((char *) start_command_vec.buf.data); + if (WIFEXITED(system_ret)) { + if (WEXITSTATUS(system_ret) != 0) { + GGL_LOGE("systemctl start failed"); + return; + } + GGL_LOGI( + "systemctl start exited with child status %d\n", + WEXITSTATUS(system_ret) + ); + } else { + GGL_LOGE("systemctl start did not exit normally"); + return; + } + } + } + + // run or startup + static uint8_t service_file_path_buf[PATH_MAX]; + GglByteVec service_file_path_vec + = GGL_BYTE_VEC(service_file_path_buf); + ret = ggl_byte_vec_append(&service_file_path_vec, args->root_path); + ggl_byte_vec_append(&service_file_path_vec, GGL_STR("/")); + ggl_byte_vec_append(&service_file_path_vec, GGL_STR("ggl.")); + ggl_byte_vec_chain_append( + &ret, &service_file_path_vec, comp_name_vec.buf_list.bufs[i] + ); + ggl_byte_vec_chain_append( + &ret, &service_file_path_vec, GGL_STR(".service") + ); + if (ret == GGL_ERR_OK) { + // run link command static uint8_t link_command_buf[PATH_MAX]; GglByteVec link_command_vec = GGL_BYTE_VEC(link_command_buf); ret = ggl_byte_vec_append( &link_command_vec, GGL_STR("sudo systemctl link ") ); - ggl_byte_vec_chain_append( - &ret, &link_command_vec, args->root_path - ); - ggl_byte_vec_chain_push(&ret, &link_command_vec, '/'); ggl_byte_vec_chain_append( &ret, &link_command_vec, service_file_path_vec.buf ); @@ -2285,64 +2404,65 @@ static void handle_deployment( return; } - static uint8_t start_command_buf[PATH_MAX]; - GglByteVec start_command_vec = GGL_BYTE_VEC(start_command_buf); + // run enable command + static uint8_t enable_command_buf[PATH_MAX]; + GglByteVec enable_command_vec + = GGL_BYTE_VEC(enable_command_buf); ret = ggl_byte_vec_append( - &start_command_vec, GGL_STR("sudo systemctl start ") + &enable_command_vec, GGL_STR("sudo systemctl enable ") ); ggl_byte_vec_chain_append( - &ret, &start_command_vec, service_file_path_vec.buf + &ret, &enable_command_vec, service_file_path_vec.buf ); - ggl_byte_vec_chain_push(&ret, &start_command_vec, '\0'); + ggl_byte_vec_chain_push(&ret, &enable_command_vec, '\0'); if (ret != GGL_ERR_OK) { - GGL_LOGE("Failed to create systemctl start command."); + GGL_LOGE("Failed to create systemctl enable command."); return; } // NOLINTNEXTLINE(concurrency-mt-unsafe) - system_ret = system((char *) start_command_vec.buf.data); + system_ret = system((char *) enable_command_vec.buf.data); if (WIFEXITED(system_ret)) { if (WEXITSTATUS(system_ret) != 0) { - GGL_LOGE("systemctl start failed"); + GGL_LOGE("systemctl enable failed"); return; } GGL_LOGI( - "systemctl start exited with child status %d\n", + "systemctl enable exited with child status %d\n", WEXITSTATUS(system_ret) ); } else { - GGL_LOGE("systemctl start did not exit normally"); + GGL_LOGE("systemctl enable did not exit normally"); return; } - static uint8_t enable_command_buf[PATH_MAX]; - GglByteVec enable_command_vec - = GGL_BYTE_VEC(enable_command_buf); + // run daemon-reload command + static uint8_t reload_command_buf[PATH_MAX]; + GglByteVec reload_command_vec + = GGL_BYTE_VEC(reload_command_buf); ret = ggl_byte_vec_append( - &enable_command_vec, GGL_STR("sudo systemctl enable ") + &reload_command_vec, + GGL_STR("sudo systemctl daemon-reload\0") ); - ggl_byte_vec_chain_append( - &ret, &enable_command_vec, service_file_path_vec.buf - ); - ggl_byte_vec_chain_push(&ret, &enable_command_vec, '\0'); if (ret != GGL_ERR_OK) { - GGL_LOGE("Failed to create systemctl enable command."); + GGL_LOGE("Failed to create systemctl daemon-reload command." + ); return; } // NOLINTNEXTLINE(concurrency-mt-unsafe) - system_ret = system((char *) enable_command_vec.buf.data); + system_ret = system((char *) reload_command_vec.buf.data); if (WIFEXITED(system_ret)) { if (WEXITSTATUS(system_ret) != 0) { - GGL_LOGE("systemctl enable failed"); + GGL_LOGE("systemctl daemon-reload failed"); return; } GGL_LOGI( - "systemctl enable exited with child status %d\n", + "systemctl daemon-reload exited with child status %d\n", WEXITSTATUS(system_ret) ); } else { - GGL_LOGE("systemctl enable did not exit normally"); + GGL_LOGE("systemctl daemon-reload did not exit normally"); return; } } diff --git a/recipe2unit/src/unit_file_generator.c b/recipe2unit/src/unit_file_generator.c index bd99b6f15..b4cae87ba 100644 --- a/recipe2unit/src/unit_file_generator.c +++ b/recipe2unit/src/unit_file_generator.c @@ -26,6 +26,7 @@ #define WORKING_DIR_LEN 4096 #define MAX_SCRIPT_SIZE 10000 +#define MAX_UNIT_SIZE 10000 #define MAX_RETRIES_BEFORE_BROKEN "3" #define MAX_RETRIES_INTERVAL_SECONDS "3600" @@ -101,7 +102,7 @@ static GglError dependency_parser(GglObject *dependency_obj, GglByteVec *out) { } static GglError fill_unit_section( - GglMap recipe_map, GglByteVec *concat_unit_vector + GglMap recipe_map, GglByteVec *concat_unit_vector, PhaseSelection phase ) { GglObject *val; @@ -143,9 +144,11 @@ static GglError fill_unit_section( } } - if (ggl_map_get(recipe_map, GGL_STR("ComponentDependencies"), &val)) { - if ((val->type == GGL_TYPE_MAP) || (val->type == GGL_TYPE_LIST)) { - return dependency_parser(val, concat_unit_vector); + if (phase == RUN_STARTUP) { + if (ggl_map_get(recipe_map, GGL_STR("ComponentDependencies"), &val)) { + if ((val->type == GGL_TYPE_MAP) || (val->type == GGL_TYPE_LIST)) { + return dependency_parser(val, concat_unit_vector); + } } } @@ -209,6 +212,9 @@ static GglError fetch_script_section( return GGL_ERR_INVALID; } *selected_script_as_buf = key_object->buf; + } else { + GGL_LOGW("Script is not in the map"); + return GGL_ERR_NOENTRY; } if (ggl_map_get(val->map, GGL_STR("Setenv"), &key_object)) { @@ -223,15 +229,69 @@ static GglError fetch_script_section( GGL_LOGE("Script section section is of invalid list type"); return GGL_ERR_INVALID; } + } else { + GGL_LOGE( + "%.*s section is not in the lifecycle", + (int) selected_phase.len, + selected_phase.data + ); + return GGL_ERR_NOENTRY; } return GGL_ERR_OK; }; -static GglError concat_initial_strings( +static GglError concat_script_name_prefix_vec( + const GglMap *recipe_map, GglByteVec *script_name_prefix_vec +) { + GglError ret; + GglObject *component_name; + if (!ggl_map_get(*recipe_map, GGL_STR("ComponentName"), &component_name)) { + return GGL_ERR_INVALID; + } + if (component_name->type != GGL_TYPE_BUF) { + return GGL_ERR_INVALID; + } + + // build the script name prefix string + ret = ggl_byte_vec_append(script_name_prefix_vec, component_name->buf); + ggl_byte_vec_chain_append( + &ret, script_name_prefix_vec, GGL_STR(".script.") + ); + if (ret != GGL_ERR_OK) { + return ret; + } + return GGL_ERR_OK; +} + +static GglError concat_working_dir_vec( + const GglMap *recipe_map, GglByteVec *working_dir_vec, Recipe2UnitArgs *args + +) { + GglError ret; + GglObject *component_name; + if (!ggl_map_get(*recipe_map, GGL_STR("ComponentName"), &component_name)) { + return GGL_ERR_INVALID; + } + if (component_name->type != GGL_TYPE_BUF) { + return GGL_ERR_INVALID; + } + + // build the working directory string + ret = ggl_byte_vec_append( + working_dir_vec, ggl_buffer_from_null_term(args->root_dir) + ); + ggl_byte_vec_chain_append(&ret, working_dir_vec, GGL_STR("/work/")); + ggl_byte_vec_chain_append(&ret, working_dir_vec, component_name->buf); + if (ret != GGL_ERR_OK) { + return ret; + } + + return GGL_ERR_OK; +} + +static GglError concat_exec_start_section_vec( const GglMap *recipe_map, - GglByteVec *script_name_prefix_vec, - GglByteVec *working_dir_vec, GglByteVec *exec_start_section_vec, GglObject **component_name, Recipe2UnitArgs *args @@ -257,26 +317,7 @@ static GglError concat_initial_strings( } GglBuffer component_version = component_version_obj->buf; - // build the script name prefix string - ret = ggl_byte_vec_append(script_name_prefix_vec, (*component_name)->buf); - ggl_byte_vec_chain_append( - &ret, script_name_prefix_vec, GGL_STR(".script.") - ); - if (ret != GGL_ERR_OK) { - return ret; - } - - // build the working directory string - ret = ggl_byte_vec_append( - working_dir_vec, ggl_buffer_from_null_term(args->root_dir) - ); - ggl_byte_vec_chain_append(&ret, working_dir_vec, GGL_STR("/work/")); - ggl_byte_vec_chain_append(&ret, working_dir_vec, (*component_name)->buf); - if (ret != GGL_ERR_OK) { - return ret; - } - - // build the working directory string + // build the path for ExecStart section in unit file ret = ggl_byte_vec_append( exec_start_section_vec, (GglBuffer) { .data = (uint8_t *) args->recipe_runner_path, @@ -384,99 +425,6 @@ static GglError update_unit_file_buffer( return GGL_ERR_OK; } -static GglError parse_install_section( - GglMap selected_lifecycle_map, - GglMap set_env_as_map, - char *root_dir, - GglMap *out_install_map, - GglAlloc *allocator -) { - GglObject *install_section; - if (ggl_map_get( - selected_lifecycle_map, GGL_STR("install"), &install_section - )) { - if (install_section->type != GGL_TYPE_MAP) { - GGL_LOGE("install section isn't formatted correctly"); - return GGL_ERR_INVALID; - } - - GglBuffer selected_script = { 0 }; - bool is_root = false; - GglError ret = fetch_script_section( - selected_lifecycle_map, - GGL_STR("install"), - &is_root, - &selected_script, - &set_env_as_map - ); - if (ret != GGL_ERR_OK) { - GGL_LOGE("Cannot parse install script section"); - return GGL_ERR_FAILURE; - } - static uint8_t mem[PATH_MAX]; - GglByteVec socketpath_vec = GGL_BYTE_VEC(mem); - ret = ggl_byte_vec_append( - &socketpath_vec, - (GglBuffer) { (uint8_t *) root_dir, strlen(root_dir) } - ); - ggl_byte_vec_chain_append( - &ret, &socketpath_vec, GGL_STR("/gg-ipc.socket") - ); - - GglObject out_object = GGL_OBJ_MAP(GGL_MAP( - { GGL_STR("requiresprivilege"), GGL_OBJ_BOOL(is_root) }, - { GGL_STR("script"), GGL_OBJ_BUF(selected_script) }, - { GGL_STR("set_env"), GGL_OBJ_MAP(set_env_as_map) }, - { GGL_STR("AWS_GG_NUCLEUS_DOMAIN_SOCKET_FILEPATH_FOR_COMPONENT"), - GGL_OBJ_BUF(socketpath_vec.buf) } - )); - - ret = ggl_obj_deep_copy(&out_object, allocator); - if (ret != GGL_ERR_OK) { - return ret; - } - *out_install_map = out_object.map; - - } else { - GGL_LOGI("No install section found within the recipe"); - } - return GGL_ERR_OK; -} - -static GglError create_standardized_install_file( - GglByteVec script_name_prefix_vec, - GglMap standardized_install_map, - char *root_dir -) { - static uint8_t json_buf[MAX_SCRIPT_SIZE]; - GglBuffer install_json_payload = GGL_BUF(json_buf); - GglError ret = ggl_json_encode( - GGL_OBJ_MAP(standardized_install_map), &install_json_payload - ); - if (ret != GGL_ERR_OK) { - GGL_LOGE("Failed to encode JSON."); - return ret; - } - - static uint8_t script_name_buf[PATH_MAX - 1]; - GglByteVec script_name_vec = GGL_BYTE_VEC(script_name_buf); - ret = ggl_byte_vec_append(&script_name_vec, script_name_prefix_vec.buf); - ggl_byte_vec_chain_append(&ret, &script_name_vec, GGL_STR("install.json")); - if (ret != GGL_ERR_OK) { - GGL_LOGE("Failed to append script details to vector."); - return GGL_ERR_FAILURE; - } - - ret = write_to_file( - root_dir, script_name_vec.buf, install_json_payload, 0600 - ); - if (ret != GGL_ERR_OK) { - GGL_LOGE("Failed to create and write the script file."); - return ret; - } - return GGL_ERR_OK; -} - // TODO: Refactor it // NOLINTNEXTLINE(readability-function-cognitive-complexity) static GglError manifest_builder( @@ -484,7 +432,8 @@ static GglError manifest_builder( GglByteVec *out, GglByteVec script_name_prefix_vec, GglByteVec exec_start_section_vec, - Recipe2UnitArgs *args + Recipe2UnitArgs *args, + PhaseSelection current_phase ) { bool is_root = false; @@ -517,71 +466,61 @@ static GglError manifest_builder( GGL_LOGI("Setenv section not found within the linux lifecycle"); } - static uint8_t big_buffer_for_bump[MAX_SCRIPT_SIZE + PATH_MAX]; - GglBumpAlloc the_allocator - = ggl_bump_alloc_init(GGL_BUF(big_buffer_for_bump)); - GglMap standardized_install_map = { 0 }; - ret = parse_install_section( - selected_lifecycle_map, - set_env_as_map, - args->root_dir, - &standardized_install_map, - &the_allocator.alloc - ); - if (ret != GGL_ERR_OK) { - return ret; - } - - ret = create_standardized_install_file( - script_name_prefix_vec, standardized_install_map, args->root_dir - ); - if (ret != GGL_ERR_OK) { - GGL_LOGE("Failed to create standardized install file."); - return ret; - } - //**************************************************************** // Note: Everything below this should only deal with run or startup // **************************************************************** GglBuffer lifecycle_script_selection = { 0 }; GglObject *startup_or_run_section; - if (ggl_map_get( - selected_lifecycle_map, - GGL_STR("startup"), - &startup_or_run_section - )) { - if (startup_or_run_section->type == GGL_TYPE_LIST) { - GGL_LOGE("startup is a list type"); - return GGL_ERR_INVALID; - } - lifecycle_script_selection = GGL_STR("startup"); - ret = ggl_byte_vec_append( - out, GGL_STR("RemainAfterExit=true\n") - ); + + if (current_phase == INSTALL) { + lifecycle_script_selection = GGL_STR("install"); ggl_byte_vec_chain_append(&ret, out, GGL_STR("Type=oneshot\n")); if (ret != GGL_ERR_OK) { GGL_LOGE("Failed to add unit type information"); return GGL_ERR_FAILURE; } - - } else if (ggl_map_get( - selected_lifecycle_map, - GGL_STR("run"), - &startup_or_run_section - )) { - if (startup_or_run_section->type == GGL_TYPE_LIST) { - GGL_LOGE("'run' field in the lifecycle is of List type."); - return GGL_ERR_INVALID; - } - lifecycle_script_selection = GGL_STR("run"); - ret = ggl_byte_vec_append(out, GGL_STR("Type=exec\n")); - if (ret != GGL_ERR_OK) { - GGL_LOGE("Failed to add unit type information"); - return GGL_ERR_FAILURE; + } else if (current_phase == RUN_STARTUP) { + if (ggl_map_get( + selected_lifecycle_map, + GGL_STR("startup"), + &startup_or_run_section + )) { + if (startup_or_run_section->type == GGL_TYPE_LIST) { + GGL_LOGE("Startup is a list type"); + return GGL_ERR_INVALID; + } + lifecycle_script_selection = GGL_STR("startup"); + ret = ggl_byte_vec_append( + out, GGL_STR("RemainAfterExit=true\n") + ); + ggl_byte_vec_chain_append( + &ret, out, GGL_STR("Type=oneshot\n") + ); + if (ret != GGL_ERR_OK) { + GGL_LOGE("Failed to add unit type information"); + return GGL_ERR_FAILURE; + } + + } else if (ggl_map_get( + selected_lifecycle_map, + GGL_STR("run"), + &startup_or_run_section + )) { + if (startup_or_run_section->type == GGL_TYPE_LIST) { + GGL_LOGE("'run' field in the lifecycle is of List type." + ); + return GGL_ERR_INVALID; + } + lifecycle_script_selection = GGL_STR("run"); + ret = ggl_byte_vec_append(out, GGL_STR("Type=exec\n")); + if (ret != GGL_ERR_OK) { + GGL_LOGE("Failed to add unit type information"); + return GGL_ERR_FAILURE; + } + } else { + GGL_LOGI("No startup or run provided"); + return GGL_ERR_OK; } - } else { - GGL_LOGI("No startup or run provided"); - return GGL_ERR_OK; } GglBuffer selected_script = { 0 }; @@ -593,12 +532,7 @@ static GglError manifest_builder( &set_env_as_map ); if (ret != GGL_ERR_OK) { - GGL_LOGE( - "Cannot parse %.*s script section", - (int) lifecycle_script_selection.len, - lifecycle_script_selection.data - ); - return GGL_ERR_FAILURE; + return ret; } static uint8_t script_name_buf[PATH_MAX - 1]; @@ -612,7 +546,6 @@ static GglError manifest_builder( if (ret != GGL_ERR_OK) { return GGL_ERR_FAILURE; } - ret = write_to_file( args->root_dir, script_name_vec.buf, selected_script, 0755 ); @@ -643,14 +576,18 @@ static GglError manifest_builder( return GGL_ERR_OK; } -static GglError fill_install_section(GglByteVec *out) { - GglError ret = ggl_byte_vec_append(out, GGL_STR("\n[Install]\n")); - ggl_byte_vec_chain_append( - &ret, out, GGL_STR("WantedBy=multi-user.target\n") - ); - if (ret != GGL_ERR_OK) { - GGL_LOGE("Failed to set Install section to unit file"); - return ret; +static GglError fill_install_section( + GglByteVec *out, PhaseSelection current_phase +) { + if (current_phase != INSTALL) { + GglError ret = ggl_byte_vec_append(out, GGL_STR("\n[Install]\n")); + ggl_byte_vec_chain_append( + &ret, out, GGL_STR("WantedBy=multi-user.target\n") + ); + if (ret != GGL_ERR_OK) { + GGL_LOGE("Failed to set Install section to unit file"); + return ret; + } } return GGL_ERR_OK; @@ -660,7 +597,8 @@ static GglError fill_service_section( const GglMap *recipe_map, GglByteVec *out, Recipe2UnitArgs *args, - GglObject **component_name + GglObject **component_name, + PhaseSelection phase ) { GglError ret = ggl_byte_vec_append(out, GGL_STR("[Service]\n")); if (ret != GGL_ERR_OK) { @@ -685,17 +623,21 @@ static GglError fill_service_section( GglByteVec script_name_prefix_vec = GGL_BYTE_VEC(script_name_prefix_buf); ret = ggl_byte_vec_append(&script_name_prefix_vec, GGL_STR("ggl.")); - ret = concat_initial_strings( - recipe_map, - &script_name_prefix_vec, - &working_dir_vec, - &exec_start_section_vec, - component_name, - args + ret = concat_script_name_prefix_vec(recipe_map, &script_name_prefix_vec); + if (ret != GGL_ERR_OK) { + GGL_LOGE("Script Name String prefix concat failed."); + return ret; + } + ret = concat_working_dir_vec(recipe_map, &working_dir_vec, args); + if (ret != GGL_ERR_OK) { + GGL_LOGE("Working directory String prefix concat failed."); + return ret; + } + ret = concat_exec_start_section_vec( + recipe_map, &exec_start_section_vec, component_name, args ); - if (ret != GGL_ERR_OK) { - GGL_LOGE("String concat failed."); + GGL_LOGE("ExctStart String prefix concat failed."); return ret; } @@ -712,7 +654,7 @@ static GglError fill_service_section( ret = ggl_dir_open(working_dir_vec.buf, O_PATH, true, &working_dir); if (ret != GGL_ERR_OK) { GGL_LOGE("Failed to created working directory."); - return GGL_ERR_FAILURE; + return ret; } GGL_CLEANUP(cleanup_close, working_dir); @@ -735,7 +677,12 @@ static GglError fill_service_section( } ret = manifest_builder( - *recipe_map, out, script_name_prefix_vec, exec_start_section_vec, args + *recipe_map, + out, + script_name_prefix_vec, + exec_start_section_vec, + args, + phase ); if (ret != GGL_ERR_OK) { return ret; @@ -748,13 +695,14 @@ GglError generate_systemd_unit( const GglMap *recipe_map, GglBuffer *unit_file_buffer, Recipe2UnitArgs *args, - GglObject **component_name + GglObject **component_name, + PhaseSelection phase ) { GglByteVec concat_unit_vector = { .buf = { .data = unit_file_buffer->data, .len = 0 }, - .capacity = unit_file_buffer->len }; + .capacity = MAX_UNIT_SIZE }; - GglError ret = fill_unit_section(*recipe_map, &concat_unit_vector); + GglError ret = fill_unit_section(*recipe_map, &concat_unit_vector, phase); if (ret != GGL_ERR_OK) { return ret; } @@ -765,17 +713,16 @@ GglError generate_systemd_unit( } ret = fill_service_section( - recipe_map, &concat_unit_vector, args, component_name + recipe_map, &concat_unit_vector, args, component_name, phase ); if (ret != GGL_ERR_OK) { return ret; } - ret = fill_install_section(&concat_unit_vector); + ret = fill_install_section(&concat_unit_vector, phase); if (ret != GGL_ERR_OK) { return ret; } - *unit_file_buffer = concat_unit_vector.buf; return GGL_ERR_OK; } diff --git a/recipe2unit/src/unit_file_generator.h b/recipe2unit/src/unit_file_generator.h index bb72cb22e..a77b5a469 100644 --- a/recipe2unit/src/unit_file_generator.h +++ b/recipe2unit/src/unit_file_generator.h @@ -10,11 +10,17 @@ #include #include +typedef enum { + INSTALL, + RUN_STARTUP +} PhaseSelection; + GglError generate_systemd_unit( const GglMap *recipe_map, GglBuffer *unit_file_buffer, Recipe2UnitArgs *args, - GglObject **component_name + GglObject **component_name, + PhaseSelection phase ); #endif From 143f6b0a318b0077ec96104684cd63b2f9559d9d Mon Sep 17 00:00:00 2001 From: Felicity Date: Thu, 31 Oct 2024 00:18:02 +0000 Subject: [PATCH 10/13] Nit fix for ci checks --- recipe2unit-test/src/entry.c | 2 ++ recipe2unit/src/parser.c | 9 +++++++++ recipe2unit/src/unit_file_generator.c | 3 --- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/recipe2unit-test/src/entry.c b/recipe2unit-test/src/entry.c index b75546e7e..61dbd9817 100644 --- a/recipe2unit-test/src/entry.c +++ b/recipe2unit-test/src/entry.c @@ -5,12 +5,14 @@ #include "ggl/recipe2unit.h" #include "recipe2unit-test.h" #include +#include #include #include #include #include #include #include +#include #include // For the testing purpose, move the sample recipe.yml to /run/packages/recipes diff --git a/recipe2unit/src/parser.c b/recipe2unit/src/parser.c index a2cbe0169..92713f00e 100644 --- a/recipe2unit/src/parser.c +++ b/recipe2unit/src/parser.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -112,6 +113,10 @@ GglError convert_to_unit( ret = create_unit_file( args, component_name, &install_response_buffer, is_install ); + if (ret != GGL_ERR_OK) { + GGL_LOGE("Failed to create the install unit file."); + return ret; + } } ret = generate_systemd_unit( @@ -130,6 +135,10 @@ GglError convert_to_unit( ret = create_unit_file( args, component_name, &run_startup_response_buffer, is_install ); + if (ret != GGL_ERR_OK) { + GGL_LOGE("Failed to create the run or startup unit file."); + return ret; + } } return GGL_ERR_OK; diff --git a/recipe2unit/src/unit_file_generator.c b/recipe2unit/src/unit_file_generator.c index b4cae87ba..c6bfb97e4 100644 --- a/recipe2unit/src/unit_file_generator.c +++ b/recipe2unit/src/unit_file_generator.c @@ -6,13 +6,10 @@ #include "file_operation.h" #include "ggl/recipe2unit.h" #include -#include #include -#include #include #include #include -#include #include #include #include From 1ae78be21e06077eb3d07fe77a2246bf05f3d817 Mon Sep 17 00:00:00 2001 From: Anubhav Rawal Date: Thu, 31 Oct 2024 02:59:59 +0000 Subject: [PATCH 11/13] Fix merge error --- recipe2unit/src/parser.c | 4 ++-- recipe2unit/src/unit_file_generator.c | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/recipe2unit/src/parser.c b/recipe2unit/src/parser.c index fbaf58051..c05b1a7b2 100644 --- a/recipe2unit/src/parser.c +++ b/recipe2unit/src/parser.c @@ -112,7 +112,7 @@ GglError convert_to_unit( } else { is_install = true; ret = create_unit_file( - args, component_name, &install_response_buffer, is_install + args, component_name, is_install,&install_response_buffer ); if (ret != GGL_ERR_OK) { GGL_LOGE("Failed to create the install unit file."); @@ -135,7 +135,7 @@ GglError convert_to_unit( } else { is_install = false; ret = create_unit_file( - args, component_name, &run_startup_response_buffer, is_install + args, component_name, is_install,&run_startup_response_buffer ); if (ret != GGL_ERR_OK) { GGL_LOGE("Failed to create the run or startup unit file."); diff --git a/recipe2unit/src/unit_file_generator.c b/recipe2unit/src/unit_file_generator.c index 17ad29d5a..cbd45dd4f 100644 --- a/recipe2unit/src/unit_file_generator.c +++ b/recipe2unit/src/unit_file_generator.c @@ -29,10 +29,6 @@ #define MAX_RETRIES_INTERVAL_SECONDS "3600" #define RETRY_DELAY_SECONDS "1" -static GglError select_linux_manifest( - GglMap recipe_map, GglObject *val, GglMap *out_selected_lifecycle_map -); - static GglError concat_script_name_prefix_vec( const GglMap *recipe_map, GglByteVec *script_name_prefix_vec ); From ced1c421e88b989667ec16b75a3403597430d39c Mon Sep 17 00:00:00 2001 From: Anubhav Rawal Date: Thu, 31 Oct 2024 03:00:42 +0000 Subject: [PATCH 12/13] Fix format --- recipe2unit/src/parser.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/recipe2unit/src/parser.c b/recipe2unit/src/parser.c index c05b1a7b2..7a8c9abc8 100644 --- a/recipe2unit/src/parser.c +++ b/recipe2unit/src/parser.c @@ -85,7 +85,7 @@ GglError convert_to_unit( // Note: currently, if we have both run and startup phases, // we will only select startup for the script and service file static uint8_t install_unit_file_buffer[MAX_UNIT_FILE_BUF_SIZE]; - + static uint8_t run_startup_unit_file_buffer[MAX_UNIT_FILE_BUF_SIZE]; GglBuffer install_response_buffer = (GglBuffer) { .data = (uint8_t *) install_unit_file_buffer, @@ -112,13 +112,12 @@ GglError convert_to_unit( } else { is_install = true; ret = create_unit_file( - args, component_name, is_install,&install_response_buffer + args, component_name, is_install, &install_response_buffer ); if (ret != GGL_ERR_OK) { GGL_LOGE("Failed to create the install unit file."); return ret; } - } ret = generate_systemd_unit( @@ -135,7 +134,7 @@ GglError convert_to_unit( } else { is_install = false; ret = create_unit_file( - args, component_name, is_install,&run_startup_response_buffer + args, component_name, is_install, &run_startup_response_buffer ); if (ret != GGL_ERR_OK) { GGL_LOGE("Failed to create the run or startup unit file."); From f0e6062b2a752fba7081565bb027d1bccc36461e Mon Sep 17 00:00:00 2001 From: Anubhav Rawal Date: Thu, 31 Oct 2024 03:31:19 +0000 Subject: [PATCH 13/13] Add support for all field in recipe2unit --- ggl-recipe/src/recipe.c | 15 +++++++-------- recipe2unit/src/unit_file_generator.c | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/ggl-recipe/src/recipe.c b/ggl-recipe/src/recipe.c index 6353de7ac..9c3d3fc38 100644 --- a/ggl-recipe/src/recipe.c +++ b/ggl-recipe/src/recipe.c @@ -131,7 +131,8 @@ static GglError manifest_selection( // Check if the current OS supported first if ((strncmp((char *) os->buf.data, "linux", os->buf.len) == 0 - || strncmp((char *) os->buf.data, "*", os->buf.len) == 0)) { + || strncmp((char *) os->buf.data, "*", os->buf.len) == 0) + || strncmp((char *) os->buf.data, "all", os->buf.len) == 0) { // Then check if architecture is also supported if (((architecture_obj == NULL) || (architecture_obj->buf.len == 0) @@ -202,13 +203,11 @@ GglError select_linux_manifest( return ret; } - if (selected_lifecycle_object == NULL) { - GGL_LOGE("No lifecycle was found for linux"); - return GGL_ERR_FAILURE; - } - // If a lifecycle is successfully selected then look no futher - if (selected_lifecycle_object->type == GGL_TYPE_MAP) { - break; + if (selected_lifecycle_object != NULL) { + // If a lifecycle is successfully selected then look no futher + if (selected_lifecycle_object->type == GGL_TYPE_MAP) { + break; + } } } diff --git a/recipe2unit/src/unit_file_generator.c b/recipe2unit/src/unit_file_generator.c index cbd45dd4f..adb124d6b 100644 --- a/recipe2unit/src/unit_file_generator.c +++ b/recipe2unit/src/unit_file_generator.c @@ -232,7 +232,7 @@ static GglError fetch_script_section( return GGL_ERR_INVALID; } } else { - GGL_LOGE( + GGL_LOGW( "%.*s section is not in the lifecycle", (int) selected_phase.len, selected_phase.data