libmpm

morphux C package management library
Log | Files | Refs | Submodules | README | LICENSE | git clone https://git.ne02ptzero.me/git/libmpm

commit 2c3a24109826d37c731fe645f26d8dd0a6995be2
parent 7a592241995aa1de6cfaeee9aa55fc9d1d73c1b3
Author: Ne02ptzero <louis@ne02ptzero.me>
Date:   Wed, 31 May 2017 19:15:58 +0200

Work(Errors): Better errors in lib

Diffstat:
Minc/compile.h | 14++++++++++++--
Minc/error.h | 6+++++-
Minc/packer.h | 2++
Asrc/\ | 290+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/compile.c | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Msrc/error.c | 28++++++++++++++--------------
6 files changed, 386 insertions(+), 38 deletions(-)

diff --git a/inc/compile.h b/inc/compile.h @@ -36,7 +36,8 @@ typedef enum { INST_STATE_INSTALLATION, INST_STATE_AFTER, INST_STATE_DB, - INST_STATE_DONE + INST_STATE_DONE, + INST_STATE_LAST } install_state_t; typedef struct compile_s { @@ -133,6 +134,15 @@ bool after_package(compile_t *ctx); * * \return true on success, false on failure */ -bool install_archive(packer_t *ctx); +bool install_archive(packer_t *ctx, compile_t *ptr); + +/*! + * \brief install_state_t to human readable string + * + * \param num Install state + * + * \return String + */ +const char *install_state_to_str(install_state_t num); #endif /* COMPILE_H */ diff --git a/inc/error.h b/inc/error.h @@ -20,7 +20,7 @@ # include <morphux.h> # define ERROR_MAX_LEN 250 -# define SET_ERR_STR(num, str) [num] = str +# define __SET_ERR_STR(num, str) [num] = str typedef enum u32_t { /* No Error */ @@ -88,10 +88,14 @@ const char *mpm_strerror(mpm_error_t err_num); * \note Support printf format */ void mpm_set_str_error(const char *str, ...); +# define SET_ERR_STR_FMT(format, ...) mpm_set_str_error(format, __VA_ARGS__) +# define SET_ERR_STR(format) mpm_set_str_error(format) + /*! * \brief Get an error string, previously set */ char *mpm_get_str_error(void); +# define GET_ERR_STR() mpm_get_str_error() #endif diff --git a/inc/packer.h b/inc/packer.h @@ -98,6 +98,8 @@ typedef struct packer_header_s { packer_header_deps_t *dependencies; /*!< Package dependencies */ } packer_header_t; +#define __pkg_name header->package->name + typedef struct packer_s { char *str; /*!< Directory, or path of the package */ json_object *json; /*!< JSON object */ diff --git a/src/\ b/src/\ @@ -0,0 +1,290 @@ +/*********************************** LICENSE **********************************\ +* Copyright 2017 Morphux * +* * +* Licensed under the Apache License, Version 2.0 (the "License"); * +* you may not use this file except in compliance with the License. * +* You may obtain a copy of the License at * +* * +* http://www.apache.org/licenses/LICENSE-2.0 * +* * +* Unless required by applicable law or agreed to in writing, software * +* distributed under the License is distributed on an "AS IS" BASIS, * +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * +* See the License for the specific language governing permissions and * +* limitations under the License. * +\******************************************************************************/ + +#include <compile.h> + +compile_t *package_install_init(packer_t *ctx) { + compile_t *ret = NULL; + packer_conf_opt_t *opt = NULL; + mlist_t *tmp = NULL; + + ret = malloc(sizeof(*ret)); + if (ret == NULL) + { + SET_ERR(ERR_MEMORY); + return NULL; + } + + ret->package = ctx; + ret->state = INST_STATE_NONE; + + getcwd(ret->old_pwd, sizeof(ret->old_pwd)); + if (chdir(ctx->out_dir) != 0) + { + free(ret); + SET_ERR(ERR_CHDIR_FAILED); + SET_ERR_STR("Cannot enter directory %s", ctx->out_dir); + return NULL; + } + if (ctx->header->compilation->env == NULL) + return ret; + + list_for_each(ctx->header->compilation->env, tmp, opt) + { + if (opt->name != NULL) + setenv(opt->value, opt->name, 1); + else + setenv(opt->value, "", 1); + } + + return ret; +} + +bool package_install_cleanup(compile_t *ctx) { + if (chdir(ctx->old_pwd) != 0) + { + SET_ERR(ERR_CHDIR_FAILED); + SET_ERR_STR("Cannot enter directory %s", ctx->old_pwd); + return false; + } + + packer_free(ctx->package); + free(ctx); + return true; +} + +bool before_package(compile_t *ctx) { + if (file_exist(COMP_BEFORE_SCRIPT) == false) + goto end; + + if (exec_line("sh " COMP_BEFORE_SCRIPT) != 0) + { + SET_ERR(ERR_EXEC_FAILED); + SET_ERR_STR("Execution failed for '%s'", "sh " COMP_BEFORE_SCRIPT); + return false; + } + +end: + ctx->state = INST_STATE_BEFORE; + return true; +} + +bool patch_package(compile_t *ctx) { + DIR *dir = opendir(PACKER_PATCH_DIR); + struct dirent *dinfo = NULL; + char *cmd = NULL; + bool status = false; + + /* Nothing to patch, we're good */ + if (dir == NULL) + return true; + + if (chdir(PACKER_SRC_DIR) == -1) + { + SET_ERR(ERR_CHDIR_FAILED); + goto end; + } + + while ((dinfo = readdir(dir))) + { + /* Skip .* files */ + if (strlen(dinfo->d_name) > 0 && dinfo->d_name[0] == '.') + continue ; + + if (dinfo->d_type != DT_DIR) + { + asprintf(&cmd, "%s ../%s%s", PATCH_CMD, PACKER_PATCH_DIR, dinfo->d_name); + if (exec_line(cmd) != 0) + { + SET_ERR(ERR_EXEC_FAILED); + free(cmd); + goto end; + } + free(cmd); + } + } + + if (chdir("..") == -1) + { + SET_ERR(ERR_CHDIR_FAILED); + goto end; + } + + status = true; +end: + closedir(dir); + ctx->state = INST_STATE_PATCHING; + return status; +} + +bool configure_package(compile_t *ctx) { + mlist_t *cmd = NULL, *tmp; + packer_conf_opt_t *opt; + char *arg = NULL; + bool ret = false; + + /* Nothing to configure, we're good */ + if (ctx->package->header->compilation->configure == NULL) + { + ret = true; + goto end; + } + + if (chdir(PACKER_SRC_DIR) == -1) + { + SET_ERR(ERR_CHDIR_FAILED); + goto end; + } + + list_add(cmd, CONFIGURE_CMD, sizeof(CONFIGURE_CMD) + 1); + + list_for_each(ctx->package->header->compilation->configure, tmp, opt) { + if (opt->name != NULL) + asprintf(&arg, "--%s=%s", opt->name, opt->value); + else + asprintf(&arg, "--%s", opt->value); + list_add(cmd, arg, strlen(arg) + 1); + free(arg); + } + + if (exec_list(cmd) == 0) + ret = true; + else + SET_ERR(ERR_EXEC_FAILED); + + list_free(cmd, NULL); + + chdir(".."); + +end: + ctx->state = INST_STATE_CONFIGURATION; + return ret; +} + +bool make_package(compile_t *ctx) { + bool status = true; + + /* Nothing to compile, we're good */ + if (STR_NULL_OR_EMPTY(ctx->package->header->compilation->make)) + goto end; + + if (chdir(PACKER_SRC_DIR)) + { + SET_ERR(ERR_CHDIR_FAILED); + return false; + } + + if (exec_line(ctx->package->header->compilation->make) != 0) + { + SET_ERR(ERR_EXEC_FAILED); + status = false; + } + + chdir(".."); + +end: + ctx->state = INST_STATE_COMPILATION; + return status; +} + +bool install_package(compile_t *ctx) { + bool status = true; + + /* Nothing to install, we're good */ + if (STR_NULL_OR_EMPTY(ctx->package->header->compilation->install)) + goto end; + + if (chdir(PACKER_SRC_DIR)) + { + SET_ERR(ERR_CHDIR_FAILED); + return false; + } + + if (exec_line(ctx->package->header->compilation->install) != 0) + { + SET_ERR(ERR_EXEC_FAILED); + status = false; + } + + chdir(".."); + +end: + ctx->state = INST_STATE_INSTALLATION; + return status; +} + +bool after_package(compile_t *ctx) { + if (file_exist(COMP_AFTER_SCRIPT) == false) + goto end; + + if (exec_line("sh " COMP_AFTER_SCRIPT) != 0) + { + SET_ERR(ERR_EXEC_FAILED); + return false; + } + +end: + ctx->state = INST_STATE_AFTER; + return true; +} + +bool install_archive(packer_t *ctx) { + bool ret = false; + compile_t *ptr = NULL; + + if (packer_extract_archive(ctx, DEFAULT_EXTRACT_DIR) == false) + { + packer_free(ctx); + SET_ERR(ERR_ARCHIVE_EXTRACT); + return ret; + } + + ptr = package_install_init(ctx); + if (ptr == NULL) + { + SET_ERR(ERR_MEMORY); + recursive_delete(ctx->out_dir); + packer_free(ctx); + return ret; + } + + if (before_package(ptr) == false) + goto end; + + if (patch_package(ptr) == false) + goto end; + + if (configure_package(ptr) == false) + goto end; + + if (make_package(ptr) == false) + goto end; + + if (install_package(ptr) == false) + goto end; + + if (after_package(ptr) == false) + goto end; + + ret = true; + +end: + if (ret != true) + SET_ERR(ERR_INSTALLATION_FAILED); + recursive_delete(ctx->out_dir); + package_install_cleanup(ptr); + return ret; +} diff --git a/src/compile.c b/src/compile.c @@ -16,6 +16,26 @@ #include <compile.h> +static const char *g_install_states_str[] = { + __SET_ERR_STR(INST_STATE_NONE, "None"), + __SET_ERR_STR(INST_STATE_BEFORE, "Before script"), + __SET_ERR_STR(INST_STATE_PATCHING, "Patching"), + __SET_ERR_STR(INST_STATE_CONFIGURATION, "Configuration"), + __SET_ERR_STR(INST_STATE_COMPILATION, "Compilation"), + __SET_ERR_STR(INST_STATE_INSTALLATION, "Installation"), + __SET_ERR_STR(INST_STATE_AFTER, "After scripts"), + __SET_ERR_STR(INST_STATE_DB, "Database operations"), + __SET_ERR_STR(INST_STATE_DONE, "Done") +}; + +const char *install_state_to_str(install_state_t num) { + const char *ret = NULL; + + if (num >= 0 && num < INST_STATE_LAST) + ret = g_install_states_str[num]; + return ret; +} + compile_t *package_install_init(packer_t *ctx) { compile_t *ret = NULL; packer_conf_opt_t *opt = NULL; @@ -24,7 +44,7 @@ compile_t *package_install_init(packer_t *ctx) { ret = malloc(sizeof(*ret)); if (ret == NULL) { - set_mpm_error(ERR_MEMORY); + SET_ERR(ERR_MEMORY); return NULL; } @@ -35,7 +55,8 @@ compile_t *package_install_init(packer_t *ctx) { if (chdir(ctx->out_dir) != 0) { free(ret); - set_mpm_error(ERR_MEMORY); + SET_ERR(ERR_CHDIR_FAILED); + SET_ERR_STR_FMT("Cannot enter directory '%s'", ctx->out_dir); return NULL; } if (ctx->header->compilation->env == NULL) @@ -55,7 +76,8 @@ compile_t *package_install_init(packer_t *ctx) { bool package_install_cleanup(compile_t *ctx) { if (chdir(ctx->old_pwd) != 0) { - set_mpm_error(ERR_CHDIR_FAILED); + SET_ERR(ERR_CHDIR_FAILED); + SET_ERR_STR_FMT("Cannot enter directory '%s'", ctx->old_pwd); return false; } @@ -70,7 +92,8 @@ bool before_package(compile_t *ctx) { if (exec_line("sh " COMP_BEFORE_SCRIPT) != 0) { - set_mpm_error(ERR_EXEC_FAILED); + SET_ERR(ERR_EXEC_FAILED); + SET_ERR_STR_FMT("Execution failed for '%s'", "sh " COMP_BEFORE_SCRIPT); return false; } @@ -91,7 +114,8 @@ bool patch_package(compile_t *ctx) { if (chdir(PACKER_SRC_DIR) == -1) { - set_mpm_error(ERR_CHDIR_FAILED); + SET_ERR(ERR_CHDIR_FAILED); + SET_ERR_STR_FMT("Cannot enter directory '%s'", PACKER_SRC_DIR); goto end; } @@ -106,7 +130,8 @@ bool patch_package(compile_t *ctx) { asprintf(&cmd, "%s ../%s%s", PATCH_CMD, PACKER_PATCH_DIR, dinfo->d_name); if (exec_line(cmd) != 0) { - set_mpm_error(ERR_EXEC_FAILED); + SET_ERR(ERR_EXEC_FAILED); + SET_ERR_STR_FMT("Execution failed for '%s'", cmd); free(cmd); goto end; } @@ -116,7 +141,8 @@ bool patch_package(compile_t *ctx) { if (chdir("..") == -1) { - set_mpm_error(ERR_CHDIR_FAILED); + SET_ERR(ERR_CHDIR_FAILED); + SET_ERR_STR("Cannot enter the directory '..'"); goto end; } @@ -142,7 +168,8 @@ bool configure_package(compile_t *ctx) { if (chdir(PACKER_SRC_DIR) == -1) { - set_mpm_error(ERR_CHDIR_FAILED); + SET_ERR(ERR_CHDIR_FAILED); + SET_ERR_STR_FMT("Cannot enter the directory '%s'", PACKER_SRC_DIR); goto end; } @@ -160,7 +187,10 @@ bool configure_package(compile_t *ctx) { if (exec_list(cmd) == 0) ret = true; else - set_mpm_error(ERR_EXEC_FAILED); + { + SET_ERR(ERR_EXEC_FAILED); + SET_ERR_STR_FMT("Execution failed for '%s'", cmd); + } list_free(cmd, NULL); @@ -180,13 +210,15 @@ bool make_package(compile_t *ctx) { if (chdir(PACKER_SRC_DIR)) { - set_mpm_error(ERR_CHDIR_FAILED); + SET_ERR(ERR_CHDIR_FAILED); + SET_ERR_STR_FMT("Cannot enter the directory '%s'", PACKER_SRC_DIR); return false; } if (exec_line(ctx->package->header->compilation->make) != 0) { - set_mpm_error(ERR_EXEC_FAILED); + SET_ERR(ERR_EXEC_FAILED); + SET_ERR_STR_FMT("Execution failed for '%s'", ctx->package->header->compilation->make); status = false; } @@ -206,13 +238,15 @@ bool install_package(compile_t *ctx) { if (chdir(PACKER_SRC_DIR)) { - set_mpm_error(ERR_CHDIR_FAILED); + SET_ERR(ERR_CHDIR_FAILED); + SET_ERR_STR_FMT("Cannot enter the directory '%s'", PACKER_SRC_DIR); return false; } if (exec_line(ctx->package->header->compilation->install) != 0) { - set_mpm_error(ERR_EXEC_FAILED); + SET_ERR(ERR_EXEC_FAILED); + SET_ERR_STR_FMT("Execution failed for '%s'", ctx->package->header->compilation->install); status = false; } @@ -229,7 +263,8 @@ bool after_package(compile_t *ctx) { if (exec_line("sh " COMP_AFTER_SCRIPT) != 0) { - set_mpm_error(ERR_EXEC_FAILED); + SET_ERR(ERR_EXEC_FAILED); + SET_ERR_STR_FMT("Execution failed for '%s'\n", "sh " COMP_BEFORE_SCRIPT); return false; } @@ -238,21 +273,21 @@ end: return true; } -bool install_archive(packer_t *ctx) { +bool install_archive(packer_t *ctx, compile_t *ptr) { bool ret = false; - compile_t *ptr = NULL; if (packer_extract_archive(ctx, DEFAULT_EXTRACT_DIR) == false) { + SET_ERR_STR("Cannot extract archive\n"); + SET_ERR(ERR_ARCHIVE_EXTRACT); packer_free(ctx); - set_mpm_error(ERR_ARCHIVE_EXTRACT); return ret; } ptr = package_install_init(ctx); if (ptr == NULL) { - set_mpm_error(ERR_MEMORY); + SET_ERR(ERR_MEMORY); recursive_delete(ctx->out_dir); packer_free(ctx); return ret; @@ -280,8 +315,15 @@ bool install_archive(packer_t *ctx) { end: if (ret != true) - set_mpm_error(ERR_INSTALLATION_FAILED); - recursive_delete(ctx->out_dir); - package_install_cleanup(ptr); + { + SET_ERR_STR_FMT("Installation failed at step: %s", + install_state_to_str(ptr->state)); + SET_ERR(ERR_INSTALLATION_FAILED); + } + else + { + recursive_delete(ctx->out_dir); + package_install_cleanup(ptr); + } return ret; } diff --git a/src/error.c b/src/error.c @@ -19,20 +19,20 @@ static u32_t g_error = ERR_NO_ERROR; static const char *g_str_errors[] = { - SET_ERR_STR(ERR_NO_ERROR, "No error"), - SET_ERR_STR(ERR_MEMORY, "Insufficient memory"), - SET_ERR_STR(ERR_BAD_PTR, "Bad pointer"), - SET_ERR_STR(ERR_CHDIR_FAILED, "Can't change directory"), - SET_ERR_STR(ERR_OPEN, "Can't open a file"), - SET_ERR_STR(ERR_MKDIR_FAILED, "Can't create a directory"), - SET_ERR_STR(ERR_EXEC_FAILED, "A binary execution failed"), - SET_ERR_STR(ERR_ARCHIVE_EXTRACT, "An archive extraction failed"), - SET_ERR_STR(ERR_BAD_ARCHIVE_TYPE, "Bad archive type"), - SET_ERR_STR(ERR_NOT_A_PACKAGE, "File is not a Morphux package"), - SET_ERR_STR(ERR_INSTALLATION_FAILED, "An installation failed"), - SET_ERR_STR(ERR_BAD_CONFIG, "Bad configuration"), - SET_ERR_STR(ERR_BAD_JSON, "JSON file wrongly formatted"), - SET_ERR_STR(ERR_BAD_JSON_TYPE, "Unexecpted JSON type") + __SET_ERR_STR(ERR_NO_ERROR, "No error"), + __SET_ERR_STR(ERR_MEMORY, "Insufficient memory"), + __SET_ERR_STR(ERR_BAD_PTR, "Bad pointer"), + __SET_ERR_STR(ERR_CHDIR_FAILED, "Can't change directory"), + __SET_ERR_STR(ERR_OPEN, "Can't open a file"), + __SET_ERR_STR(ERR_MKDIR_FAILED, "Can't create a directory"), + __SET_ERR_STR(ERR_EXEC_FAILED, "A binary execution failed"), + __SET_ERR_STR(ERR_ARCHIVE_EXTRACT, "An archive extraction failed"), + __SET_ERR_STR(ERR_BAD_ARCHIVE_TYPE, "Bad archive type"), + __SET_ERR_STR(ERR_NOT_A_PACKAGE, "File is not a Morphux package"), + __SET_ERR_STR(ERR_INSTALLATION_FAILED, "An installation failed"), + __SET_ERR_STR(ERR_BAD_CONFIG, "Bad configuration"), + __SET_ERR_STR(ERR_BAD_JSON, "JSON file wrongly formatted"), + __SET_ERR_STR(ERR_BAD_JSON_TYPE, "Unexecpted JSON type") }; static char g_str_error[ERROR_MAX_LEN] = "";